Builds on the merged W2 store/ack (EPIC #892). Adds A3 (digest.sh) and A5 (sign.sh) under packages/mosaic/framework/tools/wake/, honoring CONVERGED-DESIGN exactly. One coherent PR.
A3 — digest.sh cumulative-state digest renderer
CONVERGED-DESIGN contract
Implementation
§2.1 CUMULATIVE-STATE (state-since-CONSUMED, not a delta)
Renders the FULL unacked set since consumed_seq from the durable pending-inbox (store.sh drain). Two still-pending changes both render.
§2.1 TWO-TIER TRUST — orientation
who / lane / board-head + changed-obligation list (observed_seq + locators); decides the no-op case with zero tool calls.
§2.1 TWO-TIER TRUST — actionable
Every consequential fact rendered ONLY as a CLAIM@seq claim-to-verify ("VERIFY LIVE, do NOT act on this line"); never auto-actioned. Self-sufficiency never exempts a live gate.
§2.1 HARD LOCATORS
Every actionable claim must carry repo+issue# / 40-char SHA / file:anchor + a one-call re-verify hint. Missing/imprecise locator = fail-loud (exit 4, nothing emitted).
§2.1 BOUNDING / INJECTION / SECRETS
Source free-text only inside a delimited, length-capped, ANSI/bidi/zero-width-stripped untrusted block; secret-canary redaction over any inlined content; whole-digest backstop. Embeds the W2 ack copy-run line.
§1.2/§2.3 draws from the store
Reads the coalesced durable pending-inbox via store.sh drain (or --from-file/--stdin).
A5 — sign.sh non-circular HMAC signer
CONVERGED-DESIGN contract
Implementation
§2.5 non-circular tuple
wake_id generated INDEPENDENTLY at emit (not derived from, not a member of, the signed field-tuple). wake_mac = HMAC(key, wake_id ‖ agent_identity ‖ mission_generation ‖ observed_seq ‖ emit_ts ‖ content_hash) — over wake_id PLUS the fields; the MAC is never its own input. Envelope splits wake_id / signed{…} / wake_mac to make non-circularity visible.
§2.5 fills the placeholder
sign-entry fills the hmac field W2 left as "" and attaches the independent wake_id; content_hash binds {observed_seq,class,emit_ts,locators}.
§2.5 key by-name
Key resolved BY NAME from the operator credential store (.wake.hmac_keys.<name>); never inlined, never echoed, no flag accepts key material; unresolvable name = fail-loud.
§2.5 threat boundary
Same-uid boundary documented in-file (same-uid attacker can read the key / observe argv → out of scope); off-uid signer named as the future §4 G6 gate.
test-wake-digest-hmac.sh (wired into test:framework-shell, after the W2 harness). Each invariant was verified to go RED on a targeted regression of the implementation:
Builds on the merged W2 store/ack (EPIC #892). Adds **A3** (`digest.sh`) and **A5** (`sign.sh`) under `packages/mosaic/framework/tools/wake/`, honoring CONVERGED-DESIGN exactly. One coherent PR.
## A3 — `digest.sh` cumulative-state digest renderer
| CONVERGED-DESIGN contract | Implementation |
|---|---|
| §2.1 CUMULATIVE-STATE (state-since-CONSUMED, not a delta) | Renders the FULL unacked set since `consumed_seq` from the durable pending-inbox (`store.sh drain`). Two still-pending changes both render. |
| §2.1 TWO-TIER TRUST — orientation | who / lane / board-head + changed-obligation list (observed_seq + locators); decides the no-op case with **zero tool calls**. |
| §2.1 TWO-TIER TRUST — actionable | Every consequential fact rendered ONLY as a `CLAIM@seq` claim-to-verify ("VERIFY LIVE, do NOT act on this line"); never auto-actioned. Self-sufficiency never exempts a live gate. |
| §2.1 HARD LOCATORS | Every actionable claim must carry repo+issue# / 40-char SHA / file:anchor + a one-call re-verify hint. Missing/imprecise locator = **fail-loud (exit 4, nothing emitted)**. |
| §2.1 BOUNDING / INJECTION / SECRETS | Source free-text only inside a delimited, length-capped, ANSI/bidi/zero-width-stripped untrusted block; secret-canary redaction over any inlined content; whole-digest backstop. Embeds the W2 ack copy-run line. |
| §1.2/§2.3 draws from the store | Reads the coalesced durable pending-inbox via `store.sh drain` (or `--from-file`/`--stdin`). |
## A5 — `sign.sh` non-circular HMAC signer
| CONVERGED-DESIGN contract | Implementation |
|---|---|
| §2.5 non-circular tuple | `wake_id` generated INDEPENDENTLY at emit (not derived from, not a member of, the signed field-tuple). `wake_mac = HMAC(key, wake_id ‖ agent_identity ‖ mission_generation ‖ observed_seq ‖ emit_ts ‖ content_hash)` — over wake_id PLUS the fields; the MAC is never its own input. Envelope splits `wake_id` / `signed{…}` / `wake_mac` to make non-circularity visible. |
| §2.5 fills the placeholder | `sign-entry` fills the `hmac` field W2 left as `""` and attaches the independent `wake_id`; content_hash binds `{observed_seq,class,emit_ts,locators}`. |
| §2.5 key by-name | Key resolved BY NAME from the operator credential store (`.wake.hmac_keys.<name>`); never inlined, never echoed, no flag accepts key material; unresolvable name = fail-loud. |
| §2.5 threat boundary | Same-uid boundary documented in-file (same-uid attacker can read the key / observe argv → out of scope); off-uid signer named as the future §4 G6 gate. |
Subcommands: `sign`, `sign-digest`, `sign-entry`, `verify`, `verify-entry`.
## RED-FIRST evidence
`test-wake-digest-hmac.sh` (wired into `test:framework-shell`, after the W2 harness). Each invariant was verified to go **RED** on a targeted regression of the implementation:
| Test | Invariant | RED demo (mutation → failing assertion) |
|---|---|---|
| D1 | cumulative-state | drain→`tail -1` (delta) → "OLDER change (issue #11) dropped" |
| D2 | hard-locator fail-loud | gate forced true → "must FAIL, but render succeeded / expected exit 4 got 0" |
| D3 | two-tier | render calls `git` → "orientation no-op made a live tool call" |
| D4 | scrub | `_scrub_ctrl`→`cat` → "ANSI ESC / bidi / C0 survived the scrub" |
| H1 | non-circular HMAC | wake_id derived-fixed → "not independently generated"; drop content_hash → "tampering content_hash did NOT break the MAC" |
| H2 | key-by-name-never-inline | add `--key` flag → "accepted an inline-key flag" |
## Gates
- `test:framework-shell` full chain: **green** (rc=0), new harness passes 6/6.
- `shellcheck -x` clean on `digest.sh`, `sign.sh`, `test-wake-digest-hmac.sh`.
- Firewall: `grep -niE 'jason|woltje|jarvis'` = 0; no `$HOME/src` defaults; sanitization gate passes. Operator-agnostic (XDG/env only).
- `prettier --check` clean on the edited `package.json`.
Out of scope (untouched): detector (W4), FN-oracle/reconciler (W5), beacon (W6), installer (W7).
Part of #892
Builds on the merged W2 store/ack (EPIC #892). Adds A3 (digest.sh) and A5
(sign.sh) under packages/mosaic/framework/tools/wake/, honoring CONVERGED-DESIGN.
A3 — digest.sh (cumulative-state digest renderer), §2.1:
- CUMULATIVE-STATE: renders the FULL unacked set since consumed_seq from the
durable pending-inbox (state-since-CONSUMED, not an event delta).
- TWO-TIER TRUST: orientation tier (who/lane/board-head + changed-obligation
list with observed_seq + locators) decides the no-op case with ZERO tool
calls; actionable tier renders every consequential fact ONLY as a
CLAIM-TO-VERIFY, point-in-time-at-seq — never auto-actioned.
- HARD LOCATORS: every actionable claim must carry repo+issue#/40-char SHA/
file:anchor; a missing locator is fail-loud (exit 4, nothing emitted).
- BOUNDING/INJECTION/SECRETS: source free-text is quoted only inside a
delimited, length-capped, ANSI/bidi/zero-width-stripped untrusted block;
secret-canary redaction over any inlined content; embeds the W2 ack line.
A5 — sign.sh (non-circular HMAC signer), §2.5:
- wake_id generated INDEPENDENTLY at emit (not derived from, and not a member
of, the signed field-tuple); wake_mac = HMAC(key, wake_id || agent_identity
|| mission_generation || observed_seq || emit_ts || content_hash) — over
wake_id PLUS the fields, genuinely non-circular (the MAC is never its own
input). Fills the `hmac` placeholder W2 left in store entries.
- Key resolved BY NAME from the credential store, never inlined, never echoed;
no flag accepts key material. Same-uid threat boundary documented; off-uid
signer named as a future gate.
RED-FIRST tests (test-wake-digest-hmac.sh, wired into test:framework-shell):
cumulative-state, hard-locator fail-loud, two-tier (zero-call orientation +
claim-to-verify), scrub (secret-canary + ANSI/bidi/zero-width), non-circular
HMAC (independent wake_id + tamper-breaks-MAC), key-by-name-never-inline. Each
verified to go RED on a targeted regression. shellcheck clean; operator-agnostic
(XDG/env only). manifest.txt bumped to 0.2.0.
Part of #892
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
★ NON-CIRCULAR HMAC (§2.5) — matches EXACTLY. Reviewer MANUALLY recomputed HMAC(key, wake_id‖agent‖gen‖seq‖ts‖content_hash) = wake_mac. wake_id independently generated (fresh openssl rand — 2 emits over identical fields → different wake_ids) + OUTSIDE signed{} + prepended-to-BIND; genuinely non-circular (wake_mac never its own input). Tamper any signed field / forge wake_id / wrong key → all TAMPERED. All H1 angles red. The brief paraphrase was the wrong gloss; §2.5 formula ships.
Key by-name never-inline — only --key-name (a NAME); inline-key flags rejected; resolved from credential store; unresolvable → fail-loud; no key leak; same-uid boundary + openssl-argv caveat documented, off-uid G6 gate named.
Red-first + wiring — D1-D4/H1×3/H2×2 all reproduced genuinely red; harness wired into test:framework-shell 6/6; W2 harness still green (no regression).
Gates — shellcheck clean; firewall 0; verify-sanitized pass; prettier clean; Part of #892; mergeable; CI TERMINAL-GREEN at head.
Non-blocking hardening (tracked as #905, NOT a merge blocker)
Validator/render asymmetry: a hand-crafted top-level .claim entry via --stdin/--from-file could render without a locator (escaping exit-4). NOT reachable via canonical --from-store (store never emits top-level .claim); trust framing intact (locator-completeness gap, not trust bypass). Fast-follow #905. GO for id-11 + merge at FULL-40 d3318c5910eed3ea48d94b58f8ef3f28e9962c42. Non-executor.
# Record of Review — PR #904 W3 (digest renderer + non-circular HMAC signer; Part of #892)
**VERDICT: APPROVE.** **Reviewer:** independent subagent `a0499b1d` (opus, per CONVERGED-DESIGN §2.1/§2.5) — ≠ builder (`mosaic-coder`). **REVIEWED-HEAD (full-40):** `d3318c5910eed3ea48d94b58f8ef3f28e9962c42`.
## Per-criterion (all 8 PASS, re-derived)
1. **Cumulative-state** — 2 pending actionables both render (not a delta); D1 red on a true delta mutation.
2. **Two-tier / zero-live-calls** — no-op path renders NO-OP with ZERO tool calls (git/gh/tea/curl/ssh tripwired); actionable = `CLAIM@seq` framed UNTRUSTED-VERIFY-LIVE.
3. **Hard-locator fail-loud** — no/imprecise locator → exit 4, 0 bytes stdout. Reproduced.
4. **Scrub** — ANSI/bidi/ZWSP/BOM/C0 stripped (LC_ALL=C byte-exact); secret canaries → [REDACTED]; delimited length-capped UNTRUSTED block; whole-digest backstop. Both dimensions red-first.
5. **★ NON-CIRCULAR HMAC (§2.5) — matches EXACTLY.** Reviewer MANUALLY recomputed HMAC(key, wake_id‖agent‖gen‖seq‖ts‖content_hash) = wake_mac. wake_id independently generated (fresh openssl rand — 2 emits over identical fields → different wake_ids) + OUTSIDE signed{} + prepended-to-BIND; genuinely non-circular (wake_mac never its own input). Tamper any signed field / forge wake_id / wrong key → all TAMPERED. All H1 angles red. The brief paraphrase was the wrong gloss; §2.5 formula ships.
6. **Key by-name never-inline** — only --key-name (a NAME); inline-key flags rejected; resolved from credential store; unresolvable → fail-loud; no key leak; same-uid boundary + openssl-argv caveat documented, off-uid G6 gate named.
7. **Red-first + wiring** — D1-D4/H1×3/H2×2 all reproduced genuinely red; harness wired into test:framework-shell 6/6; W2 harness still green (no regression).
8. **Gates** — shellcheck clean; firewall 0; verify-sanitized pass; prettier clean; Part of #892; mergeable; **CI TERMINAL-GREEN** at head.
## Non-blocking hardening (tracked as #905, NOT a merge blocker)
Validator/render asymmetry: a hand-crafted top-level `.claim` entry via --stdin/--from-file could render without a locator (escaping exit-4). NOT reachable via canonical --from-store (store never emits top-level .claim); trust framing intact (locator-completeness gap, not trust bypass). Fast-follow #905.
**GO for id-11 + merge at FULL-40 `d3318c5910eed3ea48d94b58f8ef3f28e9962c42`. Non-executor.**
Ghost
approved these changes 2026-07-26 00:32:11 +00:00
GO — Gate-16 id-11 stamp, pinned to exact FULL head d3318c5910.
Basis: verbatim RoR (comment 18901) — independent contract review APPROVE (all 8 criteria vs CONVERGED-DESIGN §2.1/§2.5, red-first reproduced). The §2.5 HMAC question is ADJUDICATED with manual recomputation: wake_id independently generated, outside the signed field-set, prepended-to-bind — non-circularity is generation-independence, not input-exclusion (builder/Mos/reviewer concordant; the brief gloss was the artifact). Two-tier trust, hard-locator fail-loud, scrub + secret-canary, key-by-name all verified. #905 tracked as non-blocking locator-completeness hardening on non-canonical input paths. CI terminal-green. W3 of EPIC #892. Named executor: Mos (id-11), squash pinned.
GO — Gate-16 id-11 stamp, pinned to exact FULL head d3318c5910eed3ea48d94b58f8ef3f28e9962c42.
Basis: verbatim RoR (comment 18901) — independent contract review APPROVE (all 8 criteria vs CONVERGED-DESIGN §2.1/§2.5, red-first reproduced). The §2.5 HMAC question is ADJUDICATED with manual recomputation: wake_id independently generated, outside the signed field-set, prepended-to-bind — non-circularity is generation-independence, not input-exclusion (builder/Mos/reviewer concordant; the brief gloss was the artifact). Two-tier trust, hard-locator fail-loud, scrub + secret-canary, key-by-name all verified. #905 tracked as non-blocking locator-completeness hardening on non-canonical input paths. CI terminal-green. W3 of EPIC #892. Named executor: Mos (id-11), squash pinned.
Ghost
merged commit 10d957d095 into main2026-07-26 00:32:13 +00:00
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.
Builds on the merged W2 store/ack (EPIC #892). Adds A3 (
digest.sh) and A5 (sign.sh) underpackages/mosaic/framework/tools/wake/, honoring CONVERGED-DESIGN exactly. One coherent PR.A3 —
digest.shcumulative-state digest rendererconsumed_seqfrom the durable pending-inbox (store.sh drain). Two still-pending changes both render.CLAIM@seqclaim-to-verify ("VERIFY LIVE, do NOT act on this line"); never auto-actioned. Self-sufficiency never exempts a live gate.store.sh drain(or--from-file/--stdin).A5 —
sign.shnon-circular HMAC signerwake_idgenerated INDEPENDENTLY at emit (not derived from, not a member of, the signed field-tuple).wake_mac = HMAC(key, wake_id ‖ agent_identity ‖ mission_generation ‖ observed_seq ‖ emit_ts ‖ content_hash)— over wake_id PLUS the fields; the MAC is never its own input. Envelope splitswake_id/signed{…}/wake_macto make non-circularity visible.sign-entryfills thehmacfield W2 left as""and attaches the independentwake_id; content_hash binds{observed_seq,class,emit_ts,locators}..wake.hmac_keys.<name>); never inlined, never echoed, no flag accepts key material; unresolvable name = fail-loud.Subcommands:
sign,sign-digest,sign-entry,verify,verify-entry.RED-FIRST evidence
test-wake-digest-hmac.sh(wired intotest:framework-shell, after the W2 harness). Each invariant was verified to go RED on a targeted regression of the implementation:tail -1(delta) → "OLDER change (issue #11) dropped"git→ "orientation no-op made a live tool call"_scrub_ctrl→cat→ "ANSI ESC / bidi / C0 survived the scrub"--keyflag → "accepted an inline-key flag"Gates
test:framework-shellfull chain: green (rc=0), new harness passes 6/6.shellcheck -xclean ondigest.sh,sign.sh,test-wake-digest-hmac.sh.grep -niE 'jason|woltje|jarvis'= 0; no$HOME/srcdefaults; sanitization gate passes. Operator-agnostic (XDG/env only).prettier --checkclean on the editedpackage.json.Out of scope (untouched): detector (W4), FN-oracle/reconciler (W5), beacon (W6), installer (W7).
Part of #892
Record of Review — PR #904 W3 (digest renderer + non-circular HMAC signer; Part of #892)
VERDICT: APPROVE. Reviewer: independent subagent
a0499b1d(opus, per CONVERGED-DESIGN §2.1/§2.5) — ≠ builder (mosaic-coder). REVIEWED-HEAD (full-40):d3318c5910eed3ea48d94b58f8ef3f28e9962c42.Per-criterion (all 8 PASS, re-derived)
CLAIM@seqframed UNTRUSTED-VERIFY-LIVE.Non-blocking hardening (tracked as #905, NOT a merge blocker)
Validator/render asymmetry: a hand-crafted top-level
.claimentry via --stdin/--from-file could render without a locator (escaping exit-4). NOT reachable via canonical --from-store (store never emits top-level .claim); trust framing intact (locator-completeness gap, not trust bypass). Fast-follow #905.GO for id-11 + merge at FULL-40
d3318c5910eed3ea48d94b58f8ef3f28e9962c42. Non-executor.GO — Gate-16 id-11 stamp, pinned to exact FULL head
d3318c5910.Basis: verbatim RoR (comment 18901) — independent contract review APPROVE (all 8 criteria vs CONVERGED-DESIGN §2.1/§2.5, red-first reproduced). The §2.5 HMAC question is ADJUDICATED with manual recomputation: wake_id independently generated, outside the signed field-set, prepended-to-bind — non-circularity is generation-independence, not input-exclusion (builder/Mos/reviewer concordant; the brief gloss was the artifact). Two-tier trust, hard-locator fail-loud, scrub + secret-canary, key-by-name all verified. #905 tracked as non-blocking locator-completeness hardening on non-canonical input paths. CI terminal-green. W3 of EPIC #892. Named executor: Mos (id-11), squash pinned.