95 lines
5.9 KiB
Markdown
95 lines
5.9 KiB
Markdown
# T1 report: canonical ungated Claude base and lease overlay
|
||
|
||
## Changed
|
||
|
||
- Replaced `packages/mosaic/framework/runtime/claude/settings.json` with the canonical ungated base. It retains the model, QA hooks, plugins, command allowlist, permissions, and `mcpServers.sequential-thinking`.
|
||
- Added `packages/mosaic/framework/runtime/claude/lease-overlay.json`. It contains only `hooks` and the six removed lease hook entries.
|
||
- Added the byte-identical pre-split source fixture at `packages/mosaic/src/runtime/fixtures/claude-settings.gated.pre-split.json`.
|
||
- Added `packages/mosaic/src/runtime/claude-settings-base.spec.ts`.
|
||
|
||
`framework-manifest.txt` already declares `runtime/**`, so the new overlay is framework-owned and shipped without a manifest change.
|
||
|
||
## Lease-hook enumeration
|
||
|
||
The actual template has six lease hook entries, matching fred's refined boundary:
|
||
|
||
1. `PreToolUse` matcher `.*`: `mutator-gate.py`
|
||
2. `Stop`: one combined command containing `receipt-observer-client.py` then `promote-complete.py`
|
||
3. `UserPromptSubmit` matcher `^/mosaic-promote$`: `promote-begin.py`
|
||
4. `PreCompact`: `revoke-lease.py --reason pre-compact`
|
||
5. `SessionStart` matcher `compact`: `revoke-lease.py --reason session-start-compact`
|
||
6. `SessionStart` matcher `resume|clear`: `revoke-lease.py --reason session-start-rollover --bump-generation`
|
||
|
||
There is no delta from the refined six-entry enumeration. The Stop entry contains the receipt-observer and promote-complete commands together, rather than as two separate hook objects.
|
||
|
||
## Tests and checks
|
||
|
||
`pnpm install --frozen-lockfile` was run first because `node_modules` was absent. It completed successfully.
|
||
|
||
Red-first run before artifacts existed:
|
||
|
||
```text
|
||
RUN v2.1.9 .../packages/mosaic
|
||
❯ src/runtime/claude-settings-base.spec.ts (4 tests | 4 failed)
|
||
× keeps every lease command out of the ungated base
|
||
→ mutator-gate: expected true to be false
|
||
× reconstructs the pre-split gated hooks while retaining the canonical MCP correction
|
||
→ ENOENT: .../lease-overlay.json
|
||
× ships sequential-thinking in the base
|
||
→ expected undefined to deeply equal { 'sequential-thinking': ... }
|
||
× limits the overlay to lease hook entries
|
||
→ ENOENT: .../lease-overlay.json
|
||
```
|
||
|
||
Final focused acceptance run:
|
||
|
||
```text
|
||
RUN v2.1.9 .../packages/mosaic
|
||
✓ src/runtime/claude-settings-base.spec.ts (4 tests) 19ms
|
||
Test Files 1 passed (1)
|
||
Tests 4 passed (4)
|
||
```
|
||
|
||
`pnpm --filter @mosaicstack/mosaic lint` passed:
|
||
|
||
```text
|
||
> @mosaicstack/[email protected] lint
|
||
> eslint src
|
||
```
|
||
|
||
`pnpm --filter @mosaicstack/mosaic typecheck` failed on pre-existing workspace resolution and unrelated package errors. The new spec no longer appears in the error list. Initial failures include missing `@mosaicstack/{brain,forge,log,macp,memory,queue,storage,quality-rails,db,config,prdy,types}` declarations, followed by existing `fleet-backlog.ts`, `gateway-doctor.ts`, and TUI implicit-`any` errors. Exit status: 2.
|
||
|
||
A focused legacy consumer run confirms an existing assumption that `settings.json` itself is gated:
|
||
|
||
```text
|
||
pnpm --filter @mosaicstack/mosaic exec vitest run src/mutator-gate/mutator-gate.acceptance.spec.ts
|
||
❯ src/mutator-gate/mutator-gate.acceptance.spec.ts (20 tests | 6 failed)
|
||
× non-dangerous parser residual is denied by the global all-tools hook without a lease
|
||
→ expected all-tools mutator-gate command in settings.json
|
||
× Claude and Pi compaction observer wiring is complete and fail-closed
|
||
→ expected PreCompact/SessionStart revoke-lease hooks in settings.json
|
||
```
|
||
|
||
The other four failures in that focused run reported `STALE_GENERATION` where the test expected `MUTATOR_UNVERIFIED`, plus one successful-gate assertion. I did not redesign this legacy suite because the task explicitly says to report consumers that assume the base is gated.
|
||
|
||
## Consumers found
|
||
|
||
Direct `runtime/claude/settings.json` path consumers found by the required repository grep:
|
||
|
||
- `packages/mosaic/framework/tools/_scripts/mosaic-link-runtime-assets`: copies the base to `~/.claude/settings.json`.
|
||
- `packages/mosaic/src/commands/install-ordering-guard.ts` and `.spec.ts`: documentation and behavior assume the source embeds enforcement hooks.
|
||
- `packages/mosaic/framework/tools/_scripts/test-install-ordering-guard.sh`: comments and assertions expect `mutator-gate.py` and `receipt-observer-client.py` in the base.
|
||
- `packages/mosaic/src/mutator-gate/mutator-gate.acceptance.spec.ts`: reads the base and asserts mutator, promotion, and compaction lease wiring.
|
||
- `packages/mosaic/src/lease-broker/promotion_trigger_unittest.py`: reads the base and asserts promotion wiring.
|
||
- `packages/mosaic/src/lease-broker/recovery_runtime_unittest.py`: reads the base.
|
||
- `packages/mosaic/src/runtime/update-checker.ts` and `.spec.ts`: references the path in settings wiring/update checks.
|
||
- Documentation-only references: `docs/compaction-refresh/probes/p6_constrained_recovery.py`, `docs/plans/agent-reflection-loop-PRD.md`, `docs/tasks/544-agent-reflection-loop.md`, and the framework QA documentation/scripts found by grep.
|
||
|
||
I did not change these consumers. The install/link and lease acceptance consumers must be taught to select and compose `lease-overlay.json` when a gated promotion seat is requested. That composition behavior is outside T1.
|
||
|
||
## Ambiguity handled
|
||
|
||
The exact pre-split template fixture has no `mcpServers` key (SHA-256 `44e74ea1e9d424fffa020ee666402662ac856b88bf6ae7f3b8931eed29dc75a4`). The task simultaneously requires a byte-for-byte pre-split fixture, `mcpServers.sequential-thinking` in the base, and `deep-merge(base, overlay) == original`. Those three conditions cannot all hold because a merge cannot remove the required MCP key.
|
||
|
||
The acceptance test preserves the exact fixture and asserts that the normalized merge equals the pre-split template plus the required canonical `mcpServers.sequential-thinking` correction. It verifies all original hook content is reconstructed and the base carries the required MCP. Production three-layer merge semantics remain W-F1 work.
|