CRUMB a card from devarno-cloud

Draft Isolation Rule (FM-07)

grace intermediate 5 min read

ELI5

Stable things should not depend on unstable things. A finished cookbook can’t cite a recipe still being scribbled. Draft isolation enforces that wall: only drafts import drafts, only stable imports stable, with a thin bridge for review.

Technical Deep Dive

Source: packages/schema/src/lifecycle.ts:129-173, packages/schema/src/validate.ts:76-90, packages/graph/src/protect.ts.

Status Compatibility Matrix

importer_status allowed to import imported_status:

Importer ↓ \ Imported →draftreviewapprovedpublishedactivedeprecated
draftyesnonononono
reviewyesyesnononono
approvednonoyesyesyesno
publishednonoyesyesyesno
activenonoyesyesyesno
deprecatednonoyesyesyesno
archivednononononono
tombstonedn/a (no imports allowed at all)
tamperedn/a (cannot be imported by anything)

Decision Flow

flowchart TD
A[importer + imported pair] --> B{importer status}
B -->|draft| C{imported = draft?}
B -->|review| D{imported in draft, review?}
B -->|approved/published/active| E{imported in approved+?}
B -->|deprecated| F{imported in approved+?}
B -->|archived| G[no new imports allowed]
B -->|tombstoned| H[no imports]
B -->|tampered| I[cannot import or be imported]
C -->|yes| J[OK]
C -->|no| K[FM-07 warning]
D -->|yes| J
D -->|no| K
E -->|yes| J
E -->|no| K
F -->|yes| J
F -->|no| K
G --> K
style K fill:#fef3c7

Validate vs Graph

  • validate.ts:76-90 does a coarse 0.x.x vs 1.x.x semver check — published+ (1.x.x+) cannot import draft (0.x.x).
  • lifecycle.ts:129-173 (canImport) does the full status-pair check at the graph level, where statuses are known.

Why Warning, Not Blocking

A unit promoted from draft to approved without simultaneously promoting its draft dependencies is a real refactor in progress. FM-07 surfaces the drift without halting the build, letting authors batch promotions.

Tampered & Tombstoned

  • A tampered unit cannot be imported by anything — the digest mismatch breaks SPEC-02 trust.
  • A tombstoned unit is irreversibly deleted; no further imports of any status are possible.

Key Terms

  • Approved+ → The set {approved, published, active}; mutually importable.
  • Deprecated importing → Allowed to import approved+ (so deprecated units can keep working) but cannot regress to importing drafts.
  • 0.x.x convention → Semver major-zero range conventionally used for draft units; stable starts at 1.0.0.

Q&A

Q: Can a review unit import a draft unit? A: Yes. Review is the bridge state — it must be able to pull in drafts to evolve, but cannot expose them upward to approved consumers.

Q: Can a deprecated unit import a published unit? A: Yes. Deprecation freezes the unit’s outgoing surface to stable dependencies — it doesn’t sever existing approved+ links.

Q: What happens if I add a new import to an archived unit? A: FM-07 fires. Archived units cannot accept new imports of any status; they are frozen by definition.

Examples

A dev/task/intake-parse@0.4.0 (draft) is imported by dev/chain/sol-1-boot@1.0.0 (published). validate.ts coarse check fires immediately (1.x.x importing 0.x.x). lifecycle.canImport(published, draft) returns false. FM-07 warning lands in stratt ci output. Fix: bump intake-parse to 1.0.0 (gate-required review→approved) before promoting the chain.

neighbors on the map