diff --git a/docs/BEARING.md b/docs/BEARING.md
index 791daa29..ce239209 100644
--- a/docs/BEARING.md
+++ b/docs/BEARING.md
@@ -1,6 +1,6 @@
# BEARING
-Updated at cycle boundaries. Not mid-cycle.
+Updated at cycle boundaries and before the final commit of each v18 slice.
Scope note:
@@ -12,64 +12,73 @@ Scope note:
- For later-major horizon planning, use
[release-horizon-v20-v21.md](design/release-horizon-v20-v21.md).
+## Continuum Optic Admission Posture
+
+For cross-repo optic admission, git-warp is a complete Continuum participant,
+not an Echo runtime surrogate. Continuum is the protocol for exchanging
+witnessed causal history. Wesley compiles artifacts and descriptors, Echo
+admits Echo-local runtime invocations, git-warp admits git-warp-local causal
+history and readings, authority layers issue grants, and applications hide
+handles and basis references behind product adapters.
+
## Where are we
-`git-warp` is executing the v17 release-blocker DAG. The current work is
-not a broad RuntimeHost rewrite; it is one bounded release blocker at a
-time, with the DAG status and SVG kept current after each completed
-cycle.
+`git-warp` has shipped `v17.0.0`. The release work is now behind us in
+repo history, npm, and JSR; the active direction is `v18.0.0`.
+
+The v18 hill is not generic graph-model cleanup. It is Continuum
+compatibility:
+
+> Make `git-warp` a Continuum-compatible sibling WARP runtime: consume
+> Wesley-generated artifacts for Continuum-owned contract families, map
+> git-warp's append-only Git-backed causal history into honest WARP Optic
+> evidence, and
+> give `warp-ttd` generated-family facts instead of handwritten adapter
+> folklore.
+
+The long-term compatibility target is the WARP Optic shape described in
+`~/git/blog/aion-paper-07/dist/aion-paper-07.txt`, plus the Continuum
+contract families authored in `~/git/continuum/schemas/` and compiled by
+Wesley. Echo and `git-warp` are sibling runtime implementations. `git-warp`
+has its own Continuum role, and it must not emit Continuum-shaped values as
+native Continuum witnesses until that witnesshood is actually proven.
+
+Backlog fold-in: the repo-visible v18 lane is
+`WL-4A-v18-graph-substrate-convergence` in
+[WORKLOADS.md](method/backlog/WORKLOADS.md), backed by the eight notes in
+[method/backlog/v18.0.0](method/backlog/v18.0.0/). Treat that lane as the
+graph-model track inside this compatibility campaign: node and edge record
+identity, attachment slots, graph-op algebra, content cutover, legacy property
+projection, migration tooling, and genesis replay equivalence. Existing
+`echo-shaped` backlog identities are historical shorthand for graph-model
+pressure already exercised by Echo, not a claim that Echo owns `git-warp`'s
+Continuum role.
Current branch state at this boundary:
-- Branch: `release/v17.0.0`
-- Push state: local branch remains ahead of `origin/release/v17.0.0`;
- push only after explicit approval.
-- DAG map:
- [0124-v17-release-blocker-dag.md](design/0124-v17-release-blocker-dag.md)
+- Branch: `codex/v18-continuum-opening`
+- Release tag: `v17.0.0`
+- Latest remote head inspected: `origin/main` at `5afdd3eb`
+- Latest package version: `17.0.0`
- Latest closed cycle:
- `0144-release-preflight-and-rc`
-- Latest full unit gate shape:
- `npm run test:local` is green with `438` files and `6771` tests.
-- Latest validation shape:
- lint, anti-sludge shell checks, source/test typecheck, consumer
- typecheck, markdown lint, markdown code-sample lint, high-level npm
- audit, release preflight, and whitespace diff checks are green at this
- boundary.
-
-The current release ladder remains:
-
-- `v17.0.0`: TypeScript migration, public API honesty,
- materialization-frontdoor deletion, readings/optics direction, and
- query read-model groundwork
-- `v18.0.0`: graph substrate convergence
+ `0145-push-pr-review-merge`
+
+The release ladder is now:
+
+- `v17.0.0`: shipped TypeScript migration, public API honesty,
+ materialization-frontdoor deletion, readings/optics direction, and query
+ read-model groundwork.
+- `v18.0.0`: Continuum/WARP Optic compatibility for git-warp as an independent
+ Continuum participant, through Wesley-generated contract-family artifacts and
+ honest evidence posture.
- `v19.0.0`: observation, doctrine, and slice-first runtime convergence
- `v20.0.0`: slice-first read execution
- `v21.0.0`: distributed observer geometry and admission reality
-Recent work narrowed v17 honestly, removed public materialization
-frontdoor docs, fixed runtime read guidance, made checkpoint schema `5`
-the single runtime checkpoint contract, removed the checkpoint, patch,
-subscription, and sync controller private materialization dependencies,
-retired stale materialize-spy expectations, pinned default observer
-readings, and aligned remaining checkpoint/materialize unit tests with
-the current checkpoint contract, and replaced plain sync HMAC credential
-flow with an opaque `SyncSecret`. The sync server now fails closed for
-non-local unauthenticated serving and requires an explicit unsafe option
-for unauthenticated localhost serving. It also applies per-key token-bucket
-rate limiting for configured sync auth and requires an explicit rate-limit
-budget for non-local enforced sync auth. The package upgrade command now has
-a real checkpoint upgrade path for retired checkpoint envelopes. Unexpected
-HTTP sync `500` responses are now sanitized to `E_SYNC_INTERNAL`, with
-internal details kept in structured logs.
-
-The runtime is still partially state-first in important places. The
-important current truth is narrow: the non-security `test:local` blockers
-from the v17 materialization cleanup and the direct sync security hardening
-nodes are closed. File-level anti-sludge quarantines are also graduated, and
-the full gate matrix is green, and the release cut/version/changelog node is
-closed. Final local release preflight is also green. The remaining blocker is
-release coordination: push, PR, review, green CI, and an explicit merge
-decision.
+The v18 compatibility work is bigger than ten slices. The first ten slices are
+the opening campaign. Slice 11 is an explicit re-plan point after the repo has
+real evidence from generated artifact ingestion, evidence posture, and the
+first receipt-family projection.
## Invariants
@@ -109,80 +118,71 @@ mapping, and concrete checks live in `docs/invariants/`.
## What just shipped
-Cycles `0132-subscription-controller-reading-basis` through
-`0144-release-preflight-and-rc`:
-
-- Removed `_materializeGraph()` from subscription/watch and sync
- controller read paths.
-- Made default sync metadata-only unless callers explicitly request
- `materialize: true`.
-- Rewrote stale auto-materialize and materialize-spy tests around the v17
- reading-basis contract.
-- Pinned default `graph.observer()` reads to the caller's fresh reading
- basis.
-- Aligned remaining checkpoint/materialize tests with schema `5` or
- explicit retired-schema upgrade rejection.
-- Added `SyncSecret` so sync auth secrets redact in string, JSON, and
- inspect output while still signing HMAC requests.
-- Hardened sync serve defaults: non-local bind hosts require enforced
- auth, and local unauthenticated serving must opt into unsafe localhost
- mode.
-- Added per-key token-bucket sync auth rate limiting and required explicit
- `auth.rateLimit` for non-local enforced sync hosts.
-- Sanitized unexpected HTTP sync `500` responses and routed internal error
- detail through `LoggerPort`.
-- Graduated the anti-sludge file-level quarantine manifests to empty
- `files` lists and narrowed remaining legacy hits to owning-cycle inline
- suppressions.
-- Recorded the full gate matrix green after quarantine graduation.
-- Cut the v17.0.0 changelog section for May 5 and aligned the release note with
- the honest 0123 bounded-query scope.
-- Cleared the local release preflight from a clean commit. The hard preflight
- repairs landed in `bdafca51`, and the final preflight reports all hard checks
- passed.
-- Brought `npm run test:local` back to green.
-- Marked `PORT_subscription-controller-reading-basis`,
- `PORT_sync-controller-reading-basis`,
- `SPEC_materialize-spy-test-clusters`,
- `SPEC_observer-coordinate-pinning`, and
- `SPEC_checkpoint-materialize-test-drift` complete in the DAG, then
- marked `HEX_sync-secret-plain-string` and
- `HEX_sync-production-auth-defaults` complete, then marked
- `HEX_sync-no-rate-limiting`, `HEX_sync-500-sanitization`, and
- `REL_quarantine-graduate-clean`, then
- `REL_full-gate-matrix-green`, then
- `REL_release-cut-version-changelog`, then
- `REL_release-preflight-and-rc` complete.
+`v17.0.0` shipped and was followed by release hardening:
+
+- The v17 release branch landed through PR #84.
+- Follow-up repair and package migration work landed through PR #85.
+- Release hardening landed through PR #86.
+- The final v17 coverage ratchet landed through PR #87; the signed
+ `v17.0.0` tag points at that merge.
+- npm publish recovery landed through PR #88.
+- PR #89 simplified the README model sentence after the release line.
+
+The shipped v17 scope remains: TypeScript migration, public API honesty,
+materialization-frontdoor deletion, readings/optics direction, query
+read-model groundwork, sync hardening, release gates, and package publishing.
## What feels wrong
-- v17 is still not releasable until the branch is pushed, reviewed, green in
- CI, and explicitly approved for merge.
-- `REL_push-pr-review-merge` is now the open node.
- The release preflight fix lowered the coverage ratchet to the measured
full-suite v17 line baseline `91.74%`; this is tracked as v19 bad-code debt
in `SPEC_coverage-ratchet-baseline-drop.md`.
-- Broader historical version-suffixed substrate names still exist in
- `src/`; the checkpoint upgrade slice removed the touched checkpoint and
- migration names only.
-- The branch remains local-only relative to origin; pushing is a separate
- release/coordination decision.
+- v18 can easily turn into adapter folklore if `git-warp` hand-authors local
+ mirrors of Continuum-owned families instead of consuming Wesley-generated
+ artifacts.
+- v18 can also lie in the other direction: Continuum-shaped values are not
+ Continuum-native witnesses unless the runtime has actually proven native
+ witnesshood. Initial git-warp compatibility evidence should be treated as
+ translated git-warp evidence until stronger proof exists.
+- The v18 backlog already names a graph-model convergence lane. The plan must
+ fold that lane into Continuum compatibility instead of replacing it with a
+ parallel cross-repo adapter plan.
+- `warp-ttd` needs git-warp facts as generated-family nouns, but the existing
+ ecosystem still contains handwritten adapter and protocol residue.
## What comes next
-Continue executing the DAG one open node at a time.
-
-Recommended next pull:
-
-- `REL_push-pr-review-merge`
-
-Why:
-
-- It is open.
-- The full gate matrix, release cut, and local preflight are green.
-- The branch is still local-only relative to origin.
-- Merge must remain gated on review, green CI, and explicit human approval.
-
-Keep the loop strict: write the cycle doc, capture RED, green the slice,
-update changelog/DAG/SVG/retro, validate, commit, then pull the next open
-node.
+Run the v18 opening campaign. Update this task list at the end of each slice,
+before the final commit for that slice, and mark completed items with `- [x]`.
+
+## Running Task List
+
+- [x] 1. Sync and clean the repo runway: fast-forward `main`, clear fsmonitor
+ noise, close stale v17/0145 bookkeeping, and record the v18 starting point.
+- [x] 2. Create the v18 Continuum compatibility charter: WARP Optic
+ compatibility, Continuum contract-family compatibility, Wesley-generated
+ artifact consumption, and `warp-ttd` acceptance.
+- [x] 3. Build the cross-repo contract matrix: Continuum family to Wesley
+ generated artifact to git-warp source fact to `warp-ttd` consumer need,
+ with `WL-4A-v18-graph-substrate-convergence` folded in as the graph-model
+ track.
+- [x] 4. Define git-warp's WARP Optic realization map: observer plan, bounded
+ slice, lowering surface, admissibility law, and retention contract.
+- [x] 5. Add a generated-artifact ingestion path for Continuum families, with a
+ guard against handwritten local mirrors becoming contract authority.
+- [ ] 6. Make evidence posture explicit: translated git-warp evidence first,
+ native Continuum evidence only after native witnesshood is proven.
+- [ ] 7. Prove the patch commit visibility contract: success means canonical
+ writer-tip advancement and visible graph truth, not just object creation.
+- [ ] 8. Add the same-writer concurrent patch race witness with final-frontier
+ and visible-state assertions.
+- [ ] 9. Project git-warp receipt facts into the generated Continuum
+ receipt-family shape with conformance tests.
+- [ ] 10. Add the first `warp-ttd` smoke over generated-family git-warp receipt
+ facts instead of handwritten adapter-local receipt folklore.
+- [ ] 11. Re-plan with evidence in hand before expanding into reading-envelope,
+ suffix/runtime-boundary, neighborhood-core, and settlement-family slices.
+
+The loop stays strict: write or update the cycle doc, capture RED, green the
+slice, update this BEARING task list before the final commit, validate, then
+commit only the files touched in that slice.
diff --git a/docs/VISION.md b/docs/VISION.md
index dc41296c..8b4bf682 100644
--- a/docs/VISION.md
+++ b/docs/VISION.md
@@ -60,13 +60,14 @@ The read-side correction now matters just as much as the admission-side one:
- Observer-first read surfaces through worldlines and apertures
- Decentralized sync through Git transport
-In other words: `git-warp` owns the cold causal substrate and the lawful
-read/folding surfaces over it. It should not have to pretend that a giant
-in-memory graph is the ontology.
+In other words: `git-warp` is a complete Continuum participant for witnessed
+causal history, append-only Git-backed persistence, and lawful read/folding
+surfaces. It should not have to pretend that a giant in-memory graph is the
+ontology.
## What git-warp does not own
-- Hot deterministic execution → Echo
+- Echo's runtime-local deterministic execution → Echo
- Time-travel debugging UI → warp-ttd
- Shared schemas and contract surfaces → Wesley
- Application domain semantics → yours
@@ -87,10 +88,11 @@ Sync is just `git push` / `git fetch` of WARP refs.
## The Continuum horizon
-When used in the wider stack, `git-warp` is the cold causal substrate.
-The Continuum vision (Paper VII §5) reframes processes as strands
-whose live realization is a shadow working set over shared machine
-history:
+When used in the wider stack, `git-warp` and Echo are sibling Continuum
+participants. Continuum is the protocol for exchanging witnessed causal
+history, not a runtime hierarchy. The Continuum vision (Paper VII §5) reframes
+processes as strands whose live realization is a shadow working set over
+shared machine history:
- **Ephemeral scratch** — local, weakly retained, disposable
- **Author-only speculative lane** — durable, replayable, sealed
diff --git a/docs/design/0124-v17-release-blocker-dag.dot b/docs/design/0124-v17-release-blocker-dag.dot
index 8cf1b28b..db782657 100644
--- a/docs/design/0124-v17-release-blocker-dag.dot
+++ b/docs/design/0124-v17-release-blocker-dag.dot
@@ -150,8 +150,10 @@ digraph V17ReleaseBlockers {
penwidth=2.4
];
"REL_push-pr-review-merge" [
- fillcolor="#fee2e2",
- label="OPEN\nREL_push / PR\nreview / merge"
+ color="#15803d",
+ fillcolor="#bbf7d0",
+ label="DONE\nREL_push / PR\nreview / merge",
+ penwidth=2.4
];
"SPEC_docs-materialize-frontdoor-drift" -> "SPEC_runtime-error-reading-basis-guidance";
diff --git a/docs/design/0124-v17-release-blocker-dag.md b/docs/design/0124-v17-release-blocker-dag.md
index 2ae27f38..e081b0c2 100644
--- a/docs/design/0124-v17-release-blocker-dag.md
+++ b/docs/design/0124-v17-release-blocker-dag.md
@@ -164,8 +164,9 @@ closure. A blank cell means "not directly blocked by that task," not
documented runbook warning.
`REL_push-pr-review-merge`
-: Open. Push the branch, open or update the release PR, get review and green
- CI, and merge only after explicit approval.
+: Closed in cycle 0145. The release branch was pushed, reviewed, repaired,
+ merged, tagged, and published. Follow-up hardening and npm publish recovery
+ also landed on `main`.
## Excluded From v17 Blockers
@@ -180,9 +181,9 @@ substrate convergence are also excluded from this release-blocker graph.
## Current Open Front
-The tasks with no direct blockers are:
+There are no open v17 release-blocker nodes.
-- `REL_push-pr-review-merge`
+The v17 DAG is closed.
`SPEC_consumer-typecheck-materialize-residue` closed in cycle 0125.
`SPEC_docs-materialize-frontdoor-drift` closed in cycle 0126 and unlocks
@@ -208,7 +209,8 @@ quarantine graduation. Quarantine graduation closed in cycle 0141,
opening the full gate matrix. The full gate matrix closed in cycle 0142,
opening release cut/version/changelog. Release cut/version/changelog closed in
cycle 0143, opening release preflight and RC. Release preflight and RC closed in
-cycle 0144, opening push, PR, review, and merge.
+cycle 0144, opening push, PR, review, and merge. Push, PR, review, merge, tag,
+and publish closed in cycle 0145.
## Regeneration
diff --git a/docs/design/0124-v17-release-blocker-dag.svg b/docs/design/0124-v17-release-blocker-dag.svg
index b49b6865..a87a246f 100644
--- a/docs/design/0124-v17-release-blocker-dag.svg
+++ b/docs/design/0124-v17-release-blocker-dag.svg
@@ -419,16 +419,16 @@
REL_push-pr-review-merge
-
-OPEN
+
+DONE
REL_push / PR
review / merge
REL_release-preflight-and-rc->REL_push-pr-review-merge
-
-
+
+
diff --git a/docs/design/0124-v17-release-blocker-status.csv b/docs/design/0124-v17-release-blocker-status.csv
index da7f0a0a..29afca4b 100644
--- a/docs/design/0124-v17-release-blocker-status.csv
+++ b/docs/design/0124-v17-release-blocker-status.csv
@@ -19,4 +19,4 @@ REL_quarantine-graduate-clean,complete,BND_checkpoint-schema-contract-drift;PORT
REL_full-gate-matrix-green,complete,SPEC_consumer-typecheck-materialize-residue;SPEC_docs-materialize-frontdoor-drift;SPEC_runtime-error-reading-basis-guidance;BND_checkpoint-schema-contract-drift;PORT_patch-controller-reading-basis;PORT_checkpoint-controller-reading-basis;PORT_subscription-controller-reading-basis;PORT_sync-controller-reading-basis;SPEC_materialize-spy-test-clusters;SPEC_observer-coordinate-pinning;SPEC_checkpoint-materialize-test-drift;SPEC_uniform-git-cas-upgrade-contract-drift;HEX_sync-no-rate-limiting;HEX_sync-500-sanitization;REL_quarantine-graduate-clean,,no,Closed by 0142 full gate matrix.
REL_release-cut-version-changelog,complete,REL_full-gate-matrix-green,,no,Closed by 0143 release cut/version/changelog.
REL_release-preflight-and-rc,complete,REL_release-cut-version-changelog,,no,Closed by 0144 release preflight and RC readiness.
-REL_push-pr-review-merge,incomplete,REL_release-preflight-and-rc,,yes,Open node; release preflight is green.
+REL_push-pr-review-merge,complete,REL_release-preflight-and-rc,,no,Closed by 0145 push PR review merge; v17 merged tagged and published.
diff --git a/docs/design/0145-push-pr-review-merge/push-pr-review-merge.md b/docs/design/0145-push-pr-review-merge/push-pr-review-merge.md
index efd3106e..b4f3b3db 100644
--- a/docs/design/0145-push-pr-review-merge/push-pr-review-merge.md
+++ b/docs/design/0145-push-pr-review-merge/push-pr-review-merge.md
@@ -1,11 +1,12 @@
---
cycle: 0145
task_id: REL_push-pr-review-merge
-status: Draft
+status: Complete
sponsors:
human: James
agent: Codex
started_at: 2026-05-05
+completed_at: 2026-05-21
release_home: v17.0.0
---
@@ -24,6 +25,21 @@ unless James explicitly says `YES`.
The release branch is visible on GitHub, represented by a PR against `main`,
and blocked only by external review, CI, or the explicit merge approval gate.
+## Closeout
+
+The coordination hill is closed in repo-visible history:
+
+- PR #84 merged the `release/v17.0.0` branch to `main`.
+- PR #85 landed v17 follow-up repair and package migration work.
+- PR #86 landed release publish hardening.
+- PR #87 finalized the v17 coverage ratchet and produced the signed
+ `v17.0.0` tag.
+- PR #88 recovered npm release publishing.
+- PR #89 landed the post-release README wording cleanup.
+
+The release branches have been pruned from `origin`, `origin/main` is at
+`5afdd3eb`, and `v17.0.0` is visible on npm and JSR.
+
## Playback Questions
1. Is `release/v17.0.0` pushed to `origin` at the current local commit?
@@ -139,11 +155,10 @@ Current evidence before implementation:
### Goldens
-- Local and remote branch tips match.
-- The PR body records the v17 scope, validation evidence, and the explicit
- non-merge gate.
-- The final release decision remains outside automation until James says
- `YES`.
+- `main` contains the release merge and follow-up release hardening.
+- The signed `v17.0.0` tag points at the final coverage-ratchet release merge.
+- npm and JSR both expose `17.0.0` as the latest package version.
+- The final release branches are no longer open remote work.
### Known Fails
diff --git a/docs/design/0146-v18-continuum-compatibility-charter/v18-continuum-compatibility-charter.md b/docs/design/0146-v18-continuum-compatibility-charter/v18-continuum-compatibility-charter.md
new file mode 100644
index 00000000..aa2a3993
--- /dev/null
+++ b/docs/design/0146-v18-continuum-compatibility-charter/v18-continuum-compatibility-charter.md
@@ -0,0 +1,152 @@
+---
+cycle: 0146
+task_id: V18_continuum_compatibility_charter
+status: Complete
+sponsors:
+ human: James
+ agent: Codex
+started_at: 2026-05-21
+completed_at: 2026-05-21
+release_home: v18.0.0
+---
+
+# V18 Continuum Compatibility Charter
+
+## Pull
+
+v17 made the current engine shippable. v18 must make `git-warp` compatible
+with the shared Continuum/WARP Optic stack as a complete sibling Continuum
+participant without collapsing it into Echo, Wesley, or `warp-ttd`.
+
+## Hill
+
+`git-warp` becomes a Continuum-compatible sibling WARP runtime:
+
+- it consumes Wesley-generated artifacts for Continuum-owned contract families;
+- it maps append-only Git history into honest WARP Optic evidence;
+- it exposes generated-family facts to `warp-ttd`;
+- it separates translated git-warp evidence from native Continuum witnesshood.
+
+## Source Artifacts
+
+- `~/git/blog/aion-paper-07/dist/aion-paper-07.txt`
+- `~/git/continuum/schemas/`
+- `~/git/continuum/docs/contract-family-registry.md`
+- `~/git/wesley/README.md`
+- `~/git/echo/docs/BEARING.md`
+- `~/git/warp-ttd/docs/BEARING.md`
+- [VISION.md](../../VISION.md)
+- [BEARING.md](../../BEARING.md)
+- [backlog/WORKLOADS.md](../../method/backlog/WORKLOADS.md)
+- [backlog/v18.0.0/README.md](../../method/backlog/v18.0.0/README.md)
+
+## Compatibility Law
+
+The target WARP Optic shape is:
+
+```text
+Psi = (Omega, chi, rho, Pi, Lambda)
+Lower_Psi(F*, P) = (R, W, theta)
+```
+
+For v18, `git-warp` should interpret that shape as a compatibility boundary:
+
+- `Omega`: observer/read discipline, basis, and emission posture;
+- `chi`: bounded frontier-relative support slice;
+- `rho`: append-only Git/CRDT lowering surface over patch chains;
+- `Pi`: admission law producing derived, plural, conflict, or obstruction
+ outcomes;
+- `Lambda`: retained replay, audit, transport, revelation, and reliance
+ obligations.
+
+This charter does not require one generic optic engine. It requires each
+published compatibility surface to say which part of the optic shape it
+implements and which evidence supports that claim.
+
+## Contract Families
+
+The first v18 compatibility families are the Continuum-authored families:
+
+- `receipt-family`
+- `settlement-family`
+- `neighborhood-core-family`
+- `runtime-boundary-family`
+
+Wesley is the compiler and artifact authority for these shared families.
+`git-warp` must consume generated artifacts or documented generated fixtures.
+Handwritten mirrors may exist only as temporary local adapters with explicit
+non-authority status.
+
+## Backlog Integration
+
+The repo-visible v18 backlog already names
+`WL-4A-v18-graph-substrate-convergence` as the first major workload. This
+charter folds that work into the Continuum campaign rather than replacing it.
+
+That workload contributes the graph-model track:
+
+- node and edge record identity;
+- attachment-plane substrate work;
+- graph-op algebra convergence;
+- content migration out of legacy property conventions;
+- property-bag reads reduced to projections;
+- graph-model migration tooling;
+- replay equivalence from genesis.
+
+The existing `PROTO_echo-shaped-*` task identities are retained as backlog
+history. In this charter, `echo-shaped` means graph-model pressure already
+exercised by Echo. It does not mean Echo owns `git-warp`'s Continuum role or
+defines `git-warp`'s participant obligations.
+
+## Evidence Posture
+
+The default posture for existing git-warp facts mapped into Continuum-family
+shapes is translated evidence. A value may be Continuum-shaped without being
+Continuum-native.
+
+`git-warp` may claim native Continuum witnesshood only after a runtime witness
+proves the value was produced through the corresponding Continuum family
+contract and not merely mapped from local git-warp facts.
+
+## Non-Goals
+
+- Do not make Echo the owner or authority for `git-warp`'s Continuum role.
+- Do not make `git-warp` a semantic owner for Continuum contract families.
+- Do not make `warp-ttd` hand-normalize git-warp facts into substitute shared
+ contracts.
+- Do not build a generic WARP Optic runtime before repeated concrete
+ compatibility cuts justify it.
+- Do not claim native Continuum witnesshood for translated git-warp evidence.
+
+## Acceptance
+
+The v18 opening campaign is on track when:
+
+- [ ] `BEARING.md` tracks the running v18 task list.
+- [x] A cross-repo contract matrix names each family, generated artifact, local
+ source fact, consumer, and missing witness.
+- [x] A WARP Optic realization map exists for `git-warp`.
+- [x] The repo can ingest at least one generated Continuum family artifact or
+ generated fixture.
+- [x] A guard prevents generated-family local mirrors from becoming hidden
+ authority.
+- [ ] The first receipt-family projection reaches `warp-ttd` without adapter
+ folklore.
+
+## SSJS Scorecard
+
+- Runtime-backed forms: green for this documentation slice; no runtime forms
+ introduced.
+- Boundary validation: green; the charter names generated artifacts as the
+ boundary authority.
+- Behavior ownership: green; Continuum owns shared semantics, Wesley compiles,
+ `git-warp` emits git-warp-local facts, and `warp-ttd` observes.
+- Message parsing: green; no behavior branches are introduced.
+- Ambient time or entropy: green; no runtime code introduced.
+- Fake shape trust or cast-cosplay: green; the charter explicitly rejects fake
+ native witnesshood.
+
+## Closeout
+
+This charter closes BEARING task 2 and defines the standard later v18 slices
+must satisfy before making stronger compatibility claims.
diff --git a/docs/design/0147-v18-continuum-contract-matrix/v18-continuum-contract-matrix.md b/docs/design/0147-v18-continuum-contract-matrix/v18-continuum-contract-matrix.md
new file mode 100644
index 00000000..5f68a4f7
--- /dev/null
+++ b/docs/design/0147-v18-continuum-contract-matrix/v18-continuum-contract-matrix.md
@@ -0,0 +1,110 @@
+---
+cycle: 0147
+task_id: V18_continuum_contract_matrix
+status: Complete
+sponsors:
+ human: James
+ agent: Codex
+started_at: 2026-05-21
+completed_at: 2026-05-21
+release_home: v18.0.0
+---
+
+# V18 Continuum Contract Matrix
+
+## Pull
+
+The v18 charter names the compatibility target. This slice names the actual
+contract families and the current proof gap for each one.
+
+## Hill
+
+`git-warp` can now point at a concrete matrix:
+
+- Continuum owns the shared family semantics.
+- Wesley compiles and witnesses generated family artifacts.
+- Echo and `git-warp` are sibling runtimes that may emit or consume conforming
+ values.
+- `warp-ttd` is the structured debugger/read-model consumer.
+- Existing `git-warp` facts are translated evidence until native Continuum
+ witnesshood is proven.
+
+## Evidence Snapshot
+
+The matrix below is based on these inspected local sources:
+
+| Repo | Head | Evidence |
+| --- | --- | --- |
+| Continuum | `01e0735` | `docs/contract-family-registry.md`, `schemas/*.graphql`, `wesley/profile/scopes.mjs` |
+| Wesley | `19b2c1c9` | `README.md`, `docs/architecture/continuum-minimum-shared-contract-surface.md` |
+| Echo | `b1d979d` | `docs/BEARING.md` |
+| `warp-ttd` | `0491be6` | `docs/BEARING.md`, `schemas/warp-ttd-protocol.graphql` |
+| `git-warp` | this branch | `docs/BEARING.md`, `src/domain/types/TickReceipt.ts`, `src/domain/types/DeliveryObservation.ts`, read/materialize capabilities |
+
+## Family Matrix
+
+| Family | Authored home | Wesley status | `git-warp` source facts | Primary `warp-ttd` need | Missing witness |
+| --- | --- | --- | --- | --- | --- |
+| `receipt-family` | `~/git/continuum/schemas/continuum-receipt-family.graphql` | `profiled`, `fixture-witnessed`; scope `receipt-family` checks cross-leg schema hash, TTD fixture shape, Echo fixture shape, boundary fixture, roundtrip vectors, and receipt/witness separation | `TickReceipt`, op outcomes, `DeliveryObservation`, audit receipt chains, materialize/provenance receipt collection | Receipt and delivery facts as generated-family nouns, not adapter-local summaries | Live `git-warp` receipt publication mapped through generated artifacts with translated evidence posture, then witnessed as native only after a Continuum runtime witness exists |
+| `settlement-family` | `~/git/continuum/schemas/continuum-settlement-family.graphql` | `profiled`, `fixture-witnessed`; scope `settlement-family` checks cross-leg coherence and settlement boundary fixtures | Patch diffs, conflict traces, merge/conflict analysis, strand/braid conflict artifacts, writer frontier state | Import/settlement explanation for cross-runtime history and merge inspection | Live settlement values from `git-warp` suffix/import or merge flows, plus generated-artifact conformance |
+| `neighborhood-core-family` | `~/git/continuum/schemas/continuum-neighborhood-core-family.graphql` | `authored`; not yet profiled in the current Continuum Wesley scope list | Graph name, writer refs, worldline/frontier facts, local site-like participation facts still unnamed as a stable family | Neighborhood focus, participant catalog, and site navigation across Echo and `git-warp` targets | Wesley profile and fixture witness first; then `git-warp` participant values with explicit translated/native evidence status |
+| `runtime-boundary-family` | `~/git/continuum/schemas/continuum-runtime-boundary-family.graphql` | `authored`; not yet profiled in the current Continuum Wesley scope list | Materialize/read requests, observer/read basis, patch suffixes, frontiers, provenance refs, receipt collections, import outcomes still split across local APIs | Admission-chain read model: observer plans, reading envelopes, evidence posture, suffix shells, causal suffix bundles, import outcomes | Wesley profile, generated fixtures, and a live witnessed suffix exchange/admission proof between sibling runtimes |
+
+## Source-Fact Map
+
+| Continuum noun | Current `git-warp` anchor | Current posture |
+| --- | --- | --- |
+| `Receipt` | `TickReceipt`, audit receipts, receipt shards | Translated evidence; shape is not yet generated-family native |
+| `DeliveryObservation` | `DeliveryObservation` and effect sink observations | Local fact with strong name overlap; not yet Continuum family output |
+| `Witness` | checkpoint-tail witnesses, conflict witnesses, audit chain proofs | Local witness forms; no shared generated family surface yet |
+| `SettlementDelta` / `ConflictArtifact` | `PatchDiff`, conflict traces, merge/conflict services | Candidate source facts; missing shared generated settlement adapter |
+| `NeighborhoodCore` / `NeighborhoodParticipant` | graph name, writers, frontiers, worldline metadata | Candidate source facts; missing stable local site/participant object |
+| `ObserverPlan` / `ObservationRequest` | query/read basis, materialize options, traversal context | Candidate source facts; missing generated runtime-boundary profile |
+| `ReadingEnvelope` | materialize/query/read results plus provenance/receipt options | Candidate source facts; missing explicit evidence status wrapper |
+| `TranslatedSubstrateEvidence` | append-only Git-backed causal history, patch SHAs, writer refs, receipts | Correct initial evidence posture for compatibility outputs |
+| `WitnessedSuffixShell` / `CausalSuffixBundle` | writer patch chains, frontier maps, transport/sync suffixes | Candidate source facts; missing compact generated shell and admission witness |
+| `ImportOutcome` | sync/import/materialization outcomes and conflict posture | Candidate source facts; missing runtime-boundary family emission |
+
+## `warp-ttd` Consumer Matrix
+
+`warp-ttd`'s active bearing pressures these generated-family facts first:
+
+| `warp-ttd` target | Needed from `git-warp` | Contract-family lane |
+| --- | --- | --- |
+| Dual live app debugging | Read-only posture for a live `git-warp` target without host mutation | runtime-boundary-family |
+| Admission-chain read model | Artifact registration, evidence posture, receipts, witnesses, and reading envelopes as distinct facts | runtime-boundary-family, receipt-family |
+| Neighborhood and site catalog | Participant/site summaries that can compare Echo and `git-warp` targets | neighborhood-core-family |
+| Receipt shell summary | Generated-family receipt facts and delivery observations | receipt-family |
+| Merge and import inspection | Conflict artifacts, import candidates, settlement plans, and outcomes | settlement-family |
+
+## First Implementation Pressure
+
+The first implementation slice should not try to ingest every family. It should
+build a generated-artifact ingestion seam around one generated fixture family,
+then guard against hidden handwritten mirrors.
+
+Recommended order:
+
+1. Ingest or locally fixture the `receipt-family` generated artifact manifest.
+2. Reject local `git-warp` files that claim to be authoritative mirrors of
+ Continuum-owned families.
+3. Map `TickReceipt` and `DeliveryObservation` into a translated
+ `receipt-family` projection without claiming native Continuum witnesshood.
+4. Let `warp-ttd` consume that projection as generated-family-shaped input.
+
+## SSJS Scorecard
+
+- Runtime-backed forms: green for this documentation slice; no runtime forms
+ introduced.
+- Boundary validation: green; the matrix keeps authored schemas and Wesley
+ generated artifacts as authority.
+- Behavior ownership: green; each row separates authored home, compiler,
+ runtime source fact, consumer, and missing witness.
+- Message parsing: green; no behavior branches introduced.
+- Ambient time or entropy: green; no runtime code introduced.
+- Fake shape trust or cast-cosplay: green; every current `git-warp` mapping is
+ marked as translated evidence until a stronger witness exists.
+
+## Closeout
+
+This closes BEARING task 3 and supplies the evidence table for slices 4 and 5.
diff --git a/docs/design/0148-v18-warp-optic-realization-map/v18-warp-optic-realization-map.md b/docs/design/0148-v18-warp-optic-realization-map/v18-warp-optic-realization-map.md
new file mode 100644
index 00000000..6c859f4b
--- /dev/null
+++ b/docs/design/0148-v18-warp-optic-realization-map/v18-warp-optic-realization-map.md
@@ -0,0 +1,113 @@
+---
+cycle: 0148
+task_id: V18_warp_optic_realization_map
+status: Complete
+sponsors:
+ human: James
+ agent: Codex
+started_at: 2026-05-21
+completed_at: 2026-05-21
+release_home: v18.0.0
+---
+
+# V18 WARP Optic Realization Map
+
+## Pull
+
+The contract matrix names the cross-repo families. This slice maps
+`git-warp`'s current runtime facts onto the WARP optic tuple without claiming a
+generic optic engine.
+
+## Hill
+
+For v18, `git-warp` interprets:
+
+```text
+Psi = (Omega, chi, rho, Pi, Lambda)
+Lower_Psi(F*, P) = (R, W, theta)
+```
+
+as a compatibility map over existing repo facts.
+
+## Component Map
+
+| Optic component | WARP role | Current `git-warp` anchors | v18 compatibility gap |
+| --- | --- | --- | --- |
+| `Omega` | Observer discipline: projection, basis, observer state, update discipline, and emission | `WorldlineOptic`, `NodeOptic`, `NodePropertyOptic`, `ReadIdentity`, `Observer`, `QueryRunner`, `QueryReadModelProvider`, `ExternalizationPolicy` | Generated `ObserverPlan`, `ObservationRequest`, and `ReadingEnvelope` family shapes |
+| `chi` | Bounded frontier-relative optic slice | `CheckpointTailWitnessLocator`, `CheckpointTailBasisLoader`, `CheckpointTailOpticSource`, `CheckpointTailReadIdentityBuilder`, `ProvenanceController.materializeSlice` | Shared vocabulary for slice support, tail budget, and graph-model attachment plane |
+| `rho` | Set-side lowering surface that presents comparable claims over `chi` | `reduceV5`, `applyWithReceipt`, `JoinReducerSession`, op classes, `PatchDiff`, `syncDelta`, materialize-coordinate paths | Generated lowering inputs for receipt, settlement, and runtime-boundary families |
+| `Pi` | Admission law for derived, plural, conflict, or obstruction outcomes | `OpStrategies`, `ReceiptBuilder`, `TickReceipt` outcomes, `ConflictAnalyzerService`, `SyncTrustGate`, `OpticReadFailureCause` | First-class outcome algebra aligned with Continuum `AdmissionOutcomeKind` and runtime-boundary admission nouns |
+| `Lambda` | Retention contract for replay, audit, transport, revelation, and reliance obligations | append-only Git commits, writer refs, patch SHAs, checkpoints, `ReceiptShard`, `AuditReceiptService`, `ReadIdentity`, sync suffixes | Generated evidence-status wrappers, suffix shells, and explicit retention obligations for `warp-ttd` |
+
+## Lowering Scales
+
+| Scale | Weave `P` | Frontier `F*` | Result `R` | Witness `W` | Retained shell `theta` | Current posture |
+| --- | --- | --- | --- | --- | --- | --- |
+| Tick / patch | One patch or ordered patch sequence | Writer and graph frontier | State transition, `PatchDiff`, or op outcomes | `TickReceipt`, op outcome details | Patch commit, receipt, optional audit receipt | Real local runtime fact; not native Continuum receipt-family output yet |
+| Read / optic | Observer/read target plus basis | Live, coordinate, or strand source | Node/property/traversal/materialized reading | `ReadIdentity`, checkpoint-tail witnesses, failure cause | Read identity plus checkpoint/tail anchors | Real local read fact; missing generated `ReadingEnvelope` |
+| Provenance slice | Backward cone for a target | Patch graph reachable from target | Bounded reconstructed state and patch count | Causal patch list, optional receipts | Provenance payload and source SHAs | Real local source fact; missing Continuum evidence wrapper |
+| Strand / braid | Strand overlay or braided strand set | Parent frontier plus overlay heads | Materialized strand state or conflict trace | conflict receipts, conflict anchors, participant traces | strand descriptor, overlay patches, conflict analysis | Candidate settlement-family source facts |
+| Replica / sync | Remote suffix family or frontier delta | Local and remote writer frontiers | Needed patch ranges, trust posture, import/sync result | writer trust gate result, ancestry checks | transferred patch commits and refs | Candidate runtime-boundary suffix/import facts |
+
+## Outcome Algebra Posture
+
+The WARP paper's outcome space is:
+
+```text
+O(X) = Derived(X) + Plural(X) + Conflict + Obstruction
+```
+
+Current `git-warp` facts map into it conservatively:
+
+| Outcome | Local anchors | Current limitation |
+| --- | --- | --- |
+| `Derived` | successful reducer outcomes, materialized readings, query results | Not wrapped as a generated Continuum outcome |
+| `Plural` | strand/braid coexistence and multi-writer frontier facts | Plurality is represented structurally, not as a named outcome |
+| `Conflict` | conflict traces, diagnostics, conflict receipt refs | Settlement-family projection is still missing |
+| `Obstruction` | optic read failures, sync trust rejection, validation errors | Obstruction is not yet one shared runtime-boundary noun |
+
+## Evidence Posture
+
+The first v18 compatibility layer must mark `git-warp` outputs as translated
+evidence unless a native Continuum runtime witness exists.
+
+That means:
+
+- a `TickReceipt` can be mapped toward `receipt-family`;
+- a conflict trace can be mapped toward `settlement-family`;
+- a read result can be mapped toward `runtime-boundary-family`;
+- a sync suffix can be mapped toward `WitnessedSuffixShell`;
+- none of those mappings may claim native Continuum witnesshood by shape alone.
+
+## Next Engineering Cut
+
+Slice 5 should create a generated-artifact ingestion seam that can load one
+Continuum family artifact descriptor or fixture and reject hidden handwritten
+authority. The first useful family is `receipt-family` because `git-warp`
+already has strong local source facts: `TickReceipt`, op outcomes,
+`DeliveryObservation`, receipt shards, and audit receipts.
+
+The seam should not:
+
+- parse arbitrary GraphQL in the domain;
+- generate types at runtime;
+- make `git-warp` the owner of Continuum family semantics;
+- equate translated `git-warp` evidence with native Continuum witnesshood.
+
+## SSJS Scorecard
+
+- Runtime-backed forms: green for this documentation slice; no runtime forms
+ introduced.
+- Boundary validation: green; the map treats generated artifacts as later
+ boundary inputs.
+- Behavior ownership: green; optic components are mapped to owning local
+ modules and their gaps are named.
+- Message parsing: green; no behavior branches introduced.
+- Ambient time or entropy: green; no runtime code introduced.
+- Fake shape trust or cast-cosplay: green; translated evidence is explicit.
+
+## Closeout
+
+This closes BEARING task 4 and gives slice 5 a narrow implementation target:
+ingest a generated-family artifact descriptor or fixture and guard against
+shadow authority.
diff --git a/docs/design/0149-v18-continuum-artifact-ingestion/v18-continuum-artifact-ingestion.md b/docs/design/0149-v18-continuum-artifact-ingestion/v18-continuum-artifact-ingestion.md
new file mode 100644
index 00000000..e7f8d79d
--- /dev/null
+++ b/docs/design/0149-v18-continuum-artifact-ingestion/v18-continuum-artifact-ingestion.md
@@ -0,0 +1,100 @@
+---
+cycle: 0149
+task_id: V18_continuum_artifact_ingestion
+status: Complete
+sponsors:
+ human: James
+ agent: Codex
+started_at: 2026-05-21
+completed_at: 2026-05-21
+release_home: v18.0.0
+---
+
+# V18 Continuum Artifact Ingestion
+
+## Pull
+
+The contract matrix and optic map both point at the same first implementation
+pressure: `git-warp` needs a generated-family artifact seam before it can map
+local facts into Continuum-family shapes.
+
+## Hill
+
+Add a narrow ingestion path for generated Continuum family artifact descriptors
+and reject local mirrors before they can become hidden family authority.
+
+## Implementation
+
+This slice adds:
+
+- `ContinuumFamilyId` for the four Continuum-owned family ids;
+- `ContinuumArtifactAuthority` for generated artifacts, generated fixtures,
+ local mirrors, and handwritten mirrors;
+- `ContinuumArtifactDescriptor` as the runtime-backed descriptor object;
+- `ContinuumArtifactIngestionPolicy` as the authority guard;
+- `ContinuumArtifactJsonFileAdapter` as the infrastructure-edge JSON loader;
+- `test/fixtures/continuum/receipt-family-generated-artifact.json` as the first
+ generated-family fixture descriptor.
+
+The guard accepts only:
+
+- `generated-artifact`
+- `generated-fixture`
+
+It rejects:
+
+- `local-mirror`
+- `handwritten-mirror`
+
+## Boundary Law
+
+JSON parsing stays in `src/infrastructure/adapters/`. Domain code receives
+validated constructor fields and runtime-backed objects.
+
+The descriptor does not parse GraphQL, generate TypeScript, or claim family
+semantics. It only records which generated-family artifact or fixture is being
+admitted and whether that admission posture is allowed.
+
+## Verification
+
+Focused checks:
+
+```text
+npx eslint src/domain/continuum/ContinuumFamilyId.ts \
+ src/domain/continuum/ContinuumArtifactAuthority.ts \
+ src/domain/continuum/ContinuumArtifactDescriptor.ts \
+ src/domain/continuum/ContinuumArtifactIngestionPolicy.ts \
+ src/domain/errors/ContinuumArtifactAuthorityError.ts \
+ src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts
+npm run typecheck:src
+npm run typecheck:test
+npm run typecheck:surface
+npx vitest run \
+ test/unit/domain/continuum/ContinuumArtifactIngestionPolicy.test.ts \
+ test/unit/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.test.ts
+```
+
+Observed focused test result:
+
+```text
+Test Files 2 passed (2)
+Tests 9 passed (9)
+```
+
+## SSJS Scorecard
+
+- Runtime-backed forms: green; new Continuum concepts are classes with
+ constructor validation and frozen instances.
+- Boundary validation: green; untrusted JSON is parsed only in the
+ infrastructure adapter.
+- Behavior ownership: green; the descriptor owns descriptor invariants and the
+ ingestion policy owns authority decisions.
+- Message parsing: green; no behavior branches parse free-form messages.
+- Ambient time or entropy: green; no ambient time or entropy introduced.
+- Fake shape trust or cast-cosplay: green; mirror descriptors are rejected
+ before ingestion.
+
+## Closeout
+
+This closes BEARING task 5 and gives later receipt-family projection work a
+safe generated-artifact entry point.
diff --git a/docs/design/continuum-categories.pdf b/docs/design/continuum-categories.pdf
index a218496f..82c7fc81 100644
Binary files a/docs/design/continuum-categories.pdf and b/docs/design/continuum-categories.pdf differ
diff --git a/docs/design/continuum-categories.tex b/docs/design/continuum-categories.tex
index e4d5d1ef..66d3e7ed 100644
--- a/docs/design/continuum-categories.tex
+++ b/docs/design/continuum-categories.tex
@@ -53,13 +53,17 @@ \section{Context}
The intended runtime family is the present Continuum surface:
\begin{itemize}[leftmargin=2em]
-\item \Echo{} as the hot runtime,
-\item \GitWarp{} as the cold causal runtime,
+\item \Echo{} as a Continuum participant,
+\item \GitWarp{} as a Continuum participant,
\item \TTD{} as the host-neutral debugger protocol surface,
\item \Fuse{}-style materializations as host adapters over worldlines, strands,
or braids.
\end{itemize}
+Continuum is the protocol for exchanging witnessed causal history. It is not a
+runtime hierarchy, and it does not make \Echo{} the owner of \GitWarp{}'s
+participant role.
+
\section{Design Claim}
\begin{principle}[Continuum split]
@@ -272,7 +276,7 @@ \section{Host-Indexed Optic Interpretations}
\toprule
Host or realization context & Interpreted role \\
\midrule
-\Echo{} & execute hot-side rewrites \\
+\Echo{} & execute Echo-local rewrites \\
\GitWarp{} & admit and materialize causal patches \\
\TTD{} & expose debugger playback and explanation surfaces \\
\Fuse{} & materialize editable filesystem projections \\
diff --git a/docs/method/backlog/README.md b/docs/method/backlog/README.md
index caa37341..74e38a7f 100644
--- a/docs/method/backlog/README.md
+++ b/docs/method/backlog/README.md
@@ -127,7 +127,7 @@ lanes.
| `B1` | backlog root | Unlaned maintenance and reference work. Needs classification or direct pull before it should block committed work. | `B0` or direct human pull. |
| `B2` | `bad-code/` | Foundational debt and invariant repair. This lane can legitimately block release or execution work. | `B0`, `B1`, or lower-level debt in `B2`. |
| `B3` | `v17.0.0/` | Current committed release work. Explicit per-note edges win here. | `B2`, same-band work, or explicit edges. |
-| `B4` | `v18.0.0/`, `up-next/` | Next-major substrate work plus unslotted near-term feature overflow after the active release. | `B2`, `B3`, or explicit same-band edges. |
+| `B4` | `v18.0.0/`, `up-next/` | Next-major graph-model work plus unslotted near-term feature overflow after the active release. | `B2`, `B3`, or explicit same-band edges. |
| `B5` | `v19.0.0/` | Doctrine/runtime follow-through after the substrate cut. | `B2`, `B3`, `B4`, or explicit same-band edges. |
| `B6` | `v20.0.0/`, `v21.0.0/`, `cool-ideas/` | Far-horizon slice-first/runtime and distributed/plural follow-through plus speculative orbit. | Promotion into another lane or completion of lower numbered bands. |
@@ -139,8 +139,8 @@ lanes.
| backlog root | `B1` | These notes are real work, but still need lane assignment or an explicit pull decision. When `feature:` is present, treat that as the subsystem home while release-home remains undecided. |
| `bad-code/` | `B2` | Invariant debt can block `v17.0.0`, `v18.0.0`, and `up-next`. |
| `v17.0.0/` | `B3` | This is the active release graph for TypeScript migration and streaming ORSets. |
-| `v18.0.0/` | `B4` | This is the next-major graph-substrate convergence lane. |
-| `up-next/` | `B4` | Feature-overflow queue behind the active release and next-major substrate work unless explicitly promoted into a numbered lane. |
+| `v18.0.0/` | `B4` | This is the next-major graph-model convergence lane. |
+| `up-next/` | `B4` | Feature-overflow queue behind the active release and next-major graph-model work unless explicitly promoted into a numbered lane. |
| `v19.0.0/` | `B5` | Doctrine, observer, and admission convergence after the substrate cut. |
| `v20.0.0/` | `B6` | Slice-first runtime realization after `v19.0.0/` hardens the noun and support law. |
| `v21.0.0/` | `B6` | Common-basis, braid, and fuller distributed observer geometry after `v20.0.0/`. |
@@ -296,13 +296,14 @@ Prefix counts:
| `SLUDGE` | 1 |
| `TS` | 11 |
-### `v18.0.0/` — `B4` Graph-Substrate Convergence
+### `v18.0.0/` — `B4` Graph-Model Convergence
Dependency posture:
- downstream of `v17.0.0/`
- explicit frontmatter edges carry the actual substrate cut order
-- this lane is the Echo-shaped graph-model cut, not full repo parity
+- this lane is the Continuum-compatible graph-model cut pressure-tested against
+ Echo, not full repo parity or runtime hierarchy
Canonical lane readme:
diff --git a/docs/method/backlog/WORKLOADS.md b/docs/method/backlog/WORKLOADS.md
index be8715b3..30502d45 100644
--- a/docs/method/backlog/WORKLOADS.md
+++ b/docs/method/backlog/WORKLOADS.md
@@ -42,7 +42,7 @@ dependency graph and likely write-surface overlap.
| `3.0` | `B3` | 5 | 25 | Ready-now v17 foundations and independent release hygiene |
| `3.1` | `B3` | 2 | 7 | Downstream v17 runtime split work |
| `3.x` parked | `B3` | 1 | 6 | Launch-prep proof and package tail |
-| `4` | `B4` | 9 | 43 | v18 substrate cut plus current `up-next/` queue |
+| `4` | `B4` | 9 | 43 | v18 graph-model cut plus current `up-next/` queue |
| `5` | `B5` | 3 | 11 | v19 observer/admission/runtime convergence |
| `6` | `B6` | 10 | 100 | v20/v21 horizon plus speculative orbit |
| Grand total | all | 44 | 371 | Full live backlog |
@@ -114,12 +114,12 @@ engineering trunks.
## Wave 4 — `B4`
-This wave contains the next-major graph-substrate lane and the current
-`up-next/` queue.
+This wave contains the next-major graph-model lane and the current `up-next/`
+queue.
| Workload | Count | Items | Agent surface | Preconditions |
|----------|------:|-------|---------------|---------------|
-| `WL-4A-v18-graph-substrate-convergence` | 8 | `PROTO_echo-shaped-node-records`, `PROTO_echo-shaped-edge-records`, `PROTO_attachment-plane-substrate`, `PROTO_graph-op-algebra-convergence`, `PROTO_content-attachment-plane-cutover`, `PROTO_legacy-props-as-projection`, `INFRA_graph-model-migration-tool`, `TRUST_genesis-replay-equivalence` | Echo-shaped graph model cut, migration tooling, and replay proof | v17 core release work complete |
+| `WL-4A-v18-graph-substrate-convergence` | 8 | `PROTO_echo-shaped-node-records`, `PROTO_echo-shaped-edge-records`, `PROTO_attachment-plane-substrate`, `PROTO_graph-op-algebra-convergence`, `PROTO_content-attachment-plane-cutover`, `PROTO_legacy-props-as-projection`, `INFRA_graph-model-migration-tool`, `TRUST_genesis-replay-equivalence` | Continuum-compatible graph model cut pressure-tested against Echo, migration tooling, and replay proof | v17 core release work complete |
| `WL-40-upnext-api-capability-contracts` | 4 | `DX_modular-type-declarations`, `DX_plumbing-to-gitplumbing-rename`, `PROTO_controller-capability-interfaces`, `PROTO_patch-commit-visibility-contract` | API capability and declaration-contract cleanup | none |
| `WL-41-upnext-runtime-boundaries` | 9 | `DX_max-file-size-policy`, `DX_trailer-codec-dts`, `NDNM_delete-vv-orset-shims`, `PROTO_cbor-op-hydration`, `PROTO_drop-v5-runtime-nouns`, `PROTO_op-consumer-instanceof-migration`, `PROTO_warpkernel-port-cleanup`, `PROTO_warpruntime-open-options-class`, `PROTO_wire-format-migration-edgepropset` | Runtime boundary cleanup and noun drift removal | none |
| `WL-42-upnext-streaming-read-chain` | 5 | `NDNM_defaultcodec-to-infrastructure`, `PERF_stream-read-migration`, `PERF_stream-cleanup`, `PERF_async-generator-traversal`, `PERF_stream-memory-tests` | Streaming read migration and memory witnesses | root `PERF_out-of-core-materialization` |
@@ -132,7 +132,7 @@ This wave contains the next-major graph-substrate lane and the current
## Wave 5 — `B5`
This wave is `v19.0.0`: observer, admission, and doctrine convergence
-after the graph-substrate cut.
+after the graph-model cut.
| Workload | Count | Items | Agent surface | Preconditions |
|----------|------:|-------|---------------|---------------|
@@ -189,7 +189,7 @@ If you want to staff agents immediately, start here:
3. Pull Wave `3.1` only after the named `v17` prerequisites are true.
4. Run Wave `2` in parallel when a release slice hits the same
invariant family.
-5. Use Wave `4` for `v18.0.0` planning or selective substrate prep
+5. Use Wave `4` for `v18.0.0` planning or selective graph-model prep
without starving active `B3` work.
6. Keep Waves `5` and `6` parked unless deliberately working doctrine,
horizon, or speculative follow-through.
diff --git a/docs/method/backlog/bad-code/RELEASE_TRIAGE.md b/docs/method/backlog/bad-code/RELEASE_TRIAGE.md
index 3e95a3f0..0ff84d70 100644
--- a/docs/method/backlog/bad-code/RELEASE_TRIAGE.md
+++ b/docs/method/backlog/bad-code/RELEASE_TRIAGE.md
@@ -28,8 +28,8 @@ Use the release theme, not the filename prefix, as the slotting rule:
| Release | Bad-Code That Belongs Here |
|---------|----------------------------|
| `v17.0.0` | Current engine cleanup: TypeScript migration fallout, capability/API honesty, `WarpRuntime` deletion fallout, current sync/security hardening, current trie/checkpoint/index correctness, and test/doc debt that blocks the v17 package from being honest. |
-| `v18.0.0` | Echo-shaped graph substrate convergence: node/edge record identity, attachment plane, typed payload model, graph-op algebra, graph-model migration, and replay equivalence from genesis. |
-| `v19.0.0` | Observer/admission/doctrine convergence: audit/admission seams, observer-readable receipts, patch/session admission semantics, trust/admission boundary models, and doctrine cleanup that should not be mixed into graph-substrate migration. |
+| `v18.0.0` | Continuum-compatible graph-model convergence pressure-tested against Echo: node/edge record identity, attachment plane, typed payload model, graph-op algebra, graph-model migration, and replay equivalence from genesis. |
+| `v19.0.0` | Observer/admission/doctrine convergence: audit/admission seams, observer-readable receipts, patch/session admission semantics, trust/admission boundary models, and doctrine cleanup that should not be mixed into graph-model migration. |
| `v20.0.0` | Slice-first runtime realization: bounded-support reads, streaming/page-shaped APIs, causal indexes, query/index cost surfaces, external-memory global operators, and materialization paths that must stop assuming whole-graph residency. |
| `v21.0.0` | Distributed observer geometry and admission reality: strand/braid/common-basis/local-site semantics, merge runtime nouns, witnessed admission, conflict witnesses, wormhole/plurality surfaces, and public noun cleanup for those later semantics. |
@@ -70,10 +70,10 @@ Other v17 recheck candidates:
## `v18.0.0` Fit
-The first metadata pass promoted only graph-substrate bad-code into
+The first metadata pass promoted only graph-model bad-code into
`v18.0.0`. This should stay narrow.
-Cards now pinned to v18 for the Echo-shaped graph substrate cycle:
+Cards now pinned to v18 for the graph-model convergence cycle:
- `CAST_warpstate-prop-unknown-value`: property value truth belongs with typed attachment/payload substrate decisions.
- `MODEL_neighbor-edge-typedef`: neighbor edge shape should line up with stable edge identity and edge-record nouns.
@@ -199,7 +199,7 @@ The first metadata pass did this:
3. Pulled the direct `WarpRuntime`/Worldline escape-hatch cards forward
into v17 or graveyard them if the current runtime-deletion line
already removed the smell.
-4. Promoted only graph-substrate cards into v18. Do not move generic
+4. Promoted only graph-model cards into v18. Do not move generic
typedef cleanup there just because v18 has room.
5. Recomputed bad-code release counts from frontmatter and updated
`bad-code/README.md`.
@@ -212,7 +212,7 @@ Use feature/release overlap:
1. During the v17 burndown, pay down or graveyard bad-code cards that
sit in the files already touched by the active v17 task.
-2. At the v18 pull, move only the graph-substrate candidates listed
+2. At the v18 pull, move only the graph-model candidates listed
above into the v18 lane and leave unrelated cleanup behind.
3. At the v19 pull, resolve admission/trust/audit cards as part of the
observer/admission surface work.
diff --git a/docs/method/backlog/v18.0.0/PROTO_echo-shaped-edge-records.md b/docs/method/backlog/v18.0.0/PROTO_echo-shaped-edge-records.md
index 2d8101f2..16f92bb4 100644
--- a/docs/method/backlog/v18.0.0/PROTO_echo-shaped-edge-records.md
+++ b/docs/method/backlog/v18.0.0/PROTO_echo-shaped-edge-records.md
@@ -8,13 +8,17 @@ blocks:
feature: graph-model-substrate
---
-# Echo-shaped edge records
+# Shared graph-model edge records
+
+Identity note: the backlog id keeps the older `echo-shaped` shorthand for
+continuity. The target is graph-model alignment pressure-tested by Echo, not
+Echo ownership of `git-warp`.
## Why
`git-warp` still identifies edges by the `(from, to, label)` triple
-and derived key encodings. Echo's substrate gives edges first-class
-identity and treats edge type as part of the record, not the identity
+and derived key encodings. Echo has already pressure-tested edges as
+first-class records where edge type is part of the record, not the identity
carrier.
Shared graph shape requires stable edge records.
diff --git a/docs/method/backlog/v18.0.0/PROTO_echo-shaped-node-records.md b/docs/method/backlog/v18.0.0/PROTO_echo-shaped-node-records.md
index fcf1152c..7861ce70 100644
--- a/docs/method/backlog/v18.0.0/PROTO_echo-shaped-node-records.md
+++ b/docs/method/backlog/v18.0.0/PROTO_echo-shaped-node-records.md
@@ -8,12 +8,16 @@ blocks:
feature: graph-model-substrate
---
-# Echo-shaped node records
+# Shared graph-model node records
+
+Identity note: the backlog id keeps the older `echo-shaped` shorthand for
+continuity. The target is graph-model alignment pressure-tested by Echo, not
+Echo ownership of `git-warp`.
## Why
`git-warp` still treats node identity as a bare string plus property
-bag fallout. Echo's substrate treats nodes as skeleton records with
+bag fallout. Echo has already pressure-tested nodes as skeleton records with
stable identity and explicit type.
If the repos are going to share the same graph model, node records
diff --git a/docs/method/backlog/v18.0.0/README.md b/docs/method/backlog/v18.0.0/README.md
index 77e76e32..82dd5327 100644
--- a/docs/method/backlog/v18.0.0/README.md
+++ b/docs/method/backlog/v18.0.0/README.md
@@ -1,10 +1,16 @@
-# v18.0.0 — Echo-Shaped Graph Substrate Convergence
+# v18.0.0 — Continuum-Compatible Graph Model Convergence
-The hill: make `git-warp` and Echo share the same graph substrate
-shape without pretending they must immediately share the same public
-API, admission model, or runtime shell.
+The hill: make `git-warp`'s graph model compatible with the concrete
+shape Echo has already exercised while keeping both engines as equal
+Continuum participants. They do not need to share the same public API,
+admission model, or runtime shell.
-This release cuts the graph layer to the Echo-shaped two-plane model:
+Doctrine note: `PROTO_echo-shaped-*` task identities are historical
+backlog shorthand for graph-model alignment pressure from Echo. They do
+not mean Echo owns `git-warp`, and they do not make Continuum a runtime
+hierarchy.
+
+This release cuts the graph layer toward the shared two-plane model:
- skeleton-only node records
- skeleton-only edge records with stable edge identity
@@ -55,10 +61,9 @@ LAYER 2 (migration and proof):
## Practical rule
-`v18.0.0` is graph-substrate convergence, not "make git-warp become
-Echo." Keep the `git-warp` causal envelope if it can faithfully carry
-the shared graph model. Change the envelope only if replay honesty
-requires it.
+`v18.0.0` is graph-model convergence, not "make git-warp become Echo."
+Keep the `git-warp` causal envelope if it can faithfully carry the shared
+graph model. Change the envelope only if replay honesty requires it.
## Status key
diff --git a/docs/method/retro/0145-push-pr-review-merge/push-pr-review-merge.md b/docs/method/retro/0145-push-pr-review-merge/push-pr-review-merge.md
new file mode 100644
index 00000000..30e8df71
--- /dev/null
+++ b/docs/method/retro/0145-push-pr-review-merge/push-pr-review-merge.md
@@ -0,0 +1,38 @@
+# 0145 Push PR Review Merge Retro
+
+## Outcome
+
+`REL_push-pr-review-merge` is closed. The v17 release branch was merged to
+`main`, the signed `v17.0.0` tag was created, npm and JSR publish recovery
+completed, and the short-lived release branches were pruned from `origin`.
+
+## What Went Well
+
+- The final release coordination happened through visible PR history instead of
+ local-only release state.
+- Follow-up repair PRs kept publication and CI hardening close to the release
+ merge, which makes the release story auditable from `main`.
+- Registry checks confirmed that both npm and JSR expose `17.0.0` as the
+ current package version.
+
+## What Was Messy
+
+- `BEARING.md` and the 0145 design doc drifted behind reality after the
+ package published.
+- The v17 DAG still showed the final coordination node as open after the branch
+ had landed.
+- Local git fsmonitor was producing noisy status/diff warnings during the
+ closeout inspection.
+
+## Follow-Up
+
+Start v18 from a truthful signpost: Continuum/WARP Optic compatibility through
+Wesley-generated artifacts, explicit evidence posture, and `warp-ttd`
+acceptance over generated-family facts.
+
+## Battle Report
+
+The release train made it into the station, then the station sign kept saying
+"boarding soon." This retro fixes the sign. The next mess is bigger: teach
+`git-warp` to speak Continuum contract families without dressing adapter
+folklore up as native witnesshood.
diff --git a/index.ts b/index.ts
index e4719aed..ce8b8572 100644
--- a/index.ts
+++ b/index.ts
@@ -46,6 +46,7 @@ import NoOpLogger from './src/infrastructure/adapters/NoOpLogger.ts';
import ConsoleLogger, { LogLevel } from './src/infrastructure/adapters/ConsoleLogger.ts';
import {
AuditError,
+ ContinuumArtifactAuthorityError,
EncryptionError,
ForkError,
IndexError,
@@ -207,6 +208,14 @@ import {
exportCoordinateComparisonFact,
exportCoordinateTransferPlanFact,
} from './src/domain/services/CoordinateFactExport.ts';
+import ContinuumArtifactAuthority from './src/domain/continuum/ContinuumArtifactAuthority.ts';
+import ContinuumArtifactDescriptor from './src/domain/continuum/ContinuumArtifactDescriptor.ts';
+import ContinuumArtifactIngestionPolicy from './src/domain/continuum/ContinuumArtifactIngestionPolicy.ts';
+import ContinuumFamilyId from './src/domain/continuum/ContinuumFamilyId.ts';
+import ContinuumArtifactJsonFileAdapter from './src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts';
+import type { ContinuumArtifactAuthorityValue } from './src/domain/continuum/ContinuumArtifactAuthority.ts';
+import type { ContinuumArtifactDescriptorFields } from './src/domain/continuum/ContinuumArtifactDescriptor.ts';
+import type { ContinuumFamilyIdValue } from './src/domain/continuum/ContinuumFamilyId.ts';
export {
GitGraphAdapter,
@@ -247,6 +256,7 @@ export {
// Error types for integrity failure handling
AuditError,
+ ContinuumArtifactAuthorityError,
EncryptionError,
PatchError,
ForkError,
@@ -318,6 +328,13 @@ export {
exportCoordinateComparisonFact,
exportCoordinateTransferPlanFact,
+ // Continuum compatibility artifacts
+ ContinuumArtifactAuthority,
+ ContinuumArtifactDescriptor,
+ ContinuumArtifactIngestionPolicy,
+ ContinuumFamilyId,
+ ContinuumArtifactJsonFileAdapter,
+
// Tick receipts (LIGHTHOUSE)
createTickReceipt,
tickReceiptCanonicalJson,
@@ -360,7 +377,14 @@ export {
SyncSecret,
};
-export type { PropValue, SnapshotPropValue, SyncRateLimitConfig };
+export type {
+ PropValue,
+ SnapshotPropValue,
+ SyncRateLimitConfig,
+ ContinuumArtifactAuthorityValue,
+ ContinuumArtifactDescriptorFields,
+ ContinuumFamilyIdValue,
+};
// WarpApp is the primary product-facing API for v15.
export default WarpApp;
diff --git a/src/domain/continuum/ContinuumArtifactAuthority.ts b/src/domain/continuum/ContinuumArtifactAuthority.ts
new file mode 100644
index 00000000..589b1a7a
--- /dev/null
+++ b/src/domain/continuum/ContinuumArtifactAuthority.ts
@@ -0,0 +1,61 @@
+import WarpError from '../errors/WarpError.ts';
+
+const GENERATED_ARTIFACT_AUTHORITY = 'generated-artifact';
+const GENERATED_FIXTURE_AUTHORITY = 'generated-fixture';
+const LOCAL_MIRROR_AUTHORITY = 'local-mirror';
+const HANDWRITTEN_MIRROR_AUTHORITY = 'handwritten-mirror';
+
+export type ContinuumArtifactAuthorityValue =
+ | typeof GENERATED_ARTIFACT_AUTHORITY
+ | typeof GENERATED_FIXTURE_AUTHORITY
+ | typeof LOCAL_MIRROR_AUTHORITY
+ | typeof HANDWRITTEN_MIRROR_AUTHORITY;
+
+export const CONTINUUM_ARTIFACT_AUTHORITIES: readonly ContinuumArtifactAuthorityValue[] = Object.freeze([
+ GENERATED_ARTIFACT_AUTHORITY,
+ GENERATED_FIXTURE_AUTHORITY,
+ LOCAL_MIRROR_AUTHORITY,
+ HANDWRITTEN_MIRROR_AUTHORITY,
+]);
+
+/** Runtime-backed authority posture for an ingested Continuum artifact. */
+export default class ContinuumArtifactAuthority {
+ readonly value: ContinuumArtifactAuthorityValue;
+
+ constructor(value: string) {
+ this.value = requireContinuumArtifactAuthority(value);
+ Object.freeze(this);
+ }
+
+ /** Returns true for Wesley-generated artifacts and documented fixtures. */
+ isGeneratedAuthority(): boolean {
+ return (
+ this.value === GENERATED_ARTIFACT_AUTHORITY ||
+ this.value === GENERATED_FIXTURE_AUTHORITY
+ );
+ }
+
+ /** Returns the stable authority string. */
+ toString(): string {
+ return this.value;
+ }
+}
+
+/** Validates a raw authority posture string. */
+export function requireContinuumArtifactAuthority(value: string): ContinuumArtifactAuthorityValue {
+ switch (value) {
+ case GENERATED_ARTIFACT_AUTHORITY:
+ return GENERATED_ARTIFACT_AUTHORITY;
+ case GENERATED_FIXTURE_AUTHORITY:
+ return GENERATED_FIXTURE_AUTHORITY;
+ case LOCAL_MIRROR_AUTHORITY:
+ return LOCAL_MIRROR_AUTHORITY;
+ case HANDWRITTEN_MIRROR_AUTHORITY:
+ return HANDWRITTEN_MIRROR_AUTHORITY;
+ default:
+ throw new WarpError(
+ `Continuum artifact authority must be one of: ${CONTINUUM_ARTIFACT_AUTHORITIES.join(', ')}`,
+ 'E_VALIDATION',
+ );
+ }
+}
diff --git a/src/domain/continuum/ContinuumArtifactDescriptor.ts b/src/domain/continuum/ContinuumArtifactDescriptor.ts
new file mode 100644
index 00000000..d474b8b1
--- /dev/null
+++ b/src/domain/continuum/ContinuumArtifactDescriptor.ts
@@ -0,0 +1,96 @@
+import ContinuumArtifactAuthority from './ContinuumArtifactAuthority.ts';
+import ContinuumFamilyId from './ContinuumFamilyId.ts';
+import WarpError from '../errors/WarpError.ts';
+
+export type ContinuumArtifactDescriptorFields = {
+ readonly familyId: string | ContinuumFamilyId;
+ readonly version: string;
+ readonly sourceSchemaPath: string;
+ readonly generatedBy: string;
+ readonly artifactKind: string;
+ readonly authority: string | ContinuumArtifactAuthority;
+ readonly targets: readonly string[];
+ readonly witnessScope?: string;
+ readonly artifactDigest?: string;
+};
+
+/** Runtime-backed descriptor for a generated Continuum family artifact. */
+export default class ContinuumArtifactDescriptor {
+ readonly familyId: ContinuumFamilyId;
+ readonly version: string;
+ readonly sourceSchemaPath: string;
+ readonly generatedBy: string;
+ readonly artifactKind: string;
+ readonly authority: ContinuumArtifactAuthority;
+ readonly targets: readonly string[];
+ readonly witnessScope: string | undefined;
+ readonly artifactDigest: string | undefined;
+
+ constructor(fields: ContinuumArtifactDescriptorFields) {
+ const { familyId, version, sourceSchemaPath, generatedBy, artifactKind, authority, targets } = fields;
+ this.familyId = normalizeFamilyId(familyId);
+ this.version = requireNonEmptyString(version, 'version');
+ this.sourceSchemaPath = requireNonEmptyString(sourceSchemaPath, 'sourceSchemaPath');
+ this.generatedBy = requireNonEmptyString(generatedBy, 'generatedBy');
+ this.artifactKind = requireNonEmptyString(artifactKind, 'artifactKind');
+ this.authority = normalizeAuthority(authority);
+ this.targets = freezeTargets(targets);
+ this.witnessScope = optionalNonEmptyString(fields.witnessScope, 'witnessScope');
+ this.artifactDigest = optionalNonEmptyString(fields.artifactDigest, 'artifactDigest');
+ Object.freeze(this);
+ }
+
+ /** Returns true when the descriptor includes the requested generation target. */
+ hasTarget(target: string): boolean {
+ return this.targets.includes(target);
+ }
+
+ /** Returns true when the artifact may be used as generated authority. */
+ hasGeneratedAuthority(): boolean {
+ return this.authority.isGeneratedAuthority();
+ }
+}
+
+/** Normalizes a family id carrier. */
+function normalizeFamilyId(value: string | ContinuumFamilyId): ContinuumFamilyId {
+ if (value instanceof ContinuumFamilyId) {
+ return value;
+ }
+ return new ContinuumFamilyId(value);
+}
+
+/** Normalizes an authority carrier. */
+function normalizeAuthority(value: string | ContinuumArtifactAuthority): ContinuumArtifactAuthority {
+ if (value instanceof ContinuumArtifactAuthority) {
+ return value;
+ }
+ return new ContinuumArtifactAuthority(value);
+}
+
+/** Validates a required non-empty string. */
+function requireNonEmptyString(value: string, name: string): string {
+ if (value.length === 0) {
+ throw new WarpError(`${name} must be a non-empty string`, 'E_VALIDATION');
+ }
+ return value;
+}
+
+/** Validates an optional non-empty string. */
+function optionalNonEmptyString(value: string | undefined, name: string): string | undefined {
+ if (value === undefined) {
+ return undefined;
+ }
+ return requireNonEmptyString(value, name);
+}
+
+/** Freezes and validates a generated target list. */
+function freezeTargets(targets: readonly string[]): readonly string[] {
+ if (targets.length === 0) {
+ throw new WarpError('targets must contain at least one generated target', 'E_VALIDATION');
+ }
+ const normalized: string[] = [];
+ for (const target of targets) {
+ normalized.push(requireNonEmptyString(target, 'targets[]'));
+ }
+ return Object.freeze(normalized);
+}
diff --git a/src/domain/continuum/ContinuumArtifactIngestionPolicy.ts b/src/domain/continuum/ContinuumArtifactIngestionPolicy.ts
new file mode 100644
index 00000000..bd0fad1b
--- /dev/null
+++ b/src/domain/continuum/ContinuumArtifactIngestionPolicy.ts
@@ -0,0 +1,21 @@
+import ContinuumArtifactAuthorityError from '../errors/ContinuumArtifactAuthorityError.ts';
+import type ContinuumArtifactDescriptor from './ContinuumArtifactDescriptor.ts';
+
+/** Policy gate for admitting generated Continuum family artifacts. */
+export default class ContinuumArtifactIngestionPolicy {
+ /** Accepts generated artifacts and documented fixtures, rejecting mirrors. */
+ ingest(descriptor: ContinuumArtifactDescriptor): ContinuumArtifactDescriptor {
+ this.assertGeneratedAuthority(descriptor);
+ return descriptor;
+ }
+
+ /** Rejects descriptors whose authority would make local mirrors canonical. */
+ assertGeneratedAuthority(descriptor: ContinuumArtifactDescriptor): void {
+ if (descriptor.hasGeneratedAuthority()) {
+ return;
+ }
+ throw new ContinuumArtifactAuthorityError(
+ `Continuum family ${descriptor.familyId.toString()} must be loaded from a generated artifact or fixture, not ${descriptor.authority.toString()}`,
+ );
+ }
+}
diff --git a/src/domain/continuum/ContinuumFamilyId.ts b/src/domain/continuum/ContinuumFamilyId.ts
new file mode 100644
index 00000000..7c15288e
--- /dev/null
+++ b/src/domain/continuum/ContinuumFamilyId.ts
@@ -0,0 +1,58 @@
+import WarpError from '../errors/WarpError.ts';
+
+const RECEIPT_FAMILY_ID = 'receipt-family';
+const SETTLEMENT_FAMILY_ID = 'settlement-family';
+const NEIGHBORHOOD_CORE_FAMILY_ID = 'neighborhood-core-family';
+const RUNTIME_BOUNDARY_FAMILY_ID = 'runtime-boundary-family';
+
+export type ContinuumFamilyIdValue =
+ | typeof RECEIPT_FAMILY_ID
+ | typeof SETTLEMENT_FAMILY_ID
+ | typeof NEIGHBORHOOD_CORE_FAMILY_ID
+ | typeof RUNTIME_BOUNDARY_FAMILY_ID;
+
+export const CONTINUUM_FAMILY_IDS: readonly ContinuumFamilyIdValue[] = Object.freeze([
+ RECEIPT_FAMILY_ID,
+ SETTLEMENT_FAMILY_ID,
+ NEIGHBORHOOD_CORE_FAMILY_ID,
+ RUNTIME_BOUNDARY_FAMILY_ID,
+]);
+
+/** Runtime-backed identifier for a Continuum-owned contract family. */
+export default class ContinuumFamilyId {
+ readonly value: ContinuumFamilyIdValue;
+
+ constructor(value: string) {
+ this.value = requireContinuumFamilyId(value);
+ Object.freeze(this);
+ }
+
+ /** Returns true when both ids name the same Continuum family. */
+ equals(other: ContinuumFamilyId): boolean {
+ return this.value === other.value;
+ }
+
+ /** Returns the stable family id string. */
+ toString(): string {
+ return this.value;
+ }
+}
+
+/** Validates a raw family id string. */
+export function requireContinuumFamilyId(value: string): ContinuumFamilyIdValue {
+ switch (value) {
+ case RECEIPT_FAMILY_ID:
+ return RECEIPT_FAMILY_ID;
+ case SETTLEMENT_FAMILY_ID:
+ return SETTLEMENT_FAMILY_ID;
+ case NEIGHBORHOOD_CORE_FAMILY_ID:
+ return NEIGHBORHOOD_CORE_FAMILY_ID;
+ case RUNTIME_BOUNDARY_FAMILY_ID:
+ return RUNTIME_BOUNDARY_FAMILY_ID;
+ default:
+ throw new WarpError(
+ `Continuum family id must be one of: ${CONTINUUM_FAMILY_IDS.join(', ')}`,
+ 'E_VALIDATION',
+ );
+ }
+}
diff --git a/src/domain/errors/ContinuumArtifactAuthorityError.ts b/src/domain/errors/ContinuumArtifactAuthorityError.ts
new file mode 100644
index 00000000..4734cd51
--- /dev/null
+++ b/src/domain/errors/ContinuumArtifactAuthorityError.ts
@@ -0,0 +1,8 @@
+import WarpError, { type WarpErrorOptions } from './WarpError.ts';
+
+/** Error thrown when a Continuum artifact would create shadow authority. */
+export default class ContinuumArtifactAuthorityError extends WarpError {
+ constructor(message: string, options: WarpErrorOptions = {}) {
+ super(message, 'E_CONTINUUM_ARTIFACT_AUTHORITY', options);
+ }
+}
diff --git a/src/domain/errors/index.ts b/src/domain/errors/index.ts
index 2dd7cb41..f087fcc3 100644
--- a/src/domain/errors/index.ts
+++ b/src/domain/errors/index.ts
@@ -1,6 +1,7 @@
/** Custom error classes for domain operations. */
export { default as AuditError } from './AuditError.ts';
+export { default as ContinuumArtifactAuthorityError } from './ContinuumArtifactAuthorityError.ts';
export { default as EncryptionError } from './EncryptionError.ts';
export { default as ForkError } from './ForkError.ts';
export { default as IndexError } from './IndexError.ts';
diff --git a/src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts b/src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts
new file mode 100644
index 00000000..60042a9e
--- /dev/null
+++ b/src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts
@@ -0,0 +1,115 @@
+import { readFile } from 'node:fs/promises';
+
+import ContinuumArtifactDescriptor, {
+ type ContinuumArtifactDescriptorFields,
+} from '../../domain/continuum/ContinuumArtifactDescriptor.ts';
+import ContinuumArtifactIngestionPolicy from '../../domain/continuum/ContinuumArtifactIngestionPolicy.ts';
+import AdapterValidationError from '../../domain/errors/AdapterValidationError.ts';
+
+type JsonObject = Readonly>;
+
+/** Loads Continuum artifact descriptors from JSON files at the adapter edge. */
+export default class ContinuumArtifactJsonFileAdapter {
+ private readonly policy: ContinuumArtifactIngestionPolicy;
+
+ constructor(policy: ContinuumArtifactIngestionPolicy = new ContinuumArtifactIngestionPolicy()) {
+ this.policy = policy;
+ }
+
+ /** Reads and ingests a generated artifact descriptor from disk. */
+ async loadFile(path: string): Promise {
+ const raw = await readFile(path, 'utf8');
+ return this.loadString(raw);
+ }
+
+ /** Ingests a generated artifact descriptor from JSON text. */
+ loadString(raw: string): ContinuumArtifactDescriptor {
+ const parsed: unknown = JSON.parse(raw);
+ const fields = parseDescriptorFields(parsed);
+ return this.policy.ingest(new ContinuumArtifactDescriptor(fields));
+ }
+}
+
+/** Converts untrusted JSON into descriptor fields. */
+function parseDescriptorFields(value: unknown): ContinuumArtifactDescriptorFields {
+ const source = requireJsonObject(value);
+ const base = {
+ familyId: readRequiredString(source, 'familyId'),
+ version: readRequiredString(source, 'version'),
+ sourceSchemaPath: readRequiredString(source, 'sourceSchemaPath'),
+ generatedBy: readRequiredString(source, 'generatedBy'),
+ artifactKind: readRequiredString(source, 'artifactKind'),
+ authority: readRequiredString(source, 'authority'),
+ targets: readStringArray(source, 'targets'),
+ };
+ return withOptionalFields(base, source);
+}
+
+/** Adds optional descriptor fields when present. */
+function withOptionalFields(
+ base: ContinuumArtifactDescriptorFields,
+ source: JsonObject,
+): ContinuumArtifactDescriptorFields {
+ const witnessScope = readOptionalString(source, 'witnessScope');
+ const artifactDigest = readOptionalString(source, 'artifactDigest');
+ return {
+ ...base,
+ ...(witnessScope !== undefined ? { witnessScope } : {}),
+ ...(artifactDigest !== undefined ? { artifactDigest } : {}),
+ };
+}
+
+/** Requires a non-array JSON object. */
+function requireJsonObject(value: unknown): JsonObject {
+ if (!isJsonObject(value)) {
+ throw new AdapterValidationError('Continuum artifact descriptor JSON must be an object');
+ }
+ return value;
+}
+
+/** Returns true when a value is a non-array JSON object. */
+function isJsonObject(value: unknown): value is JsonObject {
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
+}
+
+/** Reads a required string field. */
+function readRequiredString(source: JsonObject, key: string): string {
+ const value = source[key];
+ if (typeof value !== 'string' || value.length === 0) {
+ throw new AdapterValidationError(`Continuum artifact descriptor field "${key}" must be a non-empty string`);
+ }
+ return value;
+}
+
+/** Reads an optional string field. */
+function readOptionalString(source: JsonObject, key: string): string | undefined {
+ const value = source[key];
+ if (value === undefined) {
+ return undefined;
+ }
+ if (typeof value !== 'string' || value.length === 0) {
+ throw new AdapterValidationError(`Continuum artifact descriptor field "${key}" must be a non-empty string when present`);
+ }
+ return value;
+}
+
+/** Reads a required string array field. */
+function readStringArray(source: JsonObject, key: string): readonly string[] {
+ const value = source[key];
+ if (!Array.isArray(value) || value.length === 0) {
+ throw new AdapterValidationError(`Continuum artifact descriptor field "${key}" must be a non-empty string array`);
+ }
+ const strings: string[] = [];
+ for (const entry of value) {
+ strings.push(readStringArrayEntry(entry, key));
+ }
+ return Object.freeze(strings);
+}
+
+/** Reads one string array entry. */
+function readStringArrayEntry(value: unknown, key: string): string {
+ if (typeof value !== 'string' || value.length === 0) {
+ throw new AdapterValidationError(`Continuum artifact descriptor field "${key}" must contain only non-empty strings`);
+ }
+ return value;
+}
diff --git a/test/fixtures/continuum/receipt-family-generated-artifact.json b/test/fixtures/continuum/receipt-family-generated-artifact.json
new file mode 100644
index 00000000..cc6c9029
--- /dev/null
+++ b/test/fixtures/continuum/receipt-family-generated-artifact.json
@@ -0,0 +1,11 @@
+{
+ "familyId": "receipt-family",
+ "version": "0.1.0",
+ "sourceSchemaPath": "~/git/continuum/schemas/continuum-receipt-family.graphql",
+ "generatedBy": "wesley witness-continuum --scope receipt-family",
+ "artifactKind": "continuum.family.fixture",
+ "authority": "generated-fixture",
+ "targets": ["typescript", "echo"],
+ "witnessScope": "receipt-family",
+ "artifactDigest": "sha256:receipt-fixture"
+}
diff --git a/test/unit/domain/continuum/ContinuumArtifactIngestionPolicy.test.ts b/test/unit/domain/continuum/ContinuumArtifactIngestionPolicy.test.ts
new file mode 100644
index 00000000..b8b86bf2
--- /dev/null
+++ b/test/unit/domain/continuum/ContinuumArtifactIngestionPolicy.test.ts
@@ -0,0 +1,57 @@
+import { describe, expect, it } from 'vitest';
+
+import ContinuumArtifactAuthorityError from '../../../../src/domain/errors/ContinuumArtifactAuthorityError.ts';
+import ContinuumArtifactDescriptor from '../../../../src/domain/continuum/ContinuumArtifactDescriptor.ts';
+import ContinuumArtifactIngestionPolicy from '../../../../src/domain/continuum/ContinuumArtifactIngestionPolicy.ts';
+import ContinuumFamilyId from '../../../../src/domain/continuum/ContinuumFamilyId.ts';
+
+/** Builds a receipt-family descriptor for policy tests. */
+function makeDescriptor(authority: string): ContinuumArtifactDescriptor {
+ return new ContinuumArtifactDescriptor({
+ familyId: 'receipt-family',
+ version: '0.1.0',
+ sourceSchemaPath: '~/git/continuum/schemas/continuum-receipt-family.graphql',
+ generatedBy: 'wesley witness-continuum --scope receipt-family',
+ artifactKind: 'continuum.family.fixture',
+ authority,
+ targets: ['typescript', 'echo'],
+ witnessScope: 'receipt-family',
+ });
+}
+
+describe('ContinuumArtifactIngestionPolicy', () => {
+ it('accepts documented generated fixtures', () => {
+ const descriptor = makeDescriptor('generated-fixture');
+ const policy = new ContinuumArtifactIngestionPolicy();
+
+ expect(policy.ingest(descriptor)).toBe(descriptor);
+ });
+
+ it('accepts generated artifacts', () => {
+ const descriptor = makeDescriptor('generated-artifact');
+ const policy = new ContinuumArtifactIngestionPolicy();
+
+ expect(policy.ingest(descriptor)).toBe(descriptor);
+ });
+
+ it('rejects local mirrors as family authority', () => {
+ const descriptor = makeDescriptor('local-mirror');
+ const policy = new ContinuumArtifactIngestionPolicy();
+
+ expect(() => policy.ingest(descriptor)).toThrow(ContinuumArtifactAuthorityError);
+ });
+
+ it('rejects handwritten mirrors as family authority', () => {
+ const descriptor = makeDescriptor('handwritten-mirror');
+ const policy = new ContinuumArtifactIngestionPolicy();
+
+ expect(() => policy.ingest(descriptor)).toThrow(ContinuumArtifactAuthorityError);
+ });
+
+ it('keeps family ids runtime-backed', () => {
+ const descriptor = makeDescriptor('generated-fixture');
+
+ expect(descriptor.familyId).toBeInstanceOf(ContinuumFamilyId);
+ expect(descriptor.familyId.toString()).toBe('receipt-family');
+ });
+});
diff --git a/test/unit/domain/errors/index.test.ts b/test/unit/domain/errors/index.test.ts
index 30fc4cf7..59c75c57 100644
--- a/test/unit/domain/errors/index.test.ts
+++ b/test/unit/domain/errors/index.test.ts
@@ -6,6 +6,7 @@ describe('domain/errors index barrel', () => {
expect(Object.keys(errors).sort()).toEqual([
'AuditError',
+ 'ContinuumArtifactAuthorityError',
'EncryptionError',
'ForkError',
'IndexError',
diff --git a/test/unit/domain/index.exports.test.ts b/test/unit/domain/index.exports.test.ts
index 9e768ac7..c96d5be5 100644
--- a/test/unit/domain/index.exports.test.ts
+++ b/test/unit/domain/index.exports.test.ts
@@ -40,6 +40,7 @@ import WarpAppDefault, {
TraversalError,
OperationAbortedError,
Observer,
+ ContinuumArtifactAuthorityError,
// Cancellation utilities
checkAborted,
@@ -57,6 +58,11 @@ import WarpAppDefault, {
compareVisibleState,
normalizeVisibleStateScope,
scopeMaterializedState,
+ ContinuumArtifactAuthority,
+ ContinuumArtifactDescriptor,
+ ContinuumArtifactIngestionPolicy,
+ ContinuumFamilyId,
+ ContinuumArtifactJsonFileAdapter,
} from '../../../index.ts';
const { WarpGraph, WarpRuntime, Worldline, ObserverView } = (await import('../../../index.ts') as any);
@@ -244,6 +250,36 @@ describe('index.ts exports', () => {
expect(OperationAbortedError).toBeDefined();
expect(typeof OperationAbortedError).toBe('function');
});
+
+ it('exports ContinuumArtifactAuthorityError', () => {
+ expect(ContinuumArtifactAuthorityError).toBeDefined();
+ expect(typeof ContinuumArtifactAuthorityError).toBe('function');
+ });
+ });
+
+ describe('Continuum compatibility artifacts', () => {
+ it('exports the artifact descriptor classes', () => {
+ expect(ContinuumArtifactAuthority).toBeDefined();
+ expect(ContinuumArtifactDescriptor).toBeDefined();
+ expect(ContinuumArtifactIngestionPolicy).toBeDefined();
+ expect(ContinuumFamilyId).toBeDefined();
+ expect(ContinuumArtifactJsonFileAdapter).toBeDefined();
+ });
+
+ it('constructs a generated receipt-family descriptor from public exports', () => {
+ const descriptor = new ContinuumArtifactDescriptor({
+ familyId: 'receipt-family',
+ version: '0.1.0',
+ sourceSchemaPath: '~/git/continuum/schemas/continuum-receipt-family.graphql',
+ generatedBy: 'wesley witness-continuum --scope receipt-family',
+ artifactKind: 'continuum.family.fixture',
+ authority: 'generated-fixture',
+ targets: ['typescript'],
+ });
+
+ expect(descriptor.familyId).toBeInstanceOf(ContinuumFamilyId);
+ expect(descriptor.hasGeneratedAuthority()).toBe(true);
+ });
});
describe('cancellation utilities', () => {
diff --git a/test/unit/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.test.ts b/test/unit/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.test.ts
new file mode 100644
index 00000000..e1a08079
--- /dev/null
+++ b/test/unit/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.test.ts
@@ -0,0 +1,64 @@
+import { describe, expect, it } from 'vitest';
+import { fileURLToPath } from 'node:url';
+
+import ContinuumArtifactJsonFileAdapter from '../../../../src/infrastructure/adapters/ContinuumArtifactJsonFileAdapter.ts';
+import ContinuumArtifactAuthorityError from '../../../../src/domain/errors/ContinuumArtifactAuthorityError.ts';
+import AdapterValidationError from '../../../../src/domain/errors/AdapterValidationError.ts';
+
+const generatedFixtureJson = `{
+ "familyId": "receipt-family",
+ "version": "0.1.0",
+ "sourceSchemaPath": "~/git/continuum/schemas/continuum-receipt-family.graphql",
+ "generatedBy": "wesley witness-continuum --scope receipt-family",
+ "artifactKind": "continuum.family.fixture",
+ "authority": "generated-fixture",
+ "targets": ["typescript", "echo"],
+ "witnessScope": "receipt-family",
+ "artifactDigest": "sha256:receipt-fixture"
+}`;
+
+const localMirrorJson = `{
+ "familyId": "receipt-family",
+ "version": "0.1.0",
+ "sourceSchemaPath": "src/domain/continuum/local-receipt.ts",
+ "generatedBy": "git-warp",
+ "artifactKind": "continuum.family.fixture",
+ "authority": "local-mirror",
+ "targets": ["typescript"]
+}`;
+
+const generatedFixturePath = fileURLToPath(
+ new URL('../../../fixtures/continuum/receipt-family-generated-artifact.json', import.meta.url),
+);
+
+describe('ContinuumArtifactJsonFileAdapter', () => {
+ it('loads generated fixture descriptors', () => {
+ const adapter = new ContinuumArtifactJsonFileAdapter();
+ const descriptor = adapter.loadString(generatedFixtureJson);
+
+ expect(descriptor.familyId.toString()).toBe('receipt-family');
+ expect(descriptor.hasTarget('typescript')).toBe(true);
+ expect(descriptor.hasGeneratedAuthority()).toBe(true);
+ expect(descriptor.artifactDigest).toBe('sha256:receipt-fixture');
+ });
+
+ it('loads generated fixture descriptor files', async () => {
+ const adapter = new ContinuumArtifactJsonFileAdapter();
+ const descriptor = await adapter.loadFile(generatedFixturePath);
+
+ expect(descriptor.familyId.toString()).toBe('receipt-family');
+ expect(descriptor.witnessScope).toBe('receipt-family');
+ });
+
+ it('rejects local mirrors before they become authority', () => {
+ const adapter = new ContinuumArtifactJsonFileAdapter();
+
+ expect(() => adapter.loadString(localMirrorJson)).toThrow(ContinuumArtifactAuthorityError);
+ });
+
+ it('rejects malformed descriptor JSON', () => {
+ const adapter = new ContinuumArtifactJsonFileAdapter();
+
+ expect(() => adapter.loadString('{ "familyId": "receipt-family" }')).toThrow(AdapterValidationError);
+ });
+});