feat(lease): verified lease-remediation stack (rebased onto next) — promotion trigger + promote CLI + carve-out + TTL #1109
Open
mos-dt-0
wants to merge 24 commits from
feat/lease-promotion-and-harness-isolation into next
pull from: feat/lease-promotion-and-harness-isolation
merge into: :next
:main
:next
:fix/1138-conditional-federation
:feat/webui-p2-data-auth
:fix/gateway-runner-image
:feat/webui-p1-vite-skeleton
:fix/break-c-hooks-and-web-image
:docs/webui-fleet-claude-bridge-plan
:fix/wizard-gateway-failure
:fix/ci-queue-wait-no-status
:fix/next-node-gate
:fix/mosaic-init-rce
:feat/lease-promotion-and-harness-isolation
:greenfield/fomo-lin
:fix/1099-pipefail-wake
:fix/1099-pipefail-tests
:fix/1099-pipefail-sweep
:fix/framework-shell-portability
:fix/1043-pane-git-identity
:fix/1081-issue-close-silent-comment-failure
:fix/1090-enrollment-wallclock-tolerance
:feat/1082-tea-stale-token-diagnostic
:fix/detect-platform-silent-128-outside-repo
:feat/1050-install-state-machine-red-fixture
:fix/pr-merge-message-field
:feat/1051-mosaic-brain-installer
:feat/1045-mosaic-cred
:remediation/state
:fix/1056-upgrade-rollback-control-race
:fix/1019-ci-queue-timeout-harness
:feat/rm-02-gate-registry
:fix/rm-01-reproducible-checkout
:remediation/mission-setup
:fix/hygiene-inert-format-gate
:fix/1019-queue-guard-stdin
:feat/mos-ste-writing-standard
:fix/1007-suite-hermeticity
:fix/991-comment-url-scheme-normalise
:feat/push-guard-null-case-verification
:mos-comms-live
:docs/heartbeat-framework-layering-ms-lead
:feat/869-c4-version-coupling
:feat/869-c2-install-ordering-guard
:feat/869-c5-doctor-activation-check
:feat/per-agent-gitea-identity
:fix/875-belongs-case-insensitive-slug
:fix/ci-queue-wait-404-branch-absent
:feat/869-c1-activation-probe
:feat/869-c3-broker-supervisor
:fix/865-tea-cli-comment-invocation
:feat/glpi-skills
:fix/860-deflake-mutator-lease-gate
:fix/850-detect-platform-port-normalization
:fix/856-worktree-deps-preflight
:fix/835-pr-review-approve-reject-comment-flag
:fix/848-truthful-evidence
:fix/812-pr-review-comment
:fix/849-recovery-runtime-fixture-race
:docs/758-ledger-m5-001-sync
:feat/834-tc-server-side-doc
:feat/833-constrained-recovery-command
:feat/827-gate0-probe
:governance/gate0-probe3-amendment
:fix/795-codex-pr-diff
:fix/795-ci-base-jq
:fix/795-ci-base-git
:feat/791-pr3-fleet-regen
:feat/791-pr2-snapshot-restore
:fix/807-glpi-206
:fix/808-agent-send-false-sender
:feat/791-upgrade-config-protection
:feat/790-mosaic-yolo-claudex-pr2
:feat/790-mosaic-yolo-claudex
:feat/758-v1-v2-migrator
:fix/766-exact-fleet-comms
:test/758-reconciler-lifecycle-gates
:docs/771-kbn101-db-role-split
:test/758-example-profile-dispositions
:feat/758-shared-role-resolution
:feat/mos-logical-identity-fencing
:feat/769-kbn100-unified-schema
:docs/753-kbn010-threat-gate
:feat/758-roster-v2-compiler
:feat/756-official-discord-plugin
:docs/758-fleet-config-management
:fix/mos-option2-qualification-format
:docs/issue-758-m0
:docs/mos-option2-qualification
:mos-comms
:feat/tess-interaction-agent
:fix/tess-docs-format
:draft/mosaic-platform-prd
:fix/installer-provider-gate-and-local-gateway-redis
:release/mosaic-cli-0.0.37
:feat/framework-constitution-alpha
:fix/git-wrapper-repo-detection
:fix/woodpecker-wrapper-legacy-mosaic
:fix/t-a292e96f-gitea-pr-metadata
:fix/gitea-pr-metadata-login-t-a292e96f
:fix/t_a292e96f-pr-metadata-gitea
:fix/t_3a368a52-gitea-usc-login
:fix/bootstrap-hotfix
:fix/populate-known-packages-list
:fix/idempotent-init
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Lease remediation — make gated
mosaic pi/mosaic claudeseats launch AND functionTrunk of the lease-remediation mission. Every commit below cleared an
independent verification gate (code review + security review + E2E falsifier
reproduction by a separate orchestrator session) before landing on the branch.
What's in it (10 commits, oldest → newest)
Lease invariant / read-only carve-out (W-0, W-A):
3592b92erefuse an incomplete law binding instead of silently shrinking it (W-0)87ef1c14close W-0R review findings — assert the omission notice; skip chmod sims under root289425edmeasure pi tool registry (docs)9f800493enforce read-only tool invariant (test)930b7e88distinguish pi probe timeouts (test)e76f2935assert pi carve-out capability, not just identity (test)3d98c832constrain read-only tool carve-outs (W-C — the fix; carve-outadmitted grep/find which spawn subprocesses + cold-cache download+chmod+exec)
Observer / TTL (W-E, TTL):
9c3f054fignore benign observer idle replies (W-E — fail-open confined tothe stop-blocking axis; auth/transport stay exit 2)
412ac4b0raise lease TTL 300s → 3600s (daemon cap+default + client default)Promotion trigger (W-P1):
d15b4b83single-turn Claude promotion trigger —/mosaic-promote(gated command) → begin hook injects receipt → model echoes verbatim →
same-turn Stop chain (observer posts the finished text from Stop-stdin
last_assistant_message, completion promotes) → mutator ALLOWED, one turn.Non-ASCII bytes-compare crash fix in the verbatim check included. The one
protected-file change (observer client source-swap) cleared a stricter
security gate: daemon verbatim HMAC check untouched, present-invalid +
oversize fail closed, transcript fallback retained for older Claude.
Verification
All landed commits are gate-PASS (verdicts in jarvis-brain
docs/scratchpads/lease-remediation/dispatch/verdict-*.md). Fullpnpm run test:framework-shellRC=0 reproduced independently; promotion_trigger24/24, observer 16/16, receipt_challenge 6/6. Husky pre-push gate green on push.
Reviewer notes
mainas of this push(0 behind its own remote branch — the push was a clean fast-forward). No
textual conflicts expected but please rebase/verify against current
mainbefore merge, especially anything touching the lease-broker.
mosaic promote <seat>operator CLI): held pendinga design decision. The CLI needs an external read-only lease-state poll, and
there is no such surface today by design — the broker has no status verb,
authorize_toolis ancestry-gated, and lease/TTL state is never persisted(monotonic clock, volatile memory). Options (in-band result breadcrumb vs a
new read-only
lease_statusverb) are written up for the operator to choose;W-P1b lands in a follow-up PR.
codification (W-F): later phases.
feat(lease): promotion trigger + read-only carve-out + TTL — verified lease-remediation stackto feat(lease): verified lease-remediation stack (rebased onto next) — promotion trigger + promote CLI + carve-out + TTLbuild_construction skipped any normative source it could not read (`except OSError: continue`) and promoted whatever remained. That is not a degraded binding, it is a forged smaller one: the broker recomputes h_source / h_payload from the fragments it is SENT (daemon.py:602-616), so an omitted fragment is internally consistent and PAYLOAD_BINDING_MISMATCH cannot fire. A partial law promotes exactly like a complete one and nothing downstream can tell the difference. Measured before this change, against a seeded home: with only USER.md readable, the client produced a one-fragment construction with promotion=True. Removing CONSTITUTION.md, STANDARDS.md or the runtime contract likewise promoted. The classification mirrors the framework's own file ownership rather than inventing one: * CONSTITUTION.md / AGENTS.md / STANDARDS.md are framework-owned and reconciled every upgrade (install.sh FRAMEWORK_OWNED, config/file-adapter.ts FRAMEWORK_OWNED_FILES), as is the per-runtime RUNTIME.md. Absent => IncompleteBinding. A deployment missing one is broken, not minimal. * SOUL.md / USER.md are deliberately not seeded by install.sh ("generated by `mosaic init`") and TOOLS.md is seeded on first install only, so their absence is legitimate. It is reported on stderr, never silent. Unreadable is handled separately from absent for EVERY source, optional ones included: a file that will not open is not a file that was never configured, and collapsing the two is what let a permission change quietly shrink the law. Also corrects this module's own docstring, which asserted that a VERIFIED lease means "this agent is running THIS law". It does not. Both sides of the broker's comparison originate in this client, so it detects corruption in transit and nothing else. That overstatement is where the belief spread from; the stronger claim needs the broker re-reading on-disk sources against a manifest the agent cannot rewrite. Test: promotion_binding_unittest.py, enumerated in test:framework-shell (the enumeration guard's population is *test*.sh and does not cover Python, so an unenumerated test here would simply never run). Falsifier executed: defeating the guard while leaving the module API intact turns the suite red (12 failures); restoring it returns green. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EHYXhcCQsL3J1Lnm7EraGqRetargeted main→next in place (Jason redirected to next, 2026-08-08). Branch rebased onto next: clean 21/21, zero conflicts (next touched none of these files), force-pushed d15b4b83...adb1d7f8. Now carries the full verified stack: W-0/W-0R, W-A capability tests, W-C carve-out constraint, W-E observer idle fix, TTL 300→3600, W-P1 single-turn /mosaic-promote trigger, W-P1b mosaic promote CLI (atomic breadcrumb + bounded transport), T1 carve-out acceptance alignment. Verification (fred, §4): promote 9/9, promotion_trigger 28/28, observer 16/16, receipt 6/6, T-B green; framework-shell green under controlled PATH (one PATH-sensitivity test needs clean env by design). The 4 broker-dependent mutator-gate acceptance failures are pre-existing on pristine origin/main (documented, not introduced here). GATE BEFORE MERGE: scooby full greenfield promotion-flow E2E on fomo-lin (Jason-directed; in flight) + review.
A6 live-E2E verdict (scooby, real gated seat on fomo-lin, 2026-08-09): CORE THESIS VALIDATED
Full 5-step gate against a fresh real
mosaic claudeseat, real daemon (unmodified daemon.py), real sockets, at head1a871524.mosaic promote-> VERIFIED, Write allowed/mosaic-promoteand promotion still completed synchronously; the #1126 failure mode (model refusal blocks promotion) is eliminated/mosaic-promotewith no operator tokenMerge gate — one fix required on this branch (F1)
W-P1c dropped the #1123 slow-host probe-timeout bump:
lease-activation-probe.jsshipstimeout: 2000(was 15000). fomo-lin cold node-spawn ofmosaic __lease-capabilitymeasures ~2.4 s, so gated-seat launch fails spuriously on modest hardware ("activation capability unreadable / version skew"). Pythonactivation_version_gate.pyPROBE_TIMEOUT_SECONDS = 2.0has the same ceiling. Plan: restore the 15000 ms JS timeout + align the Python ceiling on this branch, scooby re-verifies a clean seat launch (no probe-command override), then merge. While the fix is in,commands/mosaic-promote.mdshould also drop the echo-era wording ("follow the ... injected receipt confirmation instruction exactly") for mechanical framing — that text sends seat models into refusal loops.Tracked, not gating
MOSAIC_RUNTIME_GENERATIONenv vs live generation file), root-caused, likely pre-existing; fast-follow.Correction narrowing the merge gate (scooby, clean-host verification):
commands/mosaic-promote.mdat head1a871524(blobb80c0924) already carries the mechanical framing. No wording change needed in the F1 commit.mosaic-link-runtime-assets(unconditional copy loop, independent of the settings-guard) reproduced on a scratch HOME with no.claude/commands/— seeded file is byte-identical to the source blob.The merge gate is therefore F1 only: restore the #1123 probe timeout (
lease-activation-probe.js2000 → 15000) + align the PythonPROBE_TIMEOUT_SECONDSceiling, then a clean-launch re-verify on fomo-lin.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.