Development record
Old Lifeboats Still Unpack
Press Release
abcd reads lifeboats produced by older releases. When you embark from a lifeboat created with an older abcd version, abcd detects the schema delta and migrates internal structures automatically — your old lifeboats keep working without re-disembarking. If a lifeboat is too old to migrate cleanly, abcd refuses with a clear "re-disembark required" message and a one-line command to do it.
"We had lifeboats archived from six months ago," said Dave, compliance lead. "I expected them to be obsolete. abcd just unpacked them — and warned me about the two fields that had moved."
Why This Matters
abcd stamps schema_version: 1 on every lifeboat artefact (meta.json, config.json, _provenance.json, etc.) but ships no migrators initially — premature to write migrators before there is a schema change to migrate from. The moment a schema change ships, lifeboats produced under the prior schema risk becoming silently incompatible.
This intent commits abcd to taking lifeboat portability seriously: schemas evolve, but old lifeboats stay valuable. Either we migrate them forward, or we tell users explicitly what's needed to refresh.
What's In Scope
- Schema versioning convention across all lifeboat JSON artefacts
- Per-schema migrators (e.g.,
1 → 2for any field that changed) embarkdetection of schema version + auto-migration- "Re-disembark required" failure mode with explicit command suggestion
- Migration log captured in
embark-report.{json,md}
What's Out of Scope
- Migrating lifeboat content (principles, press releases) — only structural schema
- Two-way compatibility (older abcd reading newer-schema lifeboats — not supported)
- Migration tools for in-flight
.abcd/work/working artefacts (covered separately if needed)
Acceptance Criteria
BDD format, per
itd-1-acceptance-gates. These gates are checked byintent-fidelity-reviewerwhen this intent moves toshipped/.
- Given a lifeboat produced by an older abcd version with
schema_version: 1on every JSON artefact, when the user runs/abcd:embark from <path>, then embark detects the schema delta, runs the registered migrators, unpacks the lifeboat into the target repo, and writes a migration log toembark-report.{json,md}listing each schema upgrade applied. - Given a lifeboat too old to migrate cleanly (e.g. its schema is below the lowest registered migrator's source version), when embark runs, then the command refuses with a "re-disembark required" error AND the error message includes the exact one-line command the user should run on the source repo (e.g.,
/abcd:disembark pack <source> <dest>). - Given a newer-schema lifeboat, when an older abcd binary tries to embark from it, then the binary fails fast with a "lifeboat is from a newer abcd version; upgrade abcd to embark this lifeboat" message — two-way compatibility is explicitly not supported and the failure mode is clear.
- Given a successful migration during embark, when the migration log is written, then it records: source schema version, target schema version, list of migrators applied (in order), per-artefact field changes, and any non-fatal warnings.
- Given the registered v1→v2 migrator, when it runs against a v1 artefact, then it produces a v2 artefact that round-trips cleanly through the v2 schema validator (no unknown fields, no missing required fields, all enums valid).
- Given a lifeboat is migrated during embark, when the resulting
~/.abcd.noindex/voyage/<source-root-sha>/embark/provenance.json(the operator-level voyage store adr-35 moved it to) is written, then it records the migration history (was_schema: 1,now_schema: 2,migrators_applied: [...]) so future audits can reconstruct what was changed.
SOTA
Surveyed on 2026-10-23; sources, evidence tiers and the local fit risks are in the harness, interop and lifeboats SOTA note.
- The repository already carries seven independent schema versions (
probe.goSchemaVersion = 2,EmbarkSchemaVersion,GraveyardSchemaVersion,LessonsSchemaVersion,PrinciplesSchemaVersion = 2,PressReleaseSchemaVersion,ReviewSchemaVersion) and refuses newer-than-known; no reader accepts an older revision yet. - Upcasters are the read-time pattern: Axon stores a revision with each event, an upcaster maps revision x to x+1, upcasters chain, and the store is never rewritten ("the complete event history remains intact"). A lifeboat is immutable in the same sense: migrate on read, never in place.
- Kubernetes states the rule and the storage split: conversion is "a star with the internal form at the center", "it must be possible to round-trip your change … with no loss of information", adding a field with a sane default needs no new version, and a new version should not become preferred and stored in one release so a rollback still decodes. Its round trip serves an API server that converts both ways; abcd's chain is one-way (newer-than-known refused), so the half that applies is that each up-step loses no information.
- Protobuf's field discipline: never change or reuse a field number, reserve removed numbers and names, old readers "simply ignore the new field".
- Go's decoder ignores unknown keys by default and
DisallowUnknownFieldsmakes them an error; the lifeboat readers choose the error on purpose (graveyard_lessons.gocalls it to "reject smuggled extra fields" and refuses anyschema_versionbut its own), so Fowler's Tolerant Reader applies here only in bounded form: accept an older revision's known fields and default the missing ones, while unknown keys stay refused where a reader refuses them today; Parallel Change (expand, migrate, contract) is the writer's half.
Path 2 — native per-artefact upcaster chains shaped to Axon's revision model, with Kubernetes' no-information-loss rule applied to each one-way up-step (no downcasters, since newer-than-known stays refused): bounded tolerance per artefact as the first rung (an older revision's known fields accepted and missing ones defaulted, unknown keys still refused where the reader refuses them today, the lessons reader's smuggled-field guard among them), one single-step migrator per revision beside its artefact type, the lifeboat on disk untouched, "re-disembark required" when the chain has no step starting at the artefact's revision, the voyage store's provenance recording each step. The independent fit-challenge runs at plan time.
Open Questions
- Which schema version delta triggers re-disembark vs auto-migrate? Major-version bumps only?
- Where do migrators live in the native layout?
- Should
_provenance.jsonrecord the migration history (was-v1, now-v2)? - (SOTA 2026-10-23) Should the probe's "is its schema version one this build understands" and embark's check be one function before any migrator lands?
Audit Notes
Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/.
Frontmatter
| id | itd-9 |
|---|---|
| type | intent |
| lifecycle | drafts |
| kind | standalone |
| severity | major |
.abcd/development/intents/drafts/itd-9-schema-migration.md
open on GitHub ↗ · commit history ↗
Referenced by3
- iss-2610262044045987itd-8 leaves adding code to old lifeboats to itd-9; itd-9 migrates structural schema only and excludes lifeboat contentrelated
- itd-16`/abcd:audit` Is the Umbrella; Conversation/Edit Chain Is Its Default Applicationbuilt on by
- itd-35Lifeboats Carry Their Own Integrity Proofbuilt on by
mentions12
- adr-35The lifeboat is a coverage experiment — read-only, out-of-tree, and proven before it is packed (supersedes adr-4)
- adr-47abcdev.app is rendered from this repository alone
- iss-94The intent corpus still specifies the pre-adr-35 lifeboat model: itd-2, itd-8, itd-9, itd-10, itd-13, itd-15, itd-19, itd-22 and itd-24 variously use the retired 'disembark to home' signature, the in-tree .abcd/lifeboat/ home, or the in-tree .abcd/development/voyage/ path (itd-9's acceptance writes voyage provenance in-tree — the exact path that would fail abcd's own privacy-hygiene audit rule). The brief, glossary and roadmap were reconciled to adr-35; the intents were deliberately NOT rewritten, because an intent is a proposal with its own lifecycle and silently rewriting nine of them inside an unrelated change is worse than tracking the drift. Each reconciles when it is next planned.
- iss-2609081941074556releaseOf stamps the homepage feature block by strings.Contains of the record id against each CHANGELOG line, with no word boundary, walking newest dated section first. A short id therefore inherits a longer one: on ec7f40d6 releaseOf(itd-9) returns 0.4.1 off the itd-93 credit and releaseOf(itd-1) returns 0.7.1 off itd-130, and a future superstring landing in a newer section restamps the featured id. site check does not validate the stamp. The same package already carries bodyHandleRe. Fix: match the record id at a word boundary (reuse bodyHandleRe, or split the line into tokens); newest-section-first can stay. Detector: a changelog whose newer dated section mentions itd-1990 must not stamp featured itd-199, while a line naming itd-199 as its own id still matches. Independent of the Audit Notes rollup scanner. Reported as GitHub issue 624 against ec7f40d6. <!-- record-lint: illustrative -->
- iss-261104055420878706-capture.md:296 says every refusal of a ledger verb's own input exits 2, naming a malformed id and a flag value naming nothing, on promoting among others, and leaves exit 1 to a fault. abcd capture promote exits 1 on capture promote bad, on capture promote <iss-N> --intent itd-9 (not in the intent store, nothing stamped), and on a second promote of a promoted issue (06-capture.md:549 lists that as a refusal). A malformed id exits 2 on resolve and defer, and an unknown iss-N exits 2 on promote.
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Them
- itd-8Lifeboats Carry Source Code, Not Just Lessons
- itd-29Domain Experts Run A Spec Autonomously And Recover From Anything Without Touching Git
- itd-88Know What a Repo Can and Cannot Tell You — Before You Trust the Lifeboat
- itd-139Carol's team adopts abcd and gets a readable record the next day, without writing a line of site code
- itd-140The Generic/Specific Boundary of the Site Generator Is a Gate, Not a Hope
- spc-3lifeboat-coverage-experiment