Applies the document contract from
docs/plans/2026-08-20_stack-docs-flatten-and-alignment.md section 3, partially:
`kind` and `status` only. `parent` is deliberately held until the flatten in
section 4 lands, so that 127 documents do not have to be re-pointed by hand
when docs/fleet/NORTH_STAR.yaml moves to docs/NORTH_STAR.yaml.
Scope, measured on origin/next at 63069149:
127 live docs = all *.md under docs/ minus docs/archive/ minus docs/_old_structure/
104 stamped here
19 held operator judgement (plan section 9), worklist in the same PR
3 held the SUPERSEDED TASKS.md stamps, which cite the moving path
1 untouched docs/fleet/FLEET-DOCTRINE.md, already stamped in W1
Kinds applied: 54 guide, 34 record, 9 spec, 6 tracking, 1 projection.
Every row carries a confidence and a one-line rationale in the worklist.
Two collisions with the existing state, both flagged rather than resolved:
1. docs/README.md:150-160 already documents a front-matter convention
(title/type/audience/status/source_of_truth) with its own allowed values.
It is applied to 4 of 127 files. Its `status` vocabulary is
current|draft|deprecated|historical; the new contract's is active|superseded-by.
The key collides. This commit lets the new contract win and rewrites
`status: current` to `status: active` on those 4 files, keeping their other
legacy keys untouched. No code reads any of them: `git grep source_of_truth`
outside docs/ returns nothing. docs/README.md still prescribes the old
convention and is an operator row, so it is not edited here.
2. Two of the plan's 20 operator rows are YAML files, not markdown
(docs/fleet/examples/roster-v2.yaml, docs/openapi-tess.yaml), and the
contract's front-matter form has no defined meaning for a .yaml document.
That gap also applies to docs/fleet/NORTH_STAR.yaml, the source of truth
itself. Raised in the worklist.
A third row from the plan, docs/fleet/north-star.md, no longer exists: W1
renamed it to docs/fleet/FLEET-DOCTRINE.md.
Verification: 104/104 parse with the expected kind and status in front matter;
the check was shown to reject a wrong kind before it was trusted. The diff
removes 4 lines total, all of them `status: current`.
8.0 KiB
kind, status
| kind | status |
|---|---|
| guide | active |
Whole mutator-class lease gate
Status: Current contract reference. Audience: Developer and security reviewer. Evidence: Runtime launch-guard and mutator-gate tests cross-check this boundary; parser residuals and deployment gaps remain explicitly labeled below.
WI-2 adds the framework-native authorization boundary for Claude (including the supported Claudex overlay) and Pi. Every runtime-reported tool name reaches the lease broker before execution. The gate classifies capabilities by the whole tool class; it never parses a Bash command to decide whether that particular string looks read-only.
Default-deny policy
While a session is not VERIFIED, only these exact classes are allowed:
- Claude:
Read,Grep,Glob,Ls,Find - Pi:
read,grep,find,ls - Both runtimes: the fixed
mosaic_context_recoverprimitive
Every other built-in, unknown tool, and custom/MCP tool is consequential by default and is denied. This includes Claude Bash, Edit, Write, and NotebookEdit, plus Pi bash, edit, and write. A compromised model therefore cannot bypass Mosaic wrappers by selecting raw git, curl, kubectl, provider, deployment, or filesystem commands inside a generic mutator—the generic mutator itself is blocked before its input executes.
Broker-owned transition order
The authenticated broker is the sole lease writer:
begin_verificationrevokes existing authority and pending tokens first, then recordsPENDING_VERIFICATIONand mints one WI-1 single-use promotion token bound to the exact cycle.promote_leaseaccepts only that session/generation/binding/token combination.- Token consumption commits before the volatile lease becomes VERIFIED. Promotion is last and cannot be reached directly from UNVERIFIED.
revoke_lease, a runtime-generation increase, broker restart, or monotonic expiry removes mutator authority.
The initial TTL is capped at the ratified 300-second maximum. A caller may request a shorter positive TTL but cannot lengthen the maximum. WI-3 installs the compaction observer and generation lifecycle. Dual compaction-hook miss within an unexpired lease remains the ratified bounded T-A residual: consequential tools are allowed until expiry, with no claimed within-window action bound; once either observer revokes or TTL expires, the next consequential tool is denied.
A receipt is only a future promotion prerequisite. It is not an obedience, residency, or safety proof and never replaces this mechanical gate.
Runtime adapters
launch-runtime.py registers itself with the broker and then execs Claude or Pi so PID/starttime remain the authenticated parent anchor. It exports the broker-minted session ID and an owner-only generation-file reference to descendants; lifecycle hooks advance that file for same-PID replacement generations.
- Claude installs
mutator-gate.pyas an all-tools (.*)PreToolUsehook. mosaic claudexandmosaic yolo claudexpreserve their isolatedCLAUDE_CONFIG_DIR, merge the mandatory hook into that isolatedsettings.json, and use the same register-before-exec launcher. Malformed or symlinked isolated settings deny launch.- Pi invokes the same executable from its
tool_callhandler.
The executable submits the runtime's actual tool name to authorize_tool. Missing identity, malformed input/reply, timeout, broker unavailability, or denial exits with status 2 and blocks fail-closed.
Runtime-launch choke-point and permanent guard
Every repository-owned Claude/Pi launch entry converges on launch-runtime.py, either directly or through mosaic → execLeaseGatedRuntime. PRDY init/update and QA remediation invoke the wrapper directly so their existing prompts, dangerous-permission behavior, working directory, and environment survive without skipping broker registration. The raw Claude --dangerously-skip-permissions primitive is owned only by launch-runtime.py; callers request semantic --dangerous mode, and the wrapper validates Claude before injecting the primitive. @mosaicstack/coord rewrites direct Claude commands to mosaic claude and rejects unknown custom Claude launchers.
check-runtime-launches.py is the permanent completeness guard. It scans production shell, TypeScript/JavaScript, Python, and data launch definitions under packages/, apps/, plugins/, and tools/; direct literal, absolute-path, process-API, dynamic, command-substitution, eval, and variable-execution runtime launches fail. Shell comments are stripped with quote awareness, wrapper prefixes are tokenized with shlex, and only an invocation in command position with --runtime before the command separator is gated. Literal and tracked-variable command tokens use one terminal resolver after any nesting of exec, command, nohup, or env plus assignments. A direct command always wins over an inert marker on the same line. Independently, the raw dangerous primitive anywhere outside the choke-point is RED.
The command parser is a best-effort CI defense, not a complete shell interpreter. Alias/function redefinition, sourced commands, generated scripts, and encoded pipelines are intentionally residual rather than an invitation to chase an unbounded shell language. Two runtime controls backstop that residual surface: primitive ownership rejects a dangerous launch even when command identity is alias-indirected, and Claude's global .* PreToolUse hook invokes the broker gate for non-dangerous launches. Without MOSAIC_LEASE_SESSION_ID, representative read, mutator, and custom/MCP tools all fail closed with GATE_UNAVAILABLE. Hook absence or replacement remains in the documented T-C boundary.
Parser stopping criterion
- A — realistic parser matrix: comments, inert strings/assignments, heredocs, continuations, chained commands, command substitution,
eval, bare tracked variables, and quoted/unquoted tracked variables behindexec,command,nohup, orenvare permanent RED regressions. Prefix-variable forms are covered in both multiline and same-line assignment shapes. - B — residual backstops: a dangerous alias-indirected launch is RED solely through primitive anchoring; a parser-missed non-dangerous alias launch is paired with an acceptance test proving the global all-tools hook denies every representative tool class as
GATE_UNAVAILABLEwithout a lease. - C — independent fresh review: the parser class is considered complete only when reviewers find no new non-overlapping realistic evasion on the exact head. A and B are repository evidence; C is supplied by the fresh review round.
All three layers are load-bearing and complementary. The guard is mandatory in @mosaicstack/mosaic's test script, so root CI fails on a future realistic bypass. Real-socket tests separately prove PRDY init/update and QA receive broker sessions and deny an unverified mutator.
The live inventory is emitted by:
python3 packages/mosaic/framework/tools/lease-broker/check-runtime-launches.py --root . --json
| Production launch family | Gated entries |
|---|---|
@mosaicstack/coord default/configured Claude command |
2 |
| Fleet runtime start | 1 |
| QA remediation + generated QA command | 2 |
| Orchestrator command construction/session launches | 3 |
| PRDY init/update | 2 |
| Mosaic Claude/Pi/Claudex adapter and wrapper boundary | 4 |
| Total | 14 / 14 |
Assurance boundary
This closes T-A after an observer fires or lease expiry and T-B for in-runtime tool calls. Hook/extension absence, a runtime executing outside the gated launcher, ptrace/same-UID broker replacement, and other fully rotted behavior remain T-C. Server-side branch protection and required PR review/CI remain the irreducible line for protected repository mutations.