+If you are evaluating the system seriously, read the security and threat-model
+docs before designing around encrypted storage behavior.
diff --git a/docs/BACKLOG/README.md b/docs/BACKLOG/README.md
index a6af255..bfb5c03 100644
--- a/docs/BACKLOG/README.md
+++ b/docs/BACKLOG/README.md
@@ -32,8 +32,7 @@ Current backlog items:
- [TR-005 — CasService Decomposition Plan](./TR-005-casservice-decomposition-plan.md)
- [TR-008 — Empty-State Phrasing Consistency](./TR-008-empty-state-phrasing-consistency.md)
- [TR-011 — Streaming Encrypted Restore](./TR-011-streaming-encrypted-restore.md)
-- [TR-012 — Examples Surface Audit](./TR-012-examples-surface-audit.md)
-- [TR-014 — Markdown Surface Rationalization](./TR-014-markdown-surface-rationalization.md)
+- [TR-015 — Platform-Agnostic CLI Plan](./TR-015-platform-agnostic-cli-plan.md)
Archived delivered backlog items:
diff --git a/docs/BACKLOG/TR-015-platform-agnostic-cli-plan.md b/docs/BACKLOG/TR-015-platform-agnostic-cli-plan.md
new file mode 100644
index 0000000..404b388
--- /dev/null
+++ b/docs/BACKLOG/TR-015-platform-agnostic-cli-plan.md
@@ -0,0 +1,61 @@
+# TR-015 — Platform-Agnostic CLI Plan
+
+## Legend
+
+- [TR — Truth](../legends/TR-truth.md)
+
+## Why This Exists
+
+`git-cas` already maintains a real Node, Bun, and Deno test matrix, but the
+human CLI entrypoint is still a Node-specific launcher.
+
+[bin/git-cas.js](../../bin/git-cas.js) depends directly on:
+
+- the `#!/usr/bin/env node` launcher model
+- `node:` built-ins for file, path, URL, and readline behavior
+- direct `process` access for argv, env, stdin, stdout, and stderr
+- Node-oriented file helpers and prompt flows under `bin/` and `src/`
+
+That means the repo is closer to "runtime-tested core with a Node CLI" than to
+"portable command surface with multiple distribution options."
+
+## Target Outcome
+
+Produce a design-backed plan for making the CLI runtime-neutral at the command
+core while being honest about distribution realities, including:
+
+- what must move out of the Node-specific launcher
+- what runtime adapter boundary should exist for argv, stdio, prompts, file
+ access, and exit behavior
+- whether file-backed store/restore helpers should stay Node-only or move
+ behind a portable interface
+- what `@git-stunts/plumbing` assumptions still block true portability
+- how per-platform packaged binaries should follow once the runtime boundary is
+ clean
+
+## Human Value
+
+Maintainers should be able to reason clearly about what "platform agnostic"
+means here, what work is required to get there, and whether the repo should aim
+for multi-runtime source portability, compiled binaries, or both.
+
+## Agent Value
+
+Agents should be able to propose bounded follow-on work around CLI portability
+without hand-waving past the current Node-specific launcher, TTY helpers, and
+Git runner assumptions.
+
+## Linked Invariants
+
+- [I-001 — Determinism, Trust, And Explicit Surfaces](../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
+
+## Notes
+
+- distinguish runtime-agnostic command logic from platform-specific binary
+ packaging
+- prefer a small runtime adapter boundary over scattering `globalThis.Bun` /
+ `globalThis.Deno` checks throughout command code
+- treat Git runner behavior and subprocess semantics as first-class constraints,
+ not an afterthought
+- do not promise a single universal binary; prefer a portable codebase with
+ explicit per-platform artifacts if packaging is pursued
diff --git a/docs/MARKDOWN_SURFACE.md b/docs/MARKDOWN_SURFACE.md
new file mode 100644
index 0000000..666065d
--- /dev/null
+++ b/docs/MARKDOWN_SURFACE.md
@@ -0,0 +1,205 @@
+# Markdown Surface Map
+
+This document audits the tracked Markdown surface in `git-cas` and makes an
+explicit recommendation for each file:
+
+- `KEEP` — the file belongs where it is
+- `CUT` — the file should stop existing in its current tracked form
+- `MERGE` — the file's value should move into one or more other docs
+- `MOVE` — the file should live elsewhere in the repo
+
+More than one recommendation can apply at once.
+
+## Root Policy
+
+The repo root should contain only a small set of high-traffic, front-door, or
+canonical project docs:
+
+- package/front-door docs
+- contributor and workflow docs
+- security and architecture docs
+- release history
+
+Planning history, archive material, long-form tutorials, and tool-specific
+instruction files should prefer `docs/`, `docs/archive/`, or local-only
+surfaces.
+
+## Root Markdown
+
+- [README.md](../README.md): `KEEP` — package front door and adoption surface;
+ belongs at the repo root.
+- [CHANGELOG.md](../CHANGELOG.md): `KEEP` — canonical release history; belongs
+ at the repo root.
+- [CONTRIBUTING.md](../CONTRIBUTING.md): `KEEP` — contributor doctrine and
+ onboarding surface; belongs at the repo root.
+- [SECURITY.md](../SECURITY.md): `KEEP` — canonical security guidance and
+ vulnerability-routing surface; belongs at the repo root.
+- [WORKFLOW.md](../WORKFLOW.md): `KEEP` — planning and delivery model for fresh
+ work; belongs at the repo root.
+- [ARCHITECTURE.md](../ARCHITECTURE.md): `KEEP` — canonical high-level
+ architecture map; still useful as a root-level reference.
+- [ROADMAP.md](../ROADMAP.md): `MOVE`, `CUT` — useful as migration and sequence
+ context today, but too specialized and too drift-prone for permanent
+ root-level residency.
+- [STATUS.md](../STATUS.md): `MERGE`, `CUT` — compact snapshot value is real,
+ but it largely overlaps with the README, roadmap, and changelog.
+- [GRAVEYARD.md](../GRAVEYARD.md): `KEEP`, `MOVE` — still useful historical
+ context, but it belongs under `docs/archive/` instead of the repo root.
+- [CLAUDE.md](../CLAUDE.md): `CUT`, `MOVE` — tool-specific instruction files
+ should not occupy tracked root doctrine alongside canonical project docs.
+
+## Canonical Docs Under `docs/`
+
+- [docs/API.md](./API.md): `KEEP` — canonical API reference; belongs under
+ `docs/`.
+- [docs/THREAT_MODEL.md](./THREAT_MODEL.md): `KEEP` — canonical threat model;
+ belongs under `docs/`.
+- [docs/BENCHMARKS.md](./BENCHMARKS.md): `KEEP` — benchmark guidance and
+ published baselines belong under `docs/`.
+- [docs/RELEASE.md](./RELEASE.md): `KEEP` — release runbook belongs under
+ `docs/`.
+- [docs/DOCS_CHECKLIST.md](./DOCS_CHECKLIST.md): `KEEP` — maintainer-facing docs
+ review checklist belongs under `docs/`.
+- [docs/GUIDE.md](./GUIDE.md): `KEEP` — the long-form tutorial should exist, but
+ under `docs/`, not at the repo root.
+- [docs/ADR-001-vault-in-facade.md](./ADR-001-vault-in-facade.md): `KEEP` —
+ accepted architecture decision record; current placement is fine until there
+ is a broader ADR collection.
+- [docs/MARKDOWN_SURFACE.md](./MARKDOWN_SURFACE.md): `KEEP` — this audit belongs
+ under `docs/` as repo-maintainer guidance, not at the root.
+
+## Live Planning Surface
+
+- [docs/BACKLOG/README.md](./BACKLOG/README.md): `KEEP` — canonical live backlog
+ index.
+- [docs/BACKLOG/TR-005-casservice-decomposition-plan.md](./BACKLOG/TR-005-casservice-decomposition-plan.md):
+ `KEEP` — active backlog work item.
+- [docs/BACKLOG/TR-008-empty-state-phrasing-consistency.md](./BACKLOG/TR-008-empty-state-phrasing-consistency.md):
+ `KEEP` — active backlog work item.
+- [docs/BACKLOG/TR-011-streaming-encrypted-restore.md](./BACKLOG/TR-011-streaming-encrypted-restore.md):
+ `KEEP` — active backlog work item.
+- [docs/BACKLOG/TR-015-platform-agnostic-cli-plan.md](./BACKLOG/TR-015-platform-agnostic-cli-plan.md):
+ `KEEP` — active backlog work item.
+
+## Landed Design Surface
+
+- [docs/design/README.md](./design/README.md): `KEEP` — canonical landed design
+ index.
+- [docs/design/0001-m18-relay-agent-cli.md](./design/0001-m18-relay-agent-cli.md):
+ `KEEP` — legacy-named landed cycle history; retain until touched.
+- [docs/design/0002-m18-relay-write-flows.md](./design/0002-m18-relay-write-flows.md):
+ `KEEP` — legacy-named landed cycle history; retain until touched.
+- [docs/design/0003-m18-relay-tree-creation.md](./design/0003-m18-relay-tree-creation.md):
+ `KEEP` — legacy-named landed cycle history; retain until touched.
+- [docs/design/RL-001-agent-recipient-list.md](./design/RL-001-agent-recipient-list.md):
+ `KEEP` — landed cycle history.
+- [docs/design/RL-002-agent-recipient-mutations.md](./design/RL-002-agent-recipient-mutations.md):
+ `KEEP` — landed cycle history.
+- [docs/design/RL-003-agent-rotate.md](./design/RL-003-agent-rotate.md):
+ `KEEP` — landed cycle history.
+- [docs/design/RL-004-agent-vault-rotate.md](./design/RL-004-agent-vault-rotate.md):
+ `KEEP` — landed cycle history.
+- [docs/design/RL-005-agent-vault-lifecycle.md](./design/RL-005-agent-vault-lifecycle.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-001-architecture-reality-gap.md](./design/TR-001-architecture-reality-gap.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-002-threat-model.md](./design/TR-002-threat-model.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-003-benchmark-baselines.md](./design/TR-003-benchmark-baselines.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-004-design-doc-lifecycle.md](./design/TR-004-design-doc-lifecycle.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-006-docs-maintainer-checklist.md](./design/TR-006-docs-maintainer-checklist.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-007-security-doc-discoverability-audit.md](./design/TR-007-security-doc-discoverability-audit.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-009-pre-pr-doc-cross-link-audit.md](./design/TR-009-pre-pr-doc-cross-link-audit.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-010-planning-index-consistency-review.md](./design/TR-010-planning-index-consistency-review.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-012-examples-surface-audit.md](./design/TR-012-examples-surface-audit.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-013-guide-accuracy-audit.md](./design/TR-013-guide-accuracy-audit.md):
+ `KEEP` — landed cycle history.
+- [docs/design/TR-014-markdown-surface-rationalization.md](./design/TR-014-markdown-surface-rationalization.md):
+ `KEEP` — landed cycle history.
+
+## Archive And Historical Intent
+
+- [docs/archive/README.md](./archive/README.md): `KEEP` — archive entrypoint.
+- [docs/archive/design/README.md](./archive/design/README.md): `KEEP` — reserved
+ archive surface for retired design docs.
+- [docs/archive/BACKLOG/README.md](./archive/BACKLOG/README.md): `KEEP` —
+ canonical archive index for retired backlog cards.
+- [docs/archive/BACKLOG/RL-001-agent-recipient-list.md](./archive/BACKLOG/RL-001-agent-recipient-list.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/RL-002-agent-recipient-mutations.md](./archive/BACKLOG/RL-002-agent-recipient-mutations.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/RL-003-agent-rotate.md](./archive/BACKLOG/RL-003-agent-rotate.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/RL-004-agent-vault-rotate.md](./archive/BACKLOG/RL-004-agent-vault-rotate.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/RL-005-agent-vault-lifecycle.md](./archive/BACKLOG/RL-005-agent-vault-lifecycle.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-001-architecture-reality-gap.md](./archive/BACKLOG/TR-001-architecture-reality-gap.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-002-threat-model.md](./archive/BACKLOG/TR-002-threat-model.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-003-benchmark-baselines.md](./archive/BACKLOG/TR-003-benchmark-baselines.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-004-design-doc-lifecycle.md](./archive/BACKLOG/TR-004-design-doc-lifecycle.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-006-docs-maintainer-checklist.md](./archive/BACKLOG/TR-006-docs-maintainer-checklist.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-007-security-doc-discoverability-audit.md](./archive/BACKLOG/TR-007-security-doc-discoverability-audit.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-009-pre-pr-doc-cross-link-audit.md](./archive/BACKLOG/TR-009-pre-pr-doc-cross-link-audit.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-010-planning-index-consistency-review.md](./archive/BACKLOG/TR-010-planning-index-consistency-review.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-012-examples-surface-audit.md](./archive/BACKLOG/TR-012-examples-surface-audit.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-013-guide-accuracy-audit.md](./archive/BACKLOG/TR-013-guide-accuracy-audit.md):
+ `KEEP` — archived historical intent.
+- [docs/archive/BACKLOG/TR-014-markdown-surface-rationalization.md](./archive/BACKLOG/TR-014-markdown-surface-rationalization.md):
+ `KEEP` — archived historical intent.
+
+## Invariants And Legends
+
+- [docs/invariants/README.md](./invariants/README.md): `KEEP` — invariants index.
+- [docs/invariants/I-001-determinism-trust-and-explicit-surfaces.md](./invariants/I-001-determinism-trust-and-explicit-surfaces.md):
+ `KEEP` — active project invariant.
+- [docs/legends/README.md](./legends/README.md): `KEEP` — legend index.
+- [docs/legends/RL-relay.md](./legends/RL-relay.md): `KEEP` — active legend doc.
+- [docs/legends/TR-truth.md](./legends/TR-truth.md): `KEEP` — active legend doc.
+
+## Examples And Test Doctrine
+
+- [examples/README.md](../examples/README.md): `KEEP` — examples index is useful,
+ and now reflects the maintained examples surface audit.
+- [test/CONVENTIONS.md](../test/CONVENTIONS.md): `KEEP` — test doctrine belongs
+ near the test surface.
+- [test/cycles/README.md](../test/cycles/README.md): `KEEP` — cycle-owned test
+ directory contract belongs near the test surface.
+
+## Local-Only And Non-Tracked Markdown
+
+These files are not part of the tracked Markdown audit and should remain out of
+the canonical tracked doctrine surface unless the repo makes an explicit policy
+change:
+
+- `AGENTS.md`
+- `EDITORS-REPORT.md`
+- `.claude/bad_code.md`
+- `.claude/cool_ideas.md`
+
+## Immediate Follow-On Priorities
+
+If the repo wants to act on this audit, the highest-value next changes are:
+
+1. move [GRAVEYARD.md](../GRAVEYARD.md) under `docs/archive/`
+2. decide whether [CLAUDE.md](../CLAUDE.md) should leave tracked root entirely
+3. collapse [STATUS.md](../STATUS.md) into other canonical surfaces and remove
+ the duplicate snapshot doc
+4. shrink and relocate [ROADMAP.md](../ROADMAP.md) once its remaining migration
+ value is absorbed elsewhere
diff --git a/docs/archive/BACKLOG/README.md b/docs/archive/BACKLOG/README.md
index e464700..4d6dc17 100644
--- a/docs/archive/BACKLOG/README.md
+++ b/docs/archive/BACKLOG/README.md
@@ -33,5 +33,9 @@ Landed archived backlog items:
- landed as [TR-009 — Truth: Pre-PR Doc Cross-Link Audit](../../design/TR-009-pre-pr-doc-cross-link-audit.md)
- [TR-010 — Planning Index Consistency Review](./TR-010-planning-index-consistency-review.md)
- landed as [TR-010 — Truth: Planning Index Consistency Review](../../design/TR-010-planning-index-consistency-review.md)
+- [TR-012 — Examples Surface Audit](./TR-012-examples-surface-audit.md)
+ - landed as [TR-012 — Truth: Examples Surface Audit](../../design/TR-012-examples-surface-audit.md)
- [TR-013 — Guide Accuracy Audit](./TR-013-guide-accuracy-audit.md)
- landed as [TR-013 — Truth: Guide Accuracy Audit](../../design/TR-013-guide-accuracy-audit.md)
+- [TR-014 — Markdown Surface Rationalization](./TR-014-markdown-surface-rationalization.md)
+ - landed as [TR-014 — Truth: Markdown Surface Rationalization](../../design/TR-014-markdown-surface-rationalization.md)
diff --git a/docs/BACKLOG/TR-012-examples-surface-audit.md b/docs/archive/BACKLOG/TR-012-examples-surface-audit.md
similarity index 86%
rename from docs/BACKLOG/TR-012-examples-surface-audit.md
rename to docs/archive/BACKLOG/TR-012-examples-surface-audit.md
index 7f0513c..b46a649 100644
--- a/docs/BACKLOG/TR-012-examples-surface-audit.md
+++ b/docs/archive/BACKLOG/TR-012-examples-surface-audit.md
@@ -2,7 +2,7 @@
## Legend
-- [TR — Truth](../legends/TR-truth.md)
+- [TR — Truth](../../legends/TR-truth.md)
## Why This Exists
@@ -35,7 +35,7 @@ which ones still belong in the repo and why.
## Linked Invariants
-- [I-001 — Determinism, Trust, And Explicit Surfaces](../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
+- [I-001 — Determinism, Trust, And Explicit Surfaces](../../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
## Notes
diff --git a/docs/BACKLOG/TR-014-markdown-surface-rationalization.md b/docs/archive/BACKLOG/TR-014-markdown-surface-rationalization.md
similarity index 88%
rename from docs/BACKLOG/TR-014-markdown-surface-rationalization.md
rename to docs/archive/BACKLOG/TR-014-markdown-surface-rationalization.md
index 3f76a30..3b5bf7c 100644
--- a/docs/BACKLOG/TR-014-markdown-surface-rationalization.md
+++ b/docs/archive/BACKLOG/TR-014-markdown-surface-rationalization.md
@@ -2,7 +2,7 @@
## Legend
-- [TR — Truth](../legends/TR-truth.md)
+- [TR — Truth](../../legends/TR-truth.md)
## Why This Exists
@@ -40,7 +40,7 @@ equal apparent status.
## Linked Invariants
-- [I-001 — Determinism, Trust, And Explicit Surfaces](../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
+- [I-001 — Determinism, Trust, And Explicit Surfaces](../../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
## Notes
diff --git a/docs/design/README.md b/docs/design/README.md
index 23c771e..c6238c3 100644
--- a/docs/design/README.md
+++ b/docs/design/README.md
@@ -47,7 +47,9 @@ Landed cycle docs:
- [TR-007 — Truth: Security Doc Discoverability Audit](./TR-007-security-doc-discoverability-audit.md)
- [TR-009 — Truth: Pre-PR Doc Cross-Link Audit](./TR-009-pre-pr-doc-cross-link-audit.md)
- [TR-010 — Truth: Planning Index Consistency Review](./TR-010-planning-index-consistency-review.md)
+- [TR-012 — Truth: Examples Surface Audit](./TR-012-examples-surface-audit.md)
- [TR-013 — Truth: Guide Accuracy Audit](./TR-013-guide-accuracy-audit.md)
+- [TR-014 — Truth: Markdown Surface Rationalization](./TR-014-markdown-surface-rationalization.md)
Archived or retired cycle docs:
diff --git a/docs/design/TR-012-examples-surface-audit.md b/docs/design/TR-012-examples-surface-audit.md
new file mode 100644
index 0000000..facbe94
--- /dev/null
+++ b/docs/design/TR-012-examples-surface-audit.md
@@ -0,0 +1,148 @@
+# TR-012 — Truth: Examples Surface Audit
+
+## Status
+
+Landed
+
+## Linked Legend
+
+- [TR — Truth](../legends/TR-truth.md)
+
+## Linked Invariants
+
+- [I-001 — Determinism, Trust, And Explicit Surfaces](../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
+
+## Context
+
+The `examples/` directory is part of the repo's teaching surface, not just a
+miscellaneous folder of throwaway scripts.
+
+That means it has the same truth burden as the rest of the docs:
+
+- examples should use current public APIs
+- examples should not teach stale internal access patterns
+- the example index should say which files are still maintained and why
+
+Before this cycle, the examples surface had drifted:
+
+- `examples/README.md` still taught manual manifest decoding via service
+ internals
+- the README still described progress tracking as if `CasService` itself were
+ the event surface
+- `store-and-restore.js` still demonstrated the older internal manifest-read
+ path instead of `readManifest()`
+
+## Human Users, Jobs, And Hills
+
+### Users
+
+- maintainers
+- adopters reading examples before the API reference
+- contributors checking whether examples still represent current usage
+
+### Jobs
+
+- trust that examples still teach maintained public APIs
+- tell which examples remain worth keeping
+- avoid copying internal or stale patterns into new code
+
+### Hill
+
+A maintainer or adopter can run the examples and learn current `git-cas`
+workflows without inheriting stale internal access patterns.
+
+## Agent Users, Jobs, And Hills
+
+### Users
+
+- coding agents
+- review agents
+- documentation agents
+
+### Jobs
+
+- reason about which examples are maintained and what they teach
+- repair or cite examples without treating stale patterns as canonical
+- distinguish between public facade helpers and internal service plumbing
+
+### Hill
+
+An agent can use the examples surface as a maintained teaching aid instead of a
+historical code dump.
+
+## Human Playback
+
+- Does `examples/README.md` now state which example files are kept and why?
+- Do the maintained examples use current public APIs instead of internal
+ manifest-decoding patterns?
+- Is the progress example described through `EventEmitterObserver` rather than
+ a stale EventEmitter claim about `CasService`?
+
+## Agent Playback
+
+- Can an agent tell which example files are worth keeping?
+- Do the repaired examples favor public package entrypoints and public helpers?
+- Does the examples surface now align with the guide and API docs more closely?
+
+## Explicit Non-Goals
+
+- no attempt to add a large new example suite
+- no conversion of examples into tested fixtures or integration tests in this
+ cycle
+- no removal of examples that are still accurate enough to teach current usage
+
+## Decisions
+
+### Keep The Current Example Set
+
+The current set is still small and useful:
+
+- `store-and-restore.js`
+- `encrypted-workflow.js`
+- `progress-tracking.js`
+
+No file currently needs to be cut or moved.
+
+### Refresh The Example Index
+
+`examples/README.md` should explicitly record the recommendation for each file
+and should stop teaching stale internals in its reference snippets.
+
+### Prefer Public Helpers Over Internal Plumbing
+
+Where the public facade already provides a helper, the examples should prefer
+that helper. `readManifest()` is the right example for tree-to-manifest reads.
+
+## Implementation Outline
+
+1. Audit `examples/README.md` and the three example programs.
+2. Refresh the README with per-file recommendations and current API guidance.
+3. Repair `store-and-restore.js` to use `readManifest()`.
+4. Add this cycle doc, archive the consumed backlog card, update the Truth
+ indexes, and record the cycle in [CHANGELOG.md](../../CHANGELOG.md).
+
+## Tests To Write First
+
+No new automated tests.
+
+This cycle verifies the examples directly:
+
+- run the example scripts under Node
+- validate formatting and whitespace on touched files
+- run the repo lint and test gates after code changes
+
+## Risks And Unknowns
+
+- examples can still drift later if they are not treated as a maintained docs
+ surface
+- the examples are Node-oriented and do not themselves prove Bun or Deno example
+ ergonomics
+- future API changes may create pressure to split examples by audience or
+ runtime
+
+## Retrospective
+
+This was the right next cycle after rationalizing the Markdown surface.
+
+The examples did not need expansion. They needed a truth pass so the repo stops
+teaching stale internal patterns through supposedly friendly entrypoint code.
diff --git a/docs/design/TR-014-markdown-surface-rationalization.md b/docs/design/TR-014-markdown-surface-rationalization.md
new file mode 100644
index 0000000..8d7b78d
--- /dev/null
+++ b/docs/design/TR-014-markdown-surface-rationalization.md
@@ -0,0 +1,149 @@
+# TR-014 — Truth: Markdown Surface Rationalization
+
+## Status
+
+Landed
+
+## Linked Legend
+
+- [TR — Truth](../legends/TR-truth.md)
+
+## Linked Invariants
+
+- [I-001 — Determinism, Trust, And Explicit Surfaces](../invariants/I-001-determinism-trust-and-explicit-surfaces.md)
+
+## Context
+
+The repo had already fixed several individual documentation truth gaps:
+
+- stale architecture truth
+- missing threat model
+- benchmark publication
+- design lifecycle clarity
+- docs-review checklist and cross-link audits
+- guide placement and guide accuracy
+
+What was still missing was one explicit map of the Markdown surface itself.
+
+Without that, each docs-heavy review had to rediscover the same questions:
+
+- which files actually belong at the repo root
+- which ones are canonical versus migration surfaces
+- which ones should be cut, merged, or moved instead of kept indefinitely
+
+## Human Users, Jobs, And Hills
+
+### Users
+
+- maintainers
+- contributors opening docs-heavy pull requests
+- reviewers trying to judge whether a file belongs where it is
+
+### Jobs
+
+- see the whole tracked Markdown surface at once
+- distinguish canonical docs from migration and archive surfaces
+- make future cut/move/merge decisions from one explicit map instead of memory
+
+### Hill
+
+A maintainer can look at one repo-native document and tell where each tracked
+Markdown file belongs, whether it should stay, and which root-level artifacts
+still need follow-on cleanup.
+
+## Agent Users, Jobs, And Hills
+
+### Users
+
+- coding agents
+- review agents
+- documentation agents
+
+### Jobs
+
+- reason about the Markdown surface without treating every file as equally
+ canonical
+- plan docs changes from explicit keep/cut/merge/move recommendations
+- stop rediscovering root-versus-docs placement policy on every branch
+
+### Hill
+
+An agent can use one tracked Markdown-surface map as the repo's current
+placement and rationalization reference.
+
+## Human Playback
+
+- Is there now one explicit Markdown-surface map with a recommendation for each
+ tracked Markdown file?
+- Does it say which artifacts belong at the root and which do not?
+- Does it separate canonical, planning, archive, and local-only surfaces
+ clearly?
+
+## Agent Playback
+
+- Can an agent tell which Markdown files are canonical, archival, migration, or
+ tool-specific?
+- Does the audit cover tracked files broadly enough to avoid branch-local
+ guesswork?
+- Does it make future move/cut/merge work easier without performing all of it
+ prematurely?
+
+## Explicit Non-Goals
+
+- no attempt to execute every recommended move or cut in this cycle
+- no full content-accuracy rewrite of every Markdown file in the repo
+- no destruction of useful planning or archive history
+
+## Decisions
+
+### Publish One Explicit Markdown-Surface Map
+
+The repo should have one tracked Markdown-surface audit at
+[docs/MARKDOWN_SURFACE.md](../MARKDOWN_SURFACE.md) instead of leaving these
+placement decisions implicit.
+
+### Keep The Audit File-Specific
+
+This cycle should make a recommendation for each tracked Markdown file, not
+just broad directory-level guidance. That keeps the result actionable for both
+humans and agents.
+
+### Separate Placement Guidance From Execution
+
+The audit should identify candidates for `CUT`, `MERGE`, and `MOVE` without
+trying to execute every recommendation at once. That keeps the cycle honest and
+reviewable.
+
+## Implementation Outline
+
+1. Add [docs/MARKDOWN_SURFACE.md](../MARKDOWN_SURFACE.md) with per-file
+ recommendations across the tracked Markdown surface.
+2. Add this cycle doc.
+3. Archive the consumed backlog card, update the Truth indexes, and record the
+ audit in [CHANGELOG.md](../../CHANGELOG.md).
+
+## Tests To Write First
+
+No new executable tests.
+
+This is a documentation-truth cycle. Verification is:
+
+- cross-check against the tracked Markdown file inventory
+- formatting validation for touched Markdown files
+- planning-surface validation for backlog, archive, design, and legend updates
+
+## Risks And Unknowns
+
+- some recommendations may age as the repo evolves
+- the audit surfaces content-accuracy follow-ons it does not itself fix
+- tool-specific root files may require a separate policy decision before they
+ can be removed or relocated
+
+## Retrospective
+
+This cycle was necessary once the repo had enough documentation cleanup behind
+it to stop making purely local decisions.
+
+The repo now has an explicit Markdown placement map. That does not finish the
+cleanup, but it turns future cleanup into deliberate work instead of repeated
+review improvisation.
diff --git a/docs/git-cas-clay-loop.svg b/docs/git-cas-clay-loop.svg
new file mode 100644
index 0000000..7bdebf7
--- /dev/null
+++ b/docs/git-cas-clay-loop.svg
@@ -0,0 +1,59 @@
+
diff --git a/docs/git-cas-ember-loop.svg b/docs/git-cas-ember-loop.svg
new file mode 100644
index 0000000..2165dc7
--- /dev/null
+++ b/docs/git-cas-ember-loop.svg
@@ -0,0 +1,65 @@
+
diff --git a/docs/git-cas-honey-loop.svg b/docs/git-cas-honey-loop.svg
new file mode 100644
index 0000000..d237d63
--- /dev/null
+++ b/docs/git-cas-honey-loop.svg
@@ -0,0 +1,59 @@
+
diff --git a/docs/git-cas-ice-loop.svg b/docs/git-cas-ice-loop.svg
new file mode 100644
index 0000000..765125d
--- /dev/null
+++ b/docs/git-cas-ice-loop.svg
@@ -0,0 +1,47 @@
+
diff --git a/docs/git-cas-ivory-loop.svg b/docs/git-cas-ivory-loop.svg
new file mode 100644
index 0000000..e9f0a96
--- /dev/null
+++ b/docs/git-cas-ivory-loop.svg
@@ -0,0 +1,53 @@
+
diff --git a/docs/git-cas-moss-loop.svg b/docs/git-cas-moss-loop.svg
new file mode 100644
index 0000000..c017240
--- /dev/null
+++ b/docs/git-cas-moss-loop.svg
@@ -0,0 +1,41 @@
+
diff --git a/docs/git-cas-neon-loop.svg b/docs/git-cas-neon-loop.svg
new file mode 100644
index 0000000..e53c505
--- /dev/null
+++ b/docs/git-cas-neon-loop.svg
@@ -0,0 +1,65 @@
+
diff --git a/docs/git-cas-plum-loop.svg b/docs/git-cas-plum-loop.svg
new file mode 100644
index 0000000..c5597ac
--- /dev/null
+++ b/docs/git-cas-plum-loop.svg
@@ -0,0 +1,59 @@
+
diff --git a/docs/git-cas-preview.html b/docs/git-cas-preview.html
new file mode 100644
index 0000000..a580ea2
--- /dev/null
+++ b/docs/git-cas-preview.html
@@ -0,0 +1,284 @@
+
+
+
+
+
+ git-cas SVG Preview
+
+
+
+
+
+
+
Light Background
+
Each SVG stacked vertically on white.
+
+
+
+
git-cas.svg
+
+
+
+
git-cas-neon-loop.svg
+
+
+
+
git-cas-moss-loop.svg
+
+
+
+
git-cas-ice-loop.svg
+
+
+
+
git-cas-plum-loop.svg
+
+
+
+
git-cas-ember-loop.svg
+
+
+
+
git-cas-clay-loop.svg
+
+
+
+
git-cas-honey-loop.svg
+
+
+
+
git-cas-slate-loop.svg
+
+
+
+
git-cas-ivory-loop.svg
+
+
+
+
+
+
+
+
Dark Background
+
The same SVGs stacked vertically on black.
+
+
+
+
git-cas.svg
+
+
+
+
git-cas-neon-loop.svg
+
+
+
+
git-cas-moss-loop.svg
+
+
+
+
git-cas-ice-loop.svg
+
+
+
+
git-cas-plum-loop.svg
+
+
+
+
git-cas-ember-loop.svg
+
+
+
+
git-cas-clay-loop.svg
+
+
+
+
git-cas-honey-loop.svg
+
+
+
+
git-cas-slate-loop.svg
+
+
+
+
git-cas-ivory-loop.svg
+
+
+
+
+
+
+
diff --git a/docs/git-cas-slate-loop.svg b/docs/git-cas-slate-loop.svg
new file mode 100644
index 0000000..75f9550
--- /dev/null
+++ b/docs/git-cas-slate-loop.svg
@@ -0,0 +1,47 @@
+
diff --git a/docs/git-cas.svg b/docs/git-cas.svg
new file mode 100644
index 0000000..7a1d781
--- /dev/null
+++ b/docs/git-cas.svg
@@ -0,0 +1 @@
+
diff --git a/docs/legends/TR-truth.md b/docs/legends/TR-truth.md
index 4b6688b..d687b9b 100644
--- a/docs/legends/TR-truth.md
+++ b/docs/legends/TR-truth.md
@@ -79,15 +79,16 @@ Current Truth design docs:
- [TR-007 — Truth: Security Doc Discoverability Audit](../design/TR-007-security-doc-discoverability-audit.md)
- [TR-009 — Truth: Pre-PR Doc Cross-Link Audit](../design/TR-009-pre-pr-doc-cross-link-audit.md)
- [TR-010 — Truth: Planning Index Consistency Review](../design/TR-010-planning-index-consistency-review.md)
+- [TR-012 — Truth: Examples Surface Audit](../design/TR-012-examples-surface-audit.md)
- [TR-013 — Truth: Guide Accuracy Audit](../design/TR-013-guide-accuracy-audit.md)
+- [TR-014 — Truth: Markdown Surface Rationalization](../design/TR-014-markdown-surface-rationalization.md)
Current Truth backlog items:
- [TR-005 — CasService Decomposition Plan](../BACKLOG/TR-005-casservice-decomposition-plan.md)
- [TR-008 — Empty-State Phrasing Consistency](../BACKLOG/TR-008-empty-state-phrasing-consistency.md)
- [TR-011 — Streaming Encrypted Restore](../BACKLOG/TR-011-streaming-encrypted-restore.md)
-- [TR-012 — Examples Surface Audit](../BACKLOG/TR-012-examples-surface-audit.md)
-- [TR-014 — Markdown Surface Rationalization](../BACKLOG/TR-014-markdown-surface-rationalization.md)
+- [TR-015 — Platform-Agnostic CLI Plan](../BACKLOG/TR-015-platform-agnostic-cli-plan.md)
Truth work under this legend is currently focused on:
@@ -100,10 +101,16 @@ Truth work under this legend is currently focused on:
- improving security doc discoverability from high-traffic repo surfaces
- keeping the long-form guide accurate and positioned as a docs surface instead
of a root-level front door
+- keeping the examples surface aligned with current public APIs instead of
+ stale internal helper paths
+- making the tracked Markdown surface explicit so root, docs, archive, and
+ local-only placement decisions stop living only in memory
- running a lightweight pre-PR doc cross-link audit on doc-heavy branches
- running planning-index consistency reviews and keeping empty-state language
consistent over time
- investigating lower-memory restore paths for encrypted and compressed assets
+- defining a runtime-neutral CLI boundary before promising broader
+ cross-platform binary distribution
## Explicit Non-Goals
diff --git a/examples/README.md b/examples/README.md
index 015462f..7113149 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -2,6 +2,15 @@
This directory contains runnable examples demonstrating the core features of `@git-stunts/git-cas`.
+Audit status:
+
+| File | Recommendation | Notes |
+| -------------------------------- | -------------- | --------------------------------------------------------------------------------------------- |
+| `examples/README.md` | Keep, refresh | Canonical index for the examples surface; keep it accurate and scoped to maintained examples. |
+| `examples/store-and-restore.js` | Keep, refresh | Good first example; now uses the public `readManifest()` helper for tree-to-manifest reads. |
+| `examples/encrypted-workflow.js` | Keep | Still a useful end-to-end encryption example with current public APIs. |
+| `examples/progress-tracking.js` | Keep | Still the right observability example now that it teaches `EventEmitterObserver`. |
+
## Prerequisites
- Node.js 22 or later
@@ -37,19 +46,21 @@ node progress-tracking.js
**Demonstrates:** Basic CAS workflow with verification
This example shows the complete lifecycle of storing and restoring a file:
+
1. Creates a temporary Git bare repository
2. Stores a file in the content-addressable store
3. Creates a Git tree to persist the manifest
-4. Reads the manifest back from the tree
+4. Reads the manifest back from the tree with the public `readManifest()` helper
5. Restores the file to disk
6. Verifies the restored content matches the original
7. Runs integrity verification on the stored chunks
**Key concepts:**
+
- `ContentAddressableStore.createJson()` factory
- `storeFile()` to store files
- `createTree()` to persist manifests in Git
-- Reading manifests from Git trees
+- `readManifest()` to reconstruct manifests from Git trees
- `restoreFile()` to write files back to disk
- `verifyIntegrity()` to check chunk digests
@@ -58,6 +69,7 @@ This example shows the complete lifecycle of storing and restoring a file:
**Demonstrates:** Encryption and decryption with AES-256-GCM
This example shows how to work with encrypted content:
+
1. Generates a secure 32-byte encryption key
2. Stores a file with encryption enabled
3. Restores the file using the correct key
@@ -65,6 +77,7 @@ This example shows how to work with encrypted content:
5. Shows the encryption metadata stored in the manifest
**Key concepts:**
+
- Generating encryption keys with `crypto.randomBytes(32)`
- Storing encrypted files with `encryptionKey` parameter
- Encryption metadata in manifests
@@ -75,10 +88,12 @@ This example shows how to work with encrypted content:
**Demonstrates:** Event-driven progress monitoring
-This example shows how to track storage and restore operations using Node.js EventEmitter:
-1. Accesses the CasService via `cas.getService()`
-2. Attaches event listeners for various operations
-3. Builds a progress logger that tracks:
+This example shows how to track storage and restore operations using `EventEmitterObserver`:
+
+1. Creates an `EventEmitterObserver`
+2. Passes it into `ContentAddressableStore` via the `observability` option
+3. Attaches event listeners to the observer
+4. Builds a progress logger that tracks:
- Chunk storage progress
- File storage completion
- Chunk restoration progress
@@ -86,7 +101,8 @@ This example shows how to track storage and restore operations using Node.js Eve
- Integrity verification results
**Key concepts:**
-- Accessing the underlying CasService
+
+- `EventEmitterObserver` as the backward-compatible event bridge
- Event types: `chunk:stored`, `file:stored`, `chunk:restored`, `file:restored`, `integrity:pass`, `integrity:fail`, `error`
- Building real-time progress indicators
- Calculating percentages based on chunk counts
@@ -111,7 +127,7 @@ const manifest = await cas.storeFile({
filePath: '/path/to/file',
slug: 'unique-identifier',
filename: 'optional-name.txt',
- encryptionKey: optionalKeyBuffer // 32-byte Buffer
+ encryptionKey: optionalKeyBuffer, // 32-byte Buffer
});
// Create a Git tree
@@ -125,13 +141,13 @@ const treeOid = await cas.createTree({ manifest });
await cas.restoreFile({
manifest,
encryptionKey: optionalKeyBuffer,
- outputPath: '/path/to/output'
+ outputPath: '/path/to/output',
});
// Restore to memory (returns Buffer)
const { buffer, bytesWritten } = await cas.restore({
manifest,
- encryptionKey: optionalKeyBuffer
+ encryptionKey: optionalKeyBuffer,
});
```
@@ -145,19 +161,7 @@ const isValid = await cas.verifyIntegrity(manifest);
### Reading Manifests from Trees
```javascript
-// Get the service
-const service = await cas.getService();
-
-// Read tree entries
-const entries = await service.persistence.readTree(treeOid);
-
-// Find manifest entry
-const manifestEntry = entries.find(e => e.name === 'manifest.json');
-
-// Read and decode manifest blob
-const manifestBlob = await service.persistence.readBlob(manifestEntry.oid);
-const manifestData = service.codec.decode(manifestBlob);
-const manifest = new Manifest(manifestData);
+const manifest = await cas.readManifest({ treeOid });
```
## Encryption Keys
@@ -179,20 +183,23 @@ const key = randomBytes(32);
- All examples clean up temporary files and directories
- The examples use temporary Git bare repositories to avoid polluting your working directory
- Chunk size defaults to 256 KiB (262,144 bytes)
-- File paths must be absolute paths, not relative paths
-- The CAS service extends EventEmitter for progress tracking
+- Relative file paths are fine; these examples happen to use temporary absolute paths
+- Progress events are exposed through `EventEmitterObserver`, not by subscribing directly to `CasService`
## Troubleshooting
**Error: "Encryption key must be 32 bytes"**
+
- Ensure your encryption key is exactly 32 bytes
- Use `crypto.randomBytes(32)` or equivalent
**Error: "INTEGRITY_ERROR"**
+
- Using wrong decryption key
- Chunk corruption in Git object database
- Run `verifyIntegrity()` to identify corrupted chunks
**Error: "MISSING_KEY"**
+
- Attempting to restore encrypted content without providing the key
- Check if `manifest.encryption.encrypted === true`
diff --git a/examples/store-and-restore.js b/examples/store-and-restore.js
index 4f0a111..8aab547 100755
--- a/examples/store-and-restore.js
+++ b/examples/store-and-restore.js
@@ -17,7 +17,7 @@ import { execSync } from 'node:child_process';
import path from 'node:path';
import os from 'node:os';
import GitPlumbing from '@git-stunts/plumbing';
-import ContentAddressableStore, { Manifest } from '@git-stunts/git-cas';
+import ContentAddressableStore from '@git-stunts/git-cas';
console.log('=== Store and Restore Example ===\n');
@@ -44,7 +44,7 @@ console.log('\n--- Step 1: Storing file ---');
const manifest = await cas.storeFile({
filePath: testFilePath,
slug: 'example-file',
- filename: 'sample.bin'
+ filename: 'sample.bin',
});
console.log(`Stored successfully!`);
@@ -61,24 +61,7 @@ console.log(`Git tree created: ${treeOid}`);
// Step 3: Read the manifest back from the tree
console.log('\n--- Step 3: Reading manifest from tree ---');
-const service = await cas.getService();
-const entries = await service.persistence.readTree(treeOid);
-
-console.log(`Tree contains ${entries.length} entries:`);
-entries.forEach(entry => {
- const label = entry.name.startsWith('manifest.') ? 'Manifest' : `Chunk ${entry.name.substring(0, 8)}...`;
- console.log(` - ${label} (${entry.type}): ${entry.oid}`);
-});
-
-// Find and decode the manifest
-const manifestEntry = entries.find(e => e.name === 'manifest.json');
-if (!manifestEntry) {
- throw new Error('Manifest not found in tree');
-}
-
-const manifestBlob = await service.persistence.readBlob(manifestEntry.oid);
-const manifestData = service.codec.decode(manifestBlob);
-const restoredManifest = new Manifest(manifestData);
+const restoredManifest = await cas.readManifest({ treeOid });
console.log('\nManifest successfully read from tree');
console.log(` Slug: ${restoredManifest.slug}`);
@@ -89,7 +72,7 @@ console.log('\n--- Step 4: Restoring file to disk ---');
const outputPath = path.join(testDir, 'restored.bin');
const { bytesWritten } = await cas.restoreFile({
manifest: restoredManifest,
- outputPath
+ outputPath,
});
console.log(`File restored to: ${outputPath}`);