diff --git a/docs/guide/cli-reference.md b/docs/guide/cli-reference.md
index ce406a3..dec71cf 100644
--- a/docs/guide/cli-reference.md
+++ b/docs/guide/cli-reference.md
@@ -34,6 +34,13 @@ Spec Engine — it invents no semantics of its own. Exit codes mirror specdrift:
| `goldpath db status [--path
]` | What is applied, what is pending — also inlined into `check`. |
| `goldpath db bundle [--path ]` | A self-contained migration bundle for environments where the SDK is not installed. |
+## Export
+
+- `goldpath export compose [--path ]` — reads the AppHost (the ONLY definition of the
+ topology) and writes a `docker-compose.yaml` + Dockerfile beside it. Re-runnable; the
+ compose file is an EXPORT, never a second source of truth. Exit 1 with the reason when
+ the AppHost declares no resources or a project has no matching directory.
+
## Inspect
| Verb | What it does |
@@ -55,3 +62,8 @@ goldpath/templates/goldpath-worker kind=worker name=GoldpathWorker
- It never edits what the engine would reject: every transform is validated, and a refusal
rolls the change back whole.
- It calls no LLM. The AI skills call the CLI and the engine, never the reverse (ADR-0004).
+
+## Help
+
+- `goldpath help` (also `--help`, `-h`) — the verb list with one line each; `--version`/`-v`
+ prints the informational version. Unknown verbs exit 2 with usage — never a silent 0.
diff --git a/docs/rfc/goldpath-notification.md b/docs/rfc/goldpath-notification.md
index 7c36596..f1d01e8 100644
--- a/docs/rfc/goldpath-notification.md
+++ b/docs/rfc/goldpath-notification.md
@@ -140,7 +140,8 @@ replay to the jobs console. The notification rows ARE the audit.
- Insurance's nightly renewal run: 10k notifications rendered + evidence-stamped against
a no-op channel — measure rows/s (expectation: template render is string work; the
channel dominates in production).
-- Render micro-bench: token replacement at p95 (budget: sub-millisecond).
+- Render micro-bench: token replacement at p95 (budget: sub-millisecond). Reference
+ profile: `scripts/bench-notification.sh` → `packages/Goldpath.Notification/ops/notification-benchmarks.md`.
- Queue-age under a stopped channel: the backlog drains after recovery without loss or
duplicates (the claim proof, notification-flavored).
diff --git a/docs/rfc/goldpath-versioning.md b/docs/rfc/goldpath-versioning.md
index bf8d80a..3512f23 100644
--- a/docs/rfc/goldpath-versioning.md
+++ b/docs/rfc/goldpath-versioning.md
@@ -50,7 +50,7 @@ warnings first; a later minor may raise severity, and says so in the guide).
No release tag without all three, in the same release PR:
-1. **PublicAPI roll:** every package's `Unshipped.txt` rolls into `Shipped.txt` (the
+1. **PublicAPI roll (`scripts/roll-shipped.sh`):** every package's `Unshipped.txt` rolls into `Shipped.txt` (the
ledger IS the released surface; the roll script lands with the NuGet release work).
2. **CHANGELOG entry** for the train (one file, newest on top).
3. **Upgrade guide:** `docs/upgrades/.md` — step-by-step for every break;
diff --git a/docs/strategy/coverage-matrix.md b/docs/strategy/coverage-matrix.md
index 4ab0be2..776d5ca 100644
--- a/docs/strategy/coverage-matrix.md
+++ b/docs/strategy/coverage-matrix.md
@@ -61,6 +61,20 @@ for planning · — deliberately absent (the card does not trigger it).
| specdrift CLI path | ✅ | — |
| specdrift MCP path (from skills) | 🟡 not exercised in a sample flow | Insurance build runs it |
+## Ring C modules (matrix entry pending their sample cards)
+
+| Capability | CorPay (finance) | Insurance | Telco |
+|---|---|---|---|
+| Approvals | 🟡 no sample story yet (the api-portal product proves the pattern end to end) | 🔷 endorsement four-eyes candidate | 🔷 tariff-change four-eyes candidate |
+| FileExchange | 🟡 no sample story yet | 🔷 bordereaux import candidate | 🔷 CDR drop candidate |
+
+## Foundational packages (no matrix row — they underpin EVERY cell)
+
+Abstractions · Sdk · ServiceDefaults · ApiDefaults · Data · Messaging — composed by every
+sample and every generated shape; their proof is the nightly golden-manifest matrix, not a
+sector story. Named here so the docs-freshness inventory can hold this file to the full
+package list.
+
## Console panels (post-UI; eyes-on + Playwright per sample)
| Panel | CorPay | Insurance | Telco |
diff --git a/docs/strategy/golden-manifests-v1.md b/docs/strategy/golden-manifests-v1.md
index bfe2b37..a0f7abe 100644
--- a/docs/strategy/golden-manifests-v1.md
+++ b/docs/strategy/golden-manifests-v1.md
@@ -87,3 +87,25 @@
2. A combination that blows up in the field → a GM update or a regression manifest (never deleted).
3. A GM change demands a review as serious as a schema/template change (these are the product's contract).
4. Every GM is also an example project usable in sales/demos — narrated by its persona name.
+
+## 6. The nightly matrix today (docs-freshness gate keeps this table honest)
+
+Every shape below runs nightly via `scripts/validate-gm.sh` — pack → generate → build →
+spec-lint → smoke with real containers. A shape name here and in `nightly.yml` may not
+drift apart; the gate fails on either direction.
+
+| Shape | Arguments | What it proves |
+|---|---|---|
+| GmOneAuthDefault | (defaults) | the default shape, auth floor up |
+| GmOneOpenFlow | `--auth none` | open shape drives the full order flow |
+| GmFourSimple | `--db sqlserver --broker none --auth none` | the SqlServer/no-broker quadrant |
+| GmFourClean | `--layout clean-architecture …` | four-project split, migrations in Infrastructure |
+| GmSixGateway | `--auth none` + `new service` + `new gateway` | multi-head by the adopter's own verbs; routed probe |
+| GmBulkOnly | `--features bulk --broker none --auth none` | operational module with ONLY the app database |
+| Gm.Dotted | `--broker none --auth none` | dotted solution names (issue #24 regression) |
+| GmConsole | `--features bulk --auth none` | the console SERVES with its own bundle |
+| GmConsoleAuthed | `--features bulk` | the console's 401 floor branch |
+| GmEverything | all eleven features | maximal composition compiles, boots, smokes |
+| GmWorkerQueue | worker template | queue-triggered worker shape |
+| GmWorkerSchedule | worker `--trigger schedule` | schedule-triggered worker shape |
+| GmWorkerJobs | worker `--trigger jobs` | jobs-profile worker shape |
diff --git a/packages/README.md b/packages/README.md
index 447605c..aa9cb79 100644
--- a/packages/README.md
+++ b/packages/README.md
@@ -1,6 +1,6 @@
# packages/
-The NuGet train — 19 packages (Abstractions → ServiceDefaults → ApiDefaults → Data →
-Messaging → Ring B/C modules), published as `0.1.0-preview.*` with OIDC trusted publishing.
+The NuGet train — 23 packages (Abstractions → ServiceDefaults → ApiDefaults → Data →
+Messaging → Ring B/C modules + providers), published as `0.1.0-preview.*` with OIDC trusted publishing.
Per-module RFCs and status: `docs/rfc/README.md`. Live capability ledger:
`docs/strategy/coverage-matrix.md`.
diff --git a/scripts/docs-freshness.sh b/scripts/docs-freshness.sh
index 7d62ac1..0919271 100755
--- a/scripts/docs-freshness.sh
+++ b/scripts/docs-freshness.sh
@@ -65,3 +65,83 @@ if offences:
sys.exit(1)
print("── retired names: none of the retired tools are mentioned")
PY
+
+# ── INVENTORY SYNC (#174): every public surface is NAMED where readers look for it, and
+# every numeric claim about a surface matches reality. Same contract as the tests:
+# "the docs are stale" is a RED state, never a silent one.
+python3 - "$ROOT" <<'PY'
+import os, re, sys
+root = sys.argv[1]
+fail = []
+def read(*parts):
+ path = os.path.join(root, *parts)
+ return open(path, encoding="utf-8", errors="replace").read() if os.path.exists(path) else ""
+
+# 1. Every package is on the live capability ledger.
+ledger = read("docs", "strategy", "coverage-matrix.md")
+packages = sorted(d for d in os.listdir(os.path.join(root, "packages"))
+ if d.startswith("Goldpath.") and os.path.isdir(os.path.join(root, "packages", d)))
+# The matrix speaks capability SHORT names ("Idempotency"); providers ride their base
+# capability's row ("Locking" covers Locking.SqlServer). Either spelling satisfies.
+for package in packages:
+ short = package.removeprefix("Goldpath.")
+ base = short.split(".")[0]
+ if package not in ledger and short not in ledger and base not in ledger:
+ fail.append(f"package {package} missing from docs/strategy/coverage-matrix.md")
+
+# 2. A doc that COUNTS packages must count them correctly (packages/README said 19 while
+# 23 existed — found by this gate's first run).
+readme = read("packages", "README.md")
+for claim in re.findall(r"(\d+)\s+packages", readme):
+ if int(claim) != len(packages):
+ fail.append(f"packages/README.md claims {claim} packages; there are {len(packages)}")
+
+# 3. Every CLI verb the dispatcher knows is in the CLI reference.
+dispatch = read("tools", "Goldpath.Cli", "CliRunner.cs")
+verbs = set()
+for m in re.finditer(r'\["([a-z]+)"(?:, "([a-z]+)")?', dispatch):
+ verbs.add(m.group(1) if not m.group(2) else f"{m.group(1)} {m.group(2)}")
+verbs -= {"new"} if "new " in " ".join(verbs) else set()
+reference = read("docs", "guide", "cli-reference.md")
+for verb in sorted(verbs):
+ if f"goldpath {verb}" not in reference:
+ fail.append(f"CLI verb 'goldpath {verb}' missing from docs/guide/cli-reference.md")
+
+# 4. Every golden-manifest shape in the nightly matrix is in the golden-manifests doc.
+nightly = read(".github", "workflows", "nightly.yml")
+gm_doc = read("docs", "strategy", "golden-manifests-v1.md")
+for shape in re.findall(r"- name: (Gm[A-Za-z.]+)", nightly):
+ if shape not in gm_doc:
+ fail.append(f"nightly shape {shape} missing from docs/strategy/golden-manifests-v1.md")
+
+# 5. Every script is referenced SOMEWHERE a reader can find it.
+corpus = ""
+for scope in ["README.md", "CLAUDE.md"]:
+ corpus += read(scope)
+for base, dirs, names in os.walk(os.path.join(root, "docs")):
+ for n in names:
+ if n.endswith(".md"):
+ corpus += read(os.path.relpath(os.path.join(base, n), root))
+for n in os.listdir(os.path.join(root, ".github", "workflows")):
+ corpus += read(".github", "workflows", n)
+corpus += "".join(read("scripts", n) for n in os.listdir(os.path.join(root, "scripts")))
+for script in sorted(os.listdir(os.path.join(root, "scripts"))):
+ if script.endswith((".sh", ".py")) and script not in corpus.replace("docs-freshness.sh", script, 0):
+ others = corpus
+ if script not in others:
+ fail.append(f"scripts/{script} is referenced nowhere (README, CLAUDE.md, docs, workflows, other scripts)")
+
+# 6. Every template is in templates/README.md.
+templates_doc = read("templates", "README.md")
+for template in sorted(d for d in os.listdir(os.path.join(root, "templates"))
+ if d.startswith("goldpath-") and os.path.isdir(os.path.join(root, "templates", d))):
+ if template not in templates_doc:
+ fail.append(f"template {template} missing from templates/README.md")
+
+if fail:
+ print("── inventory sync: the docs stopped telling the truth:")
+ for f in fail:
+ print(f" {f}")
+ sys.exit(1)
+print(f"── inventory sync: {len(packages)} packages, {len(verbs)} CLI verbs, nightly shapes, scripts and templates all documented")
+PY
diff --git a/templates/README.md b/templates/README.md
index 54020eb..4ffe851 100644
--- a/templates/README.md
+++ b/templates/README.md
@@ -3,8 +3,10 @@
Golden-path templates. Current: `goldpath-solution` (GM-1 shape defaults: modular-monolith,
vertical-slice, PostgreSQL, RabbitMQ) — with `--layout clean-architecture` generating the
four-project split (Domain / Application / Infrastructure / Api; the packages anchor rides
-Infrastructure, which also owns migrations). Further shapes arrive per the template RFC
-phasing (`docs/rfc/goldpath-template.md`, decision D1).
+Infrastructure, which also owns migrations). Also current: `goldpath-worker` — the
+headless worker shape (queue / schedule / jobs triggers; probes instead of business
+contracts, no OpenAPI artifact). Further shapes arrive per the template RFC phasing
+(`docs/rfc/goldpath-template.md`, decision D1).
```
dotnet new install Goldpath.Templates