diff --git a/.gitattributes b/.gitattributes
index de7c9c3b..d9ad7853 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -11,7 +11,6 @@ PLAN.md export-ignore
SOURCE_REF export-subst
docs/plan-archive/ export-ignore
scripts/shadow-brief.py export-ignore
-docs/assets/brief-decision.png export-ignore
docs/superpowers/ export-ignore
# Docs authoring surface: claudux preferences and the local VitePress preview
# scaffold. The shipped product is the Markdown under docs/, never the Node
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17df6ce7..95b79330 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
## Unreleased
+- Docs truth sweep: the guide pages no longer pin the never-tagged
+ `shadow-v1.0.1` (install tags are now contract-tested against `VERSION`);
+ Grok joins every host enumeration, the doctor/amp help text, and the config
+ table; the lint inventory names all 32 real checks (`PLAN-SECRET`, not
+ `PROOF-SECRET`; blocking `PROOF-ARGV0` documented); accept's `--repo` rule,
+ the 262144-byte refusal paths with their three remedies, and archive
+ eligibility are documented; two orphaned docs assets deleted;
+ `scripts/shadow_version.py` joins the packaging contract.
+
## 1.2.0 — 2026-08-18 — the test layer stops lying, and the plan cannot strand itself
- The starvation guard no longer disables the tests it protects: a caller's
diff --git a/README.md b/README.md
index 3adc037e..d7ec4ff7 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-

+
# Shadow
**Shadow is you, one step down.** Say what you want in any wired AI coding
-host — Claude Code, Codex, Cursor — and Shadow keeps the work durable: one
-board per computer, one `PLAN.md` per project, a proof receipt on every
-finished step. Kill any chat; the next session resumes where it stopped.
+host — Claude Code, Codex, Cursor, Grok — and Shadow keeps the work
+durable: one board per computer, one `PLAN.md` per project, a proof receipt
+on every finished step. Kill any chat; the next session resumes where it stopped.
Six words carry the system:
@@ -29,8 +29,8 @@ cd shadow && bash install.sh && shadow doctor
Git, Bash, Python 3.10+, and a supported host. No Node, no daemon, no
transcript store. The clone is the install; to upgrade, check out the
-newer `shadow-v*` tag and rerun `install.sh`. If `shadow` is not found,
-add `~/.local/bin` to your PATH.
+newer `shadow-v*` tag and rerun `install.sh`. Missing `shadow`? Add
+`~/.local/bin` to PATH.
## First run
@@ -74,6 +74,8 @@ Shadow refuses unclaimed execution, missing proof, and ambiguous authority.
## Docs
The full contract — every verb, plan grammar, extensions, privacy — lives at
-**[the docs site](https://firstbitelabsllc.github.io/shadow/)**; developing Shadow starts at [`AGENT.md`](AGENT.md).
+**[the docs site](https://firstbitelabsllc.github.io/shadow/)**; developing starts at
+[`AGENT.md`](AGENT.md) and [`CONTRIBUTING.md`](CONTRIBUTING.md) — external
+PRs are closed.
-MIT License.
+[MIT License](LICENSE).
diff --git a/bin/shadow b/bin/shadow
index 99a816d1..efb699d5 100755
--- a/bin/shadow
+++ b/bin/shadow
@@ -175,8 +175,8 @@ requires a live claim owned by --by; use shadow throw to claim new work.
exit codes:
0 block printed (char count on stderr)
- 1 no open task (mint the successor) or the resume row itself exceeds
- the budget
+ 1 no claim to resume: the row is claimed by another seat, not claimed
+ by --by, or the owned row is not executable work
2 no plan found or invalid usage
EOF
;;
@@ -346,7 +346,7 @@ shadow doctor — read-only installation and native-host doctor.
usage: shadow doctor [--json] [--help|-h]
Checks product identity, Python, Git, PATH installation, native Codex/Claude
-Code/Cursor availability, those three skill mounts, and whether each host's
+Code/Cursor/Grok availability, those four skill mounts, and whether each host's
instruction file carries the current standing goal. It is read-only and never
fetches, repairs, authenticates, or runs the test suite. Missing optional hosts
or mounts warn; contradictory product identity or mount custody fails.
diff --git a/docs/assets/board-phone.png b/docs/assets/board-phone.png
deleted file mode 100644
index b75d442b..00000000
Binary files a/docs/assets/board-phone.png and /dev/null differ
diff --git a/docs/assets/brief-decision.png b/docs/assets/brief-decision.png
deleted file mode 100644
index e160803f..00000000
Binary files a/docs/assets/brief-decision.png and /dev/null differ
diff --git a/docs/guide/index.md b/docs/guide/index.md
index d9077c5b..9f34b58f 100644
--- a/docs/guide/index.md
+++ b/docs/guide/index.md
@@ -3,7 +3,7 @@
Shadow is a local product with two durable jobs:
1. Brief you on the Outcome, active lanes, proof, and any real hard-rail decision.
-2. Claim and dispatch path-disjoint work to native Codex, Claude Code, or Cursor,
+2. Claim and dispatch path-disjoint work to native Codex, Claude Code, Cursor, or Grok,
then integrate proof and continue through every reachable row.
Its one root board per computer groups entity pointers under projects and
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
index b1869e3c..0e04e7b2 100644
--- a/docs/guide/installation.md
+++ b/docs/guide/installation.md
@@ -4,7 +4,7 @@ Requirements: Git, Bash, Python 3.10+, and one supported native coding host.
No Node, no npm, no package manager — the stable release clone *is* the install.
```bash
-git clone --branch shadow-v1.0.1 --depth 1 \
+git clone --branch shadow-v1.2.0 --depth 1 \
https://github.com/firstbitelabsllc/shadow.git
cd shadow
bash install.sh
@@ -17,7 +17,7 @@ only when you deliberately want moving development source.
`install.sh` links `bin/shadow` into `~/.local/bin` and mounts the skill in
every host root that already exists (`~/.claude/skills`, `~/.agents/skills`,
-`~/.cursor/skills`). Two flags change that:
+`~/.cursor/skills`, `~/.grok/skills`). Two flags change that:
```bash
bash install.sh --bin-dir /usr/local/bin # put the command somewhere else
@@ -39,5 +39,5 @@ Shadow shipped under a different name before 0.1.0. Its compatibility path is
gone: evidence lives in `.shadow/`, and a repository still carrying the
pre-rename evidence directory shows as dirty until that directory is renamed
to `.shadow/` or deleted. Remove the old global install and its mounts, then
-re-run `bash install.sh` so `~/.claude/skills`, `~/.agents/skills`, and
-`~/.cursor/skills` point at this checkout.
+re-run `bash install.sh` so `~/.claude/skills`, `~/.agents/skills`,
+`~/.cursor/skills`, and `~/.grok/skills` point at this checkout.
diff --git a/docs/guide/other-computer-handoff.md b/docs/guide/other-computer-handoff.md
index 517ba830..f0215b8b 100644
--- a/docs/guide/other-computer-handoff.md
+++ b/docs/guide/other-computer-handoff.md
@@ -5,7 +5,7 @@ This is the portable starting point for Shadow on another Mac.
## Bootstrap
```bash
-git clone --branch shadow-v1.0.1 --depth 1 \
+git clone --branch shadow-v1.2.0 --depth 1 \
https://github.com/firstbitelabsllc/shadow.git
cd shadow
bash install.sh
@@ -13,7 +13,7 @@ shadow doctor
```
`install.sh` links the command and mounts the same skill in each native host
-root that exists (`~/.claude/skills`, `~/.agents/skills`, `~/.cursor/skills`).
+root that exists (`~/.claude/skills`, `~/.agents/skills`, `~/.cursor/skills`, `~/.grok/skills`).
Pass `--no-skills` to link the command alone.
Expected result: `shadow doctor` reports product identity, command, and the
@@ -47,6 +47,7 @@ transcripts, provider payloads, or absolute private paths in it.
| Surface | Use it for |
| --- | --- |
| `/shadow` | Start/resume work, read the Outcome, drain reachable lanes, and leave proof plus successors. |
+| `/amplify` | Shape a loose intent into one durable PLAN plus a four-line goal launcher. The native `shadow goal` verb prints the standing goal; this skill (renamed from `goal` in 1.2.0) is the shaper. |
`shadow amp` is a CLI subcommand, not a mounted skill: it projects a
paste-ready resume block for a checkpoint the seat already claimed — see
@@ -58,7 +59,7 @@ adversarial-lens slug — post-work review, a different moment — or a person
may delegate foresight to their own method). Diagrams stay Brief-contract
law, no slot involved.
-Use native Codex, Claude Code, or Cursor for execution. Provider-specific
+Use native Codex, Claude Code, Cursor, or Grok for execution. Provider-specific
helpers are adapters; none becomes the plan authority or stores credentials.
## Read the public state
diff --git a/docs/guide/publishing.md b/docs/guide/publishing.md
index 5101baa9..125aaeae 100644
--- a/docs/guide/publishing.md
+++ b/docs/guide/publishing.md
@@ -20,6 +20,7 @@ flowchart LR
| ChatGPT and Codex | The `plugins/shadow/.codex-plugin` package and repo marketplace expose the same Shadow skill and goal shaper. | Full status and action require a local host that can read the board and run Shadow. A hosted chat is a coach only. |
| Claude Code | The existing `.claude-plugin` package installs the same source skill. | Local board access follows the existing install and host rules. |
| Cursor | The checked-in skill works through Cursor's local skill/plugin support. | Cursor can act only where the local checkout and host integration are available. |
+| Grok | `install.sh` mounts `~/.grok/skills` and `shadow goal --install` writes `~/.grok/AGENTS.md`. | Grok acts only through the sealed native host runner on a local checkout. |
| Custom GPT | The skill prose can seed a friendly “Shadow Coach” for goal shaping and explanation. | A Custom GPT is not real Shadow until a reviewed remote bridge exists. It must say that it cannot see the local board. |
| MCP directories | A future remote adapter could expose a privacy-safe brief and typed intent return. | No server is published today. The local board remains authority; a remote service may not copy the queue, credentials, or transcripts. |
diff --git a/docs/guide/quickstart.md b/docs/guide/quickstart.md
index c4bd3db0..4b2eaae6 100644
--- a/docs/guide/quickstart.md
+++ b/docs/guide/quickstart.md
@@ -80,6 +80,8 @@ For a passing `cmd` proof, use the only flip path:
```bash
shadow accept --repo . --row '~ab12' --by your-seat
+# --repo is where proofs RUN (the product checkout); a machine-local
+# plan's own directory also works when its proof argv cds there itself
```
For a remotely coordinated claim, ordinary accept publishes the completed
diff --git a/docs/index.md b/docs/index.md
index b253b0b0..82e64bb5 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,7 +4,7 @@ layout: home
hero:
name: Shadow
text: Your coding chief of staff
- tagline: Understand the work, choose what happens next, and safely use Codex, Claude Code, or Cursor.
+ tagline: Understand the work, choose what happens next, and safely use Codex, Claude Code, Cursor, or Grok.
actions:
- theme: brand
text: Start in five minutes
diff --git a/docs/reference/browser.md b/docs/reference/browser.md
index 1c98928a..78f532b0 100644
--- a/docs/reference/browser.md
+++ b/docs/reference/browser.md
@@ -10,3 +10,9 @@
Choice receipts are atomic and idempotent under the selected Git project's
`.shadow/evidence/` directory. The browser never receives a credential,
prompt, transcript, provider payload, or absolute private path.
+
+## Host header allowance
+
+`shadow browse --allow-host NAME` (repeatable) widens only the accepted
+`Host` header, for a self-run proxy such as `tailscale serve` in front of the
+loopback server. The bind itself never leaves loopback; no flag changes that.
diff --git a/docs/reference/commands.md b/docs/reference/commands.md
index cf8c5b4f..f8968c7b 100644
--- a/docs/reference/commands.md
+++ b/docs/reference/commands.md
@@ -7,17 +7,17 @@ Every verb `bin/shadow` dispatches. `shadow help ` gives exact flags.
| `shadow init --here` | Create `PLAN.md` without overwriting one. |
| `shadow status --by [--root PATH] [--shadowed]` | Read this computer's root board, project authenticated active remote coordination locks for known PLAN rows, then rank checkpoints. `--root` changes only the bounded import root; it never bypasses or writes the board. `--shadowed` adds safe reasons for suppressed or retired copies. |
| `shadow status --in-flight` | Every local claim plus authenticated remote-lock observation, joined at read time to project-owned text and proof — the recovery view after a chat dies. Add `--json` for a machine-readable end-of-chat footer. |
-| `shadow config --explain [--repo PATH]` | Read the optional repository-root `shadow.yaml` declaration, or report the built-in version 1 defaults when it is absent. It prints the attack-then-refute step and active review lenses; the command is read-only and writes no resolved state. |
+| `shadow config --explain [--repo PATH] [--json]` | Read the optional repository-root `shadow.yaml` declaration, or report the built-in version 1 defaults when it is absent. It prints the attack-then-refute step and active review lenses; the command is read-only and writes no resolved state. |
| `shadow goal [--install|--remove] [--host HOST]` | Print the static standing goal, or install/remove its managed block in supported host instruction files (Claude Code, Codex, Grok). Cursor cold directive activation is unsupported until a reviewed writable user-rule surface exists; its skill mount and sealed host runner remain supported. |
| `shadow amp --entity ID --by ` | Resume a paste-ready packet for a checkpoint already claimed by that seat. It never dispatches unclaimed work. |
| `shadow throw --task '~hash' --by [--repo PATH\|--entity ID]` | Atomically claim an entity checkpoint before work leaves the seat, then print its packet. A unique legacy text alias such as `P9a~formats` may be supplied, but it resolves to the row's canonical `~hash` before the claim. The board records pointer, canonical row id, owner, lease, and recovery action; the entity plan is unchanged. A configured origin upstream also requires the deterministic remote coordination CAS. `--adopt-expired` replaces only an overdue claim after proof was probed. |
-| `shadow return --row '~hash' --by [--repo PATH\|--entity ID]` | Idempotently append a remote released tombstone when remote coordination is active, then close the named owner's exact local claim after a committed manual proof, a committed blocked state plus one Deferred wake, or an explicit handback. |
-| `shadow priority --value 1..5 --repo PATH` | Change the root-board priority under the same local transaction. The project plan's bootstrap value is unchanged and later discovery cannot overwrite the root decision. |
-| `shadow accept --row '~hash' --repo PATH --by [--no-push]` | Require that seat's live claim and rerun the committed `cmd` proof in a clean detached checkout. Normally it flips and publishes the paired PROOF commit, appends the remote completed tombstone, then closes the local claim. A registered machine-local plan instead atomically flips only its private authority after the same clean source-checkout proof. For a remotely coordinated claim, `--no-push` keeps both claims open for a later publishing retry. |
-| `shadow lifecycle [--repo PATH] [--milestone 'heading'\|--retirement-manifest /ABS/file.json]` | Dry-run the hot-plan limits or one exact manifested retirement and emit a CAS. Apply requires explicit `--repo PATH --apply --expect CAS --by `. Archives are content-addressed, recover exact-CAS half-writes, can monotonically compact an over-limit plan across finite passes, and bind one successor row or `null` once the plan is within limits. Retirement paths must use canonical absolute spellings with no symlink component. It accepts only one clean landed non-primary linked worktree without any submodule, or one clean expired same-entity snapshot recoverable from its declared ref; it journals the exact target, never forces deletion, and commits a path-free receipt with the same bound successor. The named seat claims that row only when present, reachable, and unclaimed; the original CAS makes a completed exact repeat a no-op. |
+| `shadow return --row '~hash' --by [--repo PATH\|--entity ID]` | Idempotently append a remote released tombstone when remote coordination is active, then close the named owner's exact local claim after a committed manual proof, a committed blocked state plus one Deferred wake, or an explicit handback, and advance that claim's resume pointer. |
+| `shadow priority --value 1..5 [--repo PATH]` | Change the root-board priority under the same local transaction. The project plan's bootstrap value is unchanged and later discovery cannot overwrite the root decision. |
+| `shadow accept --row '~hash' --repo PATH --by [--timeout-seconds N] [--no-push]` | Require that seat's live claim and rerun the committed `cmd` proof in a clean detached checkout. Normally it flips and publishes the paired PROOF commit, appends the remote completed tombstone, then closes the local claim. A registered machine-local plan instead atomically flips only its private authority after the same clean source-checkout proof. For a remotely coordinated claim, `--no-push` keeps both claims open for a later publishing retry. A rejected push exits 3 naming the pull-request path. `--repo` is the root where proofs RUN, not where the plan lives; a machine-local plan's own directory also works when its committed proof argv changes into the product checkout itself. |
+| `shadow lifecycle [--repo PATH] [--json] [--milestone 'heading'\|--retirement-manifest /ABS/file.json]` | Dry-run the hot-plan limits or one exact manifested retirement and emit a CAS. Apply requires explicit `--repo PATH --apply --expect CAS --by `. Archives are content-addressed, recover exact-CAS half-writes, can monotonically compact an over-limit plan across finite passes, and bind one successor row or `null` once the plan is within limits. Retirement paths must use canonical absolute spellings with no symlink component. It accepts only one clean landed non-primary linked worktree without any submodule, or one clean expired same-entity snapshot recoverable from its declared ref; it journals the exact target, never forces deletion, and commits a path-free receipt with the same bound successor. The named seat claims that row only when present, reachable, and unclaimed; the original CAS makes a completed exact repeat a no-op. |
| `shadow plan migrate /ABS/PLAN.md --dry-run` | Build and verify the complete partitioned candidate with zero writes. Apply requires `--apply --expect SOURCE_SHA256`; `shadow plan rollback … --expect ROOT_SHA256` restores the exact prior root. An optional absolute `--board` binds the receipt while leaving pointers, claims, owners, and resume unchanged. |
| `shadow lint [--repo PATH] PLAN.md …` | Check plans against the grammar; blocking findings exit non-zero. A registered machine-local plan uses `--repo` to check proof scripts at its source checkout's committed HEAD. |
-| `shadow browse --root PATH` | Start the loopback briefing UI. |
+| `shadow browse --root PATH [--no-open] [--port N] [--host HOST] [--allow-host NAME ...]` | Start the loopback briefing UI. `--allow-host` (repeatable) only widens the accepted `Host` header for a self-run proxy; the bind stays loopback. |
| `shadow host probe --host HOST` | Check a native host without using it. |
| `shadow host run …` | Run a claimed task in its clean worktree; invoke again for path-disjoint lanes. |
| `shadow slots` | Report which extension slots are filled. Absent is a WARN and exits 0; a wrong binding FAILs. No slot reads tooling Shadow does not itself call. |
diff --git a/docs/reference/config.md b/docs/reference/config.md
index 7baac2e2..03eeb3af 100644
--- a/docs/reference/config.md
+++ b/docs/reference/config.md
@@ -67,6 +67,7 @@ These environment variables provide runtime defaults:
| `SHADOW_CODEX_BIN` | Optional Codex executable override. |
| `SHADOW_CLAUDE_CODE_BIN` | Optional Claude Code executable override. |
| `SHADOW_CURSOR_BIN` | Optional Cursor executable override. |
+| `SHADOW_GROK_BIN` | Optional Grok executable override. |
| `SHADOW_TELEMETRY` | Set exactly to `local` to append closed, local-only lifecycle events beneath the current project's `.shadow/evidence/`; unset and every other value write nothing. |
| `SHADOW_AMP_PACK_ROOT` | Amp-core pack-root override (absolute path, or `off` to disable pack inspection) — not a slot binding. See [amp.md](amp.md). |
diff --git a/docs/reference/grammar.md b/docs/reference/grammar.md
index ccdfd8de..8b55242f 100644
--- a/docs/reference/grammar.md
+++ b/docs/reference/grammar.md
@@ -266,6 +266,24 @@ by default. A budget-only over-limit report exits non-zero; a preview that
proves one legal monotonic repair exits zero so its CAS can be applied. Limits
are product law, not environment knobs.
+The byte limit an operator sees in refusals is the literal `262144`
+(`HOT-PLAN-BYTES`). Two verbs refuse differently at that wall: `shadow throw`
+refuses the claim ("hot plan exceeds the checked-in bytes budget"), and
+`shadow accept` refuses through lint ("the completed plan would fail shadow
+lint (HOT-PLAN-BYTES ...); nothing was changed"). The report names one of
+three remedies: archive one proven milestone with `shadow lifecycle`; or —
+when every open milestone is held open only by a person-gated row — archive
+cannot run and the remedy is to trim or relocate plan text; or the same trim
+when no archive-eligible milestone exists. Migration is lossless and does not
+shrink the plan.
+
+Archive eligibility, rechecked per milestone at apply time: 2-7 well-formed
+task rows; exactly one `(DoD)` row; every row completed; every row's proof
+matches a typed class (" has no typed proof" otherwise); ids unique
+within the milestone, and no duplicate task id anywhere in the plan ("plan
+has duplicate task ids" — a duplicate would let the dependency fold strip a
+still-live `needs:`).
+
`shadow lifecycle --repo --milestone ''`
makes no change and emits a content CAS. Repeating that command with
`--apply --expect --by `
@@ -295,7 +313,7 @@ marker-preserving tampering refuses.
Apply refuses a dirty plan or target archive, symlinks, an existing archive
with different provenance, a malformed or unproven milestone, and a non-Git
-plan. Normal lint, portfolio import, and claim paths enforce the same hot-plan
+plan. Normal lint, accept, portfolio import, and claim paths enforce the same hot-plan
limits before mutating the computer board; lifecycle is the repair door.
Worktree and snapshot deletion use the strict
@@ -321,12 +339,15 @@ replaced, broad, or provenance-bearing targets refuse without mutation.
## LINT
`scripts/shadow-lint.py`, exit non-zero on blocking findings; deterministic
-across reruns. Checks: task shape; ID-DUP; NEEDS-DANGLE; NEEDS-SHAPE;
-PROOF-MISSING / PROOF-CLASS / PROOF-SECRET; DOD-COUNT; DOD-EARLY;
-DEFER-NO-WAKE; MODE-ILLEGAL (legacy `Spike|Defer|Challenge|Broad|Close`
-values included); TS-ORDER (warning); READ-FIT (warning, lines over 2,000
-chars); HOT-PLAN-BYTES; HOT-PLAN-ROWS; HOT-PLAN-MILESTONES;
-SECTION-MISSING (warning); SPIKE-NO-END; SPIKE-DUP;
+across reruns. Checks: ROW-SHAPE; ROWS-WITHOUT-TASKS; ID-DUP; NEEDS-DANGLE;
+NEEDS-SHAPE; NEEDS-CYCLE; PROOF-MISSING / PROOF-CLASS / PROOF-UNPARSEABLE /
+PROOF-SCRIPT / PROOF-SHELL-OPERATOR / PROOF-RECEIPT-SHAPE; PROOF-ARGV0
+(blocking for a path operand, warning for a bare name); PLAN-SECRET;
+COMPLETED-NO-PROOF; CONFLICT-MARKER; DOD-COUNT; DOD-EARLY; DEFER-NO-WAKE;
+MODE-ILLEGAL (legacy `Spike|Defer|Challenge|Broad|Close` values included);
+TS-ORDER (warning); READ-FIT (warning, lines over 2,000 chars);
+HOT-PLAN-BYTES; HOT-PLAN-ROWS; HOT-PLAN-MILESTONES; SECTION-MISSING
+(warning); SECTION-ORDER; SPIKE-NO-END; SPIKE-DUP;
SPIKE-EXPIRED-NO-DECISION; SHIP-OVER-OPEN-SPIKE; ORPHAN-DECISION (warning).
## BOARD
diff --git a/docs/reference/host-integration.md b/docs/reference/host-integration.md
index d02b9436..c50cb955 100644
--- a/docs/reference/host-integration.md
+++ b/docs/reference/host-integration.md
@@ -10,7 +10,7 @@ user-rule surface; Shadow does not invent `~/.cursor/rules`.
## 1. Install once
```bash
-git clone --branch shadow-v1.0.1 --depth 1 \
+git clone --branch shadow-v1.2.0 --depth 1 \
https://github.com/firstbitelabsllc/shadow.git && cd shadow
bash install.sh
shadow doctor
diff --git a/docs/reference/plan-scale.md b/docs/reference/plan-scale.md
index 41531f1a..2032c038 100644
--- a/docs/reference/plan-scale.md
+++ b/docs/reference/plan-scale.md
@@ -319,7 +319,8 @@ shard before an answer is returned.
Index pages MUST be at most 16 KiB, data shards at most 32 KiB, and the
`PLAN.md` root at most 8 KiB. Tree pages have at most 64 children. A single
grammar item that cannot fit a data shard MUST refuse migration rather than be
-split mid-item. These budgets replace the 256 KiB monolith ceiling; active row
+split mid-item. These budgets bound each stored object; the 256 KiB
+logical ceiling still applies to the materialized hot plan, and active row
and milestone budgets remain unchanged. Historical growth adds immutable
shards and logarithmic catalog pages without enlarging the active context.
diff --git a/docs/reference/slots.md b/docs/reference/slots.md
index 73b63b7a..dd15d51d 100644
--- a/docs/reference/slots.md
+++ b/docs/reference/slots.md
@@ -18,8 +18,8 @@ there is no slot configuration file.
## The slots
-- slot memory | kind: skill | default: memory | fills: routed recall — the routing file that delegates where to look things up (static docs, semantic vectors, graph — per person); recall is a lead, never plan, proof, or ownership authority; re-verify at the attributed source | absent: mount a skill named memory in one of the three skill roots, or set SHADOW_SLOT_MEMORY=off
-- slot taste | kind: skill | default: taste | fills: the finished-quality grade on a human-visible surface and the voice of everything written or shown for humans — prose, briefs, PR text, explanation visuals — after it works and before anyone calls it done | absent: mount a skill named taste in one of the three skill roots, or set SHADOW_SLOT_TASTE=off
+- slot memory | kind: skill | default: memory | fills: routed recall — the routing file that delegates where to look things up (static docs, semantic vectors, graph — per person); recall is a lead, never plan, proof, or ownership authority; re-verify at the attributed source | absent: mount a skill named memory in one of the four skill roots, or set SHADOW_SLOT_MEMORY=off
+- slot taste | kind: skill | default: taste | fills: the finished-quality grade on a human-visible surface and the voice of everything written or shown for humans — prose, briefs, PR text, explanation visuals — after it works and before anyone calls it done | absent: mount a skill named taste in one of the four skill roots, or set SHADOW_SLOT_TASTE=off
## How each kind resolves
@@ -32,7 +32,7 @@ its `name`. Present when it matches, and the detail is that manifest's
asserted, for the same reason doctor gives about Cursor user rules — asserting a
path there would invent a convention.
-**skill** — one skill mounted in the three roots the installer writes. Look for
+**skill** — one skill mounted in the four roots the installer writes. Look for
`//SKILL.md`. Present when at least one resolves.
A slot names only a capability Shadow itself reaches for. It never asserts
diff --git a/scripts/shadow-release-package.py b/scripts/shadow-release-package.py
index 088e3c71..e89c58ec 100644
--- a/scripts/shadow-release-package.py
+++ b/scripts/shadow-release-package.py
@@ -50,6 +50,7 @@
"skills/amplify/SKILL.md",
"VERSION",
"bin/shadow",
+ "scripts/shadow_version.py",
"bin/shadow-browse",
# Deleting either of these left the gate reporting publishable while
# `shadow amp` and `shadow throw` exited 2 with "can't open file".
diff --git a/tests/test_readme_contract.py b/tests/test_readme_contract.py
index c92d651f..81de26e7 100644
--- a/tests/test_readme_contract.py
+++ b/tests/test_readme_contract.py
@@ -37,6 +37,23 @@ def test_readme_leads_with_authority_loop_and_install(self) -> None:
self.assertIn("Every Shadow chat response ends with a compact `Ongoing tasks` projection", skill)
self.assertIn("shadow status --in-flight --json", skill)
+ def test_every_shipped_install_tag_tracks_version(self) -> None:
+ """The guide pages pinned shadow-v1.0.1 — a tag that never existed —
+ for two releases because only the README's tag was contract-tested.
+ Every install tag in the shipped doc set must name the current
+ VERSION; historical dev docs (plan-archive, superpowers) are exempt."""
+ import re as _re
+
+ version = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
+ expected = f"shadow-v{version}"
+ shipped = [ROOT / "README.md", *sorted((ROOT / "docs").rglob("*.md"))]
+ for path in shipped:
+ relative = path.relative_to(ROOT).as_posix()
+ if relative.startswith(("docs/plan-archive/", "docs/superpowers/")):
+ continue
+ for tag in _re.findall(r"--branch (shadow-v[0-9][0-9.]*)", path.read_text(encoding="utf-8")):
+ self.assertEqual(tag, expected, f"{relative} pins {tag}, VERSION is {version}")
+
def test_the_footer_projection_contract_stays_written_down(self) -> None:
"""The README sends detail to the docs site, so the host-facing footer
contract must stay stated where hosts and strangers actually read it."""