@sdlc-on-fire/storage
Reads and writes work-item Markdown. 21 exports, 6 files, one dependency (yaml). Small on purpose: it is the only sanctioned writer, so everything it does is a rule everything else inherits.
Internal package, prerelease
0.1.0-alpha.0. Published sosdlc-on-fireinstalls resolve. No stability guarantee before0.1.0— exports move and disappear between alphas. The supported surface is thesdlc-on-fireCLI.
Two guarantees, and they live nowhere else
Nothing reaches disk without validating against the object model. A file that would fail WorkItemSchema is refused before it is written, not discovered later by whatever tries to read it.
A work item at a terminal stage is never edited in place. The check reads the frontmatter about to be overwritten, not the incoming object:
import { writeWorkItem } from '@sdlc-on-fire/storage';
// TASK-001 is on disk with lifecycle_state: done
await writeWorkItem(path, { ...item, lifecycleState: 'implement' });
// → throws: refuses to write a terminal item
That ordering is the whole guarantee. An agent that sets lifecycle_state: implement on a finished task does not thereby unlock it — the incoming object is what is being checked, so it cannot also be the thing that authorises the check.
Writing a finished item at all requires verifiable grounds — an approved insertion whose blast radius reaches it, or an attestation that its own evidence contradicts the claim — and even then only operational fields may move. The body must come through byte-identical, which is checked rather than asked for.
Frontmatter round-trips
import { parseFrontmatter, serializeFrontmatter } from '@sdlc-on-fire/storage';
const { data, body } = parseFrontmatter(await fs.readFile(file, 'utf8'));
Key order and formatting survive a read/write cycle, so a tool-written file does not produce a diff against a hand-written one that says the same thing.
Licence
MIT.