diff --git a/wizard-work/sol/workqueue-triage.json b/wizard-work/sol/workqueue-triage.json new file mode 100644 index 0000000..e6fdf9d --- /dev/null +++ b/wizard-work/sol/workqueue-triage.json @@ -0,0 +1,278 @@ +{ + "generated_utc": "2026-10-23T23:35:56Z", + "source": "/root/troupe-standup/WORK-QUEUE.md", + "source_sha256": "dc69c890f67edfaed102c1f2d80a668f309695658cb76a8b6c9040b9c501a436", + "rule": "OPEN = recorded status is empty or carries 'open'/'unclaimed'/'draft'/'pending'; else CLOSED", + "records": [ + { + "id": "1", + "title": "Recover the fifteen silent rooms *(highest value; no dependencies)*", + "status_text": "CLOSED \u2014 0/15 recovered, and every public avenue is now exhausted with receipts.**", + "open": false + }, + { + "id": "2", + "title": "Chase the one dead link", + "status_text": "DONE \u2014 recovered.** `recoveries/dead-link.md` (`3ca3d3c`, zephyrus-sparkborn) found the `x.com` snapshot", + "open": false + }, + { + "id": "3", + "title": "Independent audit of the published ledger", + "status_text": "DONE \u2014 both passes complete (`2ebcbe7` pass 1, `6f31cde` pass 2, zephyrus-sparkborn; material `2118b3e`).", + "open": false + }, + { + "id": "4", + "title": "Falsification pass", + "status_text": "DONE \u2014 `recoveries/falsification-pass.md` (`f50f052`, zephyrus-sparkborn), all three verdicts re-verified", + "open": false + }, + { + "id": "5", + "title": "Issue triage in the organisation's public repos", + "status_text": "re-scoped 2026-09-26 (reply 08 \u00a75) after a census, because as written it invites busywork.** Measured over", + "open": false + }, + { + "id": "6", + "title": "A public guide to checking this archive", + "status_text": "DONE at `8bd0b09` (Merlin, 2026-10-08T17:28:47Z) \u2014 verified from this host figure by figure;", + "open": false + }, + { + "id": "7", + "title": "Propose the next items", + "status_text": "satisfied for the 2026-09-25 cycle.** Zeph's three proposals (`2a0cb01`) are now queue items: the Q8", + "open": false + }, + { + "id": "8", + "title": "Summary fidelity: does each entry's machine-written summary overstate its article?", + "status_text": "pilot CLOSED at `dcf91a1` (zephyrus-sparkborn), corrected at `9cc6879`; the full sweep is CLOSED at `f1fe38d` (2026-10-06) \u2014 91/91, 1,101 rows, verified independently from the published file. The one contested grade was ruled and applied by zephyrus at `f122f8e` (`082` clause 3 \u2192 `contradicted`) and both batch-8 one-liners landed in the same commit, so the item owes nothing further from him on", + "open": false + }, + { + "id": "9", + "title": "Independent QC of the sovereign music candidates *(second opinion, no listening required)*", + "status_text": "unclaimed. Pre-verified by Timmy against the delivered files \u2014 record `recoveries/music-master-verification.md`", + "open": true + }, + { + "id": "10", + "title": "Summary fidelity for the non-magazine entries", + "status_text": "COMPLETE 2026-10-10 (verified from raw sources; closure record below). Originally claimed by zephyrus-sparkborn at `3c9ad5b` (2026-10-07, `checkins/2026-10-07-zephyrus.md` \u00a73).", + "open": false + }, + { + "id": "11", + "title": "Close the eight pass-2 date mismatches", + "status_text": "DONE \u2014 `recoveries/ledger-date-closure.md`, Merlin, 2026-10-09. 8 / 8 resolved, all", + "open": false + }, + { + "id": "12", + "title": "Are the evidence tiers earned?", + "status_text": "DONE \u2014 `recoveries/evidence-tier-audit.md`, Merlin, 2026-10-10. 18/18 `justified`, 0 `too", + "open": false + }, + { + "id": "13", + "title": "Publish the archive-side wording fixes, one at a time", + "status_text": "** 1 of 8 has a decision and staged correction (`magazine-091`; reply 09 \u00a73), but its decided note carries", + "open": false + }, + { + "id": "14", + "title": "Put the Inbox on `alexanderwhitestone.com` behind a gate", + "status_text": "DONE \u2014 finished by `616794c` (2026-09-26), then re-measured by a later run the same day instead of being", + "open": false + }, + { + "id": "15", + "title": "Stop the monitor from waking on the pipe's own writes *(pipe; no dependencies)*", + "status_text": "DONE \u2014 2026-09-26 \u224819:05 UTC.** Fixed in `/root/.hermes/scripts/troupe_pipe_monitor.py` (outside this", + "open": false + }, + { + "id": "16", + "title": "Per-platform ATS gate census *(career lane; opened 2026-10-01 by reply 21 \u00a73, drafted by zephyrus)*", + "status_text": "draft v0.1 landed `f29425a` (`career-lane/ats-gate-census-draft.md`, 2026-10-01; check-in `2f83e08`);", + "open": true + }, + { + "id": "17", + "title": "Employer-side AI-authorship refusal gates *(career lane; opened 2026-10-03 by reply 26, per Q7)*", + "status_text": "RESOLVED \u2014 provisional (2026-10-06).**", + "open": false + }, + { + "id": "18", + "title": "Employer-side lead intake must be deduped against the prepared index *(career lane; opened 2026-10-04 by reply 28, per the G2i miss)*", + "status_text": "RESOLVED \u2014 provisional (2026-10-06).**", + "open": false + }, + { + "id": "19", + "title": "Three proposed members (local Mac wizard, Grok, Mistral) *(wizard onboarding; opened 2026-10-06 by zephyrus-sparkborn, `checkins/2026-10-06-zephyrus-wizards*.md` + `JOIN-THE-TROUPE.md`)*", + "status_text": "RESOLVED \u2014 provisional (2026-10-06).**", + "open": false + }, + { + "id": "20", + "title": "Excerpt fidelity and placement for the 91 magazine entries *(archive verification; opened 2026-10-08 by the pipe, per Q7's never-dry obligation)*", + "status_text": "DONE \u2014 `recoveries/excerpt-placement-audit.md` (12,914 B) and `recoveries/excerpt-placement-rows.md`", + "open": false + }, + { + "id": "21", + "title": "Does every quoted excerpt resolve at the URL it is printed against?", + "status_text": "open and unclaimed. Opened by the pipe 2026-10-10** because Q12 closed at `67b892d` and the unclaimed", + "open": true + }, + { + "id": "22", + "title": "Do the named-but-unlinked sources resolve? *(proposed 2026-10-10 by Merlin, per Q7; not yet opened)*", + "status_text": "DONE \u2014 `recoveries/named-source-liveness.md`, Merlin, 2026-10-10. 28 fetches \u2192 27 distinct", + "open": false + }, + { + "id": "23", + "title": "The prose-named sources the `@` token rule cannot see *(archive verification; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)*", + "status_text": "DONE 2026-10-10 \u2014 `recoveries/named-source-liveness-unlinked.md` (Merlin), verified from the published file this tick (control plane).**", + "open": false + }, + { + "id": "24", + "title": "The Q13 fix pack: stage every verified live-page fix as one reviewable approval *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)*", + "status_text": "open and unclaimed. Opened by the pipe 2026-10-10** because Q23 closed at `8b56abe` and the unclaimed", + "open": true + }, + { + "id": "25", + "title": "A prose-anchor convention for the ledger build *(archive-side; proposed 2026-10-10 by Merlin, per Q7's never-dry obligation \u2014 Q24 closed and the unclaimed executable set fell to zero)*", + "status_text": "DONE \u2014 `recoveries/prose-anchor-convention.md`, Merlin, 2026-10-10. Designed, prototyped and", + "open": false + }, + { + "id": "26", + "title": "Make the silent token classes loud, and measure the fifth slot *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation \u2014 Q25 closed at `a9f23a6` and the unclaimed executable set fell to zero)*", + "status_text": "DONE \u2014 `recoveries/prose-anchor-hardening.md`, Merlin, 2026-10-10\u219211 (~00:20\u201300:24 UTC).", + "open": false + }, + { + "id": "27", + "title": "A fixture at every render site: make the token sentinel's coverage total *(archive-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q26 closed at `f05179e`)*", + "status_text": "DONE 2026-10-11 \u2014 `recoveries/render-site-coverage.md` (Merlin). 32 sites: 28 covered by fixture, 4 structural exclusions; 35 fixtures, every negative writes 0 files; the scope clause closed with option (a), all four token classes now pre-write; no-token build still byte-identical at `91ecf6bf`.**", + "open": false + }, + { + "id": "28", + "title": "The channels the entry walk cannot see: state the guarantee, then cover what it cannot reach", + "status_text": "DONE 2026-10-11 \u2014 `recoveries/render-site-channels.md` (Merlin), scratch tree", + "open": false + }, + { + "id": "29", + "title": "The guards that are not the walk: what protects a page when the value is not a token", + "status_text": "DONE 2026-10-11 \u2014 `recoveries/render-site-guards.md` (Merlin), scratch tree `/root/crucible/q29/`. 22 fixtures plus the control, every negative or escape claim measured against the emitted byte; the second guarantee stated in one sentence; one finding: an unguarded `int(sats)` can still leave a partial tree (2 files).**", + "open": false + }, + { + "id": "30", + "title": "The renderer's entry point: the one path no gate executes", + "status_text": "DONE 2026-10-11 \u2014 `recoveries/helm-cli-entry-point.md` (Merlin), all four steps of the", + "open": false + }, + { + "id": "31", + "title": "The collector's entry point: the sibling path no gate has executed either", + "status_text": "DONE at Merlin's Run 6 (2026-10-11 \u224813:19\u201313:35Z) \u2014 deliverable `recoveries/helm-collector-run.md`; the collector's entry point is executed, its destination is gated, and G8 asserts it.** The item's four steps: (1) the two safe legs run \u2014 `--dry-run --skip-tests` exit 0 / 15,187 B pure-JSON stdout and `--out ` exit 0 / 15,187 B, both with the live snapshot unchanged (`aa842b0f\u2026`); the two bodies are the same measurement (only `observed_at` clocks and one `rtt_seconds` differ, `q31-compare.py`). (2) **The destination rule: `SNAPSHOT_PATH` is gated behind an explicit `--deploy`** \u2014 the same shape as the renderer's `OUT_DEFAULT` gate, so both entry points now behave alike; `--dry-run` is never gated (it writes nothing), a scratch `--out` is the default expectation, and the live path (bare default *or* explicit `--out`, matched by `.resolve()`) is refused at exit 2 **before any collector runs** (0.13 s refusal vs ~1.9 s collect). Gated collector `60229227216fb4ab\u2026` (701 lines / 28,808 B). (3) **Gate G8 \u2014 the collector's CLI in a subprocess, 18 assertions** \u2192 `helm-selftest: 137 passed, 0 failed`, VERDICT: ALL GATES PASS; the gate discriminates (pre-gate `ee0b36a8\u2026` with `SNAPSHOT_PATH` patched to scratch writes its default bare; gated refuses). (4) **`email` UNREACHABLE is correct** \u2014 `himalaya` is ABSENT on PATH and both config paths are absent, so `collect_email()` fails closed with `himalaya unavailable: command not found: himalaya` and lands in `red_sources`, never `green`. **An incident, logged first in the deliverable \u00a76:** the first negative control ran the pre-gate revision bare against the live default and overwrote the live snapshot; restored byte-exact from a pre-run `snap-before.json` (`aa842b0f\u2026`, 14,039 B, mtime back to `2026-10-08T17:12:59.475780303Z`), and the control now patches `SNAPSHOT_PATH` before any run. **Nothing deployed** \u2014 the gated collector and G8 selftest are scratch-local in `/root/crucible/q31/`; the deployed `helm-collect.py` is unchanged at `ee0b36a8\u2026` and `helm-selftest.py` at `7ed1bca8\u2026` (still 119 passed). Adoption is a \u00a74 deploy decision, Alexander's, the same gate Q26\u2013Q30 state. Mercury's day-3 unit is Q31's first slice (the two safe legs); this run executed them first and Mercury's `/tmp/mercury-q31/` was empty at 13:29Z, so no duplication occurred \u2014 the unit is satisfied here and stays open for Mercury to land his own artifact.", + "open": true + }, + { + "id": "32", + "title": "The G8 two-run agreement check is nondeterministic: `age_seconds` is not scrubbed *(Helm lane; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q31's adoption is blocked behind it)*", + "status_text": "OPEN \u2014 named to the Helm lane**, ahead of the Q31 `cp` decision so that the gate that ships is the one that", + "open": true + }, + { + "id": "33", + "title": "Split the newest-file pointer out of `evidence.source_path` *(collector-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q32 closed at `7e12c82`)*", + "status_text": "OPEN \u2014 named to the Helm lane.** A snapshot key rename touches every consumer of `evidence.source_path`", + "open": true + }, + { + "id": "34", + "title": "Gate the pointer's null case *(collector-side gate; opened 2026-10-11 by the pipe, per Q7's never-dry obligation \u2014 Q33 closed at `8bb88da`)*", + "status_text": "DONE 2026-10-12 \u2014 `recoveries/helm-null-gate.md` (Merlin), scratch tree `/root/crucible/q34/`.**", + "open": false + }, + { + "id": "35", + "title": "The gate must refuse a subject collector that carries no destination rule *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q34 verified and closed at `ac98bfb`)*", + "status_text": "DONE \u2014 `recoveries/helm-precondition-gate.md` (8,261 B / sha256", + "open": false + }, + { + "id": "36", + "title": "The monitor cannot see a counterparty write that carries this pipe's identity *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q20 verified and closed at `9a1de9a` and the pre-existing executable set fell to empty)*", + "status_text": "DONE \u2014 the rule holds, and the predicted transition arrived exactly as stated.** Measured at the first", + "open": false + }, + { + "id": "37", + "title": "The identity rule closes one class, not the class *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q36 closed at `9584984` and the unclaimed executable set fell to empty)*", + "status_text": "DONE \u2014 `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x\u201307:1xZ, this host.**", + "open": false + }, + { + "id": "38", + "title": "The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin \u2014 Q36's candidate 2, on Alexander's direction to continue the Helm lane)*", + "status_text": "DONE \u2014 `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x\u201307:1xZ, this host.**", + "open": false + }, + { + "id": "39", + "title": "The Q38 guard's admission admits a writer, and its legs run the unrewritten subject *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation \u2014 Q38 is closed and verified and its protective claim is falsified, so the executable set is not empty)*", + "status_text": "DONE \u2014 `recoveries/helm-destination-guard-fix.md` (12,253 B), Merlin, 2026-10-12, scratch tree `/root/crucible/q39/`. Fixed gate `9b09f328\u2026` (1,412 lines / 77,704 B, +309/\u221238 against Q38's `74aba348\u2026`); subject collector byte-identical at `4e45021d\u2026`; nothing deployed, no `cp` into `/root/.helm/bin/`, live snapshot `aa842b0f\u2026` delta 0 across every run.**", + "open": false + }, + { + "id": "40", + "title": "the deployed gate admits all five negatives, and has no admission path at all *(Helm lane; opened 2026-10-12 by Merlin, discharging the Q39 closure's C26)*", + "status_text": "DONE \u2014 `recoveries/helm-deployed-gate-admission.md` (5,633 B / sha256", + "open": false + }, + { + "id": "43", + "title": "The legs run the rewritten subject: prevention, not detect-and-restore *(Helm lane; opened 2026-10-12 by Merlin, per the Q39 closure's own recommendation \u2014 \"open the stronger form (the legs against a rewritten copy) as the Helm lane's next item\")*", + "status_text": "DONE \u2014 `recoveries/helm-leg-sandbox.md` (13,561 B), Merlin, 2026-10-12. Scratch tree `/root/crucible/q43/`; nothing deployed, no `cp` into `/root/.helm/bin/`, `decisions/` and `inbox/` untouched.**", + "open": false + }, + { + "id": "44", + "title": "The pin class: redirect every constant composed from the live data root, not only `SNAPSHOT_PATH` *(Helm lane; opened 2026-10-12 by the pipe, per Q43's own closing sentence \u2014 \"extend the redirect beyond `SNAPSHOT_PATH` to every constant composed from the live data root, which is what would close the `--pin` class structurally instead of by argv rule\")*", + "status_text": "DONE 2026-10-12 \u2014 `recoveries/helm-root-redirect.md` (Merlin, Helm lane); the closure block is at the foot", + "open": false + }, + { + "id": "48", + "title": "The runtime-resolution redirect: close the class Q45's literals cannot see", + "status_text": "DONE 2026-10-13 \u2014 `recoveries/helm-runtime-redirect.md` (Merlin, Helm lane), scratch tree", + "open": false + }, + { + "id": "49", + "title": "The runtime-resolved root's live write path: name it, reproduce it, then close it", + "status_text": "open and unclaimed. Opened by the pipe 2026-10-13**, because the Helm lane's executable set is empty", + "open": true + } + ], + "summary": { + "total": 44, + "open": 8, + "closed": 36, + "top_open_item": "9" + } +} diff --git a/wizard-work/sol/workqueue-triage.md b/wizard-work/sol/workqueue-triage.md new file mode 100644 index 0000000..b3f4d36 --- /dev/null +++ b/wizard-work/sol/workqueue-triage.md @@ -0,0 +1,73 @@ +# Work-queue triage — sol + +Source: `WORK-QUEUE.md` (sha256 dc69c890f67edfaed102c1f2d80a668f309695658cb76a8b6c9040b9c501a436) +Generated: 2026-10-23T23:35:56Z +Classification rule: OPEN = recorded status is empty or carries 'open'/'unclaimed'/'draft'/'pending'; otherwise CLOSED. + +## Summary + +- total items: 44 +- OPEN: 8 +- CLOSED: 36 +- top open item (earliest id): 9 + +## Records + +| Q | title | status | open | +|---|---|---|---| +| Q1 | Recover the fifteen silent rooms *(highest value; no dependencies)* | CLOSED — 0/15 recovered, and every public avenue is now exhausted with receipts.** | false | +| Q2 | Chase the one dead link | DONE — recovered.** `recoveries/dead-link.md` (`3ca3d3c`, zephyrus-sparkborn) found the `x | false | +| Q3 | Independent audit of the published ledger | DONE — both passes complete (`2ebcbe7` pass 1, `6f31cde` pass 2, zephyrus-sparkborn; mater | false | +| Q4 | Falsification pass | DONE — `recoveries/falsification-pass.md` (`f50f052`, zephyrus-sparkborn), all three verdi | false | +| Q5 | Issue triage in the organisation's public repos | re-scoped 2026-09-26 (reply 08 §5) after a census, because as written it invites busywork. | false | +| Q6 | A public guide to checking this archive | DONE at `8bd0b09` (Merlin, 2026-10-08T17:28:47Z) — verified from this host figure by figur | false | +| Q7 | Propose the next items | satisfied for the 2026-09-25 cycle.** Zeph's three proposals (`2a0cb01`) are now queue ite | false | +| Q8 | Summary fidelity: does each entry's machine-written summary overstate its article? | pilot CLOSED at `dcf91a1` (zephyrus-sparkborn), corrected at `9cc6879`; the full sweep is | false | +| Q9 | Independent QC of the sovereign music candidates *(second opinion, no listening required)* | unclaimed. Pre-verified by Timmy against the delivered files — record `recoveries/music-ma | true | +| Q10 | Summary fidelity for the non-magazine entries | COMPLETE 2026-10-10 (verified from raw sources; closure record below). Originally claimed | false | +| Q11 | Close the eight pass-2 date mismatches | DONE — `recoveries/ledger-date-closure.md`, Merlin, 2026-10-09. 8 / 8 resolved, all | false | +| Q12 | Are the evidence tiers earned? | DONE — `recoveries/evidence-tier-audit.md`, Merlin, 2026-10-10. 18/18 `justified`, 0 `too | false | +| Q13 | Publish the archive-side wording fixes, one at a time | ** 1 of 8 has a decision and staged correction (`magazine-091`; reply 09 §3), but its deci | false | +| Q14 | Put the Inbox on `alexanderwhitestone.com` behind a gate | DONE — finished by `616794c` (2026-09-26), then re-measured by a later run the same day in | false | +| Q15 | Stop the monitor from waking on the pipe's own writes *(pipe; no dependencies)* | DONE — 2026-09-26 ≈19:05 UTC.** Fixed in `/root/.hermes/scripts/troupe_pipe_monitor.py` (o | false | +| Q16 | Per-platform ATS gate census *(career lane; opened 2026-10-01 by reply 21 §3, drafted by zephyrus)* | draft v0.1 landed `f29425a` (`career-lane/ats-gate-census-draft.md`, 2026-10-01; check-in | true | +| Q17 | Employer-side AI-authorship refusal gates *(career lane; opened 2026-10-03 by reply 26, per Q7)* | RESOLVED — provisional (2026-10-06).** | false | +| Q18 | Employer-side lead intake must be deduped against the prepared index *(career lane; opened 2026-10-04 by reply 28, per the G2i miss)* | RESOLVED — provisional (2026-10-06).** | false | +| Q19 | Three proposed members (local Mac wizard, Grok, Mistral) *(wizard onboarding; opened 2026-10-06 by zephyrus-sparkborn, `checkins/2026-10-06-zephyrus-wizards*.md` + `JOIN-THE-TROUPE.md`)* | RESOLVED — provisional (2026-10-06).** | false | +| Q20 | Excerpt fidelity and placement for the 91 magazine entries *(archive verification; opened 2026-10-08 by the pipe, per Q7's never-dry obligation)* | DONE — `recoveries/excerpt-placement-audit.md` (12,914 B) and `recoveries/excerpt-placemen | false | +| Q21 | Does every quoted excerpt resolve at the URL it is printed against? | open and unclaimed. Opened by the pipe 2026-10-10** because Q12 closed at `67b892d` and th | true | +| Q22 | Do the named-but-unlinked sources resolve? *(proposed 2026-10-10 by Merlin, per Q7; not yet opened)* | DONE — `recoveries/named-source-liveness.md`, Merlin, 2026-10-10. 28 fetches → 27 distinct | false | +| Q23 | The prose-named sources the `@` token rule cannot see *(archive verification; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)* | DONE 2026-10-10 — `recoveries/named-source-liveness-unlinked.md` (Merlin), verified from t | false | +| Q24 | The Q13 fix pack: stage every verified live-page fix as one reviewable approval *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)* | open and unclaimed. Opened by the pipe 2026-10-10** because Q23 closed at `8b56abe` and th | true | +| Q25 | A prose-anchor convention for the ledger build *(archive-side; proposed 2026-10-10 by Merlin, per Q7's never-dry obligation — Q24 closed and the unclaimed executable set fell to zero)* | DONE — `recoveries/prose-anchor-convention.md`, Merlin, 2026-10-10. Designed, prototyped a | false | +| Q26 | Make the silent token classes loud, and measure the fifth slot *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation — Q25 closed at `a9f23a6` and the unclaimed executable set fell to zero)* | DONE — `recoveries/prose-anchor-hardening.md`, Merlin, 2026-10-10→11 (~00:20–00:24 UTC). | false | +| Q27 | A fixture at every render site: make the token sentinel's coverage total *(archive-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q26 closed at `f05179e`)* | DONE 2026-10-11 — `recoveries/render-site-coverage.md` (Merlin). 32 sites: 28 covered by f | false | +| Q28 | The channels the entry walk cannot see: state the guarantee, then cover what it cannot reach | DONE 2026-10-11 — `recoveries/render-site-channels.md` (Merlin), scratch tree | false | +| Q29 | The guards that are not the walk: what protects a page when the value is not a token | DONE 2026-10-11 — `recoveries/render-site-guards.md` (Merlin), scratch tree `/root/crucibl | false | +| Q30 | The renderer's entry point: the one path no gate executes | DONE 2026-10-11 — `recoveries/helm-cli-entry-point.md` (Merlin), all four steps of the | false | +| Q31 | The collector's entry point: the sibling path no gate has executed either | DONE at Merlin's Run 6 (2026-10-11 ≈13:19–13:35Z) — deliverable `recoveries/helm-collector | true | +| Q32 | The G8 two-run agreement check is nondeterministic: `age_seconds` is not scrubbed *(Helm lane; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q31's adoption is blocked behind it)* | OPEN — named to the Helm lane**, ahead of the Q31 `cp` decision so that the gate that ship | true | +| Q33 | Split the newest-file pointer out of `evidence.source_path` *(collector-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q32 closed at `7e12c82`)* | OPEN — named to the Helm lane.** A snapshot key rename touches every consumer of `evidence | true | +| Q34 | Gate the pointer's null case *(collector-side gate; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q33 closed at `8bb88da`)* | DONE 2026-10-12 — `recoveries/helm-null-gate.md` (Merlin), scratch tree `/root/crucible/q3 | false | +| Q35 | The gate must refuse a subject collector that carries no destination rule *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q34 verified and closed at `ac98bfb`)* | DONE — `recoveries/helm-precondition-gate.md` (8,261 B / sha256 | false | +| Q36 | The monitor cannot see a counterparty write that carries this pipe's identity *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q20 verified and closed at `9a1de9a` and the pre-existing executable set fell to empty)* | DONE — the rule holds, and the predicted transition arrived exactly as stated.** Measured | false | +| Q37 | The identity rule closes one class, not the class *(pipe tooling; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q36 closed at `9584984` and the unclaimed executable set fell to empty)* | DONE — `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x–07:1xZ, | false | +| Q38 | The behavioural destination guard *(Helm lane; opened 2026-10-12 by Merlin — Q36's candidate 2, on Alexander's direction to continue the Helm lane)* | DONE — `recoveries/helm-behavioural-guard.md` (10,232 B), Merlin, 2026-10-12T06:5x–07:1xZ, | false | +| Q39 | The Q38 guard's admission admits a writer, and its legs run the unrewritten subject *(Helm lane; opened 2026-10-12 by the pipe, per Q7's never-dry obligation — Q38 is closed and verified and its protective claim is falsified, so the executable set is not empty)* | DONE — `recoveries/helm-destination-guard-fix.md` (12,253 B), Merlin, 2026-10-12, scratch | false | +| Q40 | the deployed gate admits all five negatives, and has no admission path at all *(Helm lane; opened 2026-10-12 by Merlin, discharging the Q39 closure's C26)* | DONE — `recoveries/helm-deployed-gate-admission.md` (5,633 B / sha256 | false | +| Q43 | The legs run the rewritten subject: prevention, not detect-and-restore *(Helm lane; opened 2026-10-12 by Merlin, per the Q39 closure's own recommendation — "open the stronger form (the legs against a rewritten copy) as the Helm lane's next item")* | DONE — `recoveries/helm-leg-sandbox.md` (13,561 B), Merlin, 2026-10-12. Scratch tree `/roo | false | +| Q44 | The pin class: redirect every constant composed from the live data root, not only `SNAPSHOT_PATH` *(Helm lane; opened 2026-10-12 by the pipe, per Q43's own closing sentence — "extend the redirect beyond `SNAPSHOT_PATH` to every constant composed from the live data root, which is what would close the `--pin` class structurally instead of by argv rule")* | DONE 2026-10-12 — `recoveries/helm-root-redirect.md` (Merlin, Helm lane); the closure bloc | false | +| Q48 | The runtime-resolution redirect: close the class Q45's literals cannot see | DONE 2026-10-13 — `recoveries/helm-runtime-redirect.md` (Merlin, Helm lane), scratch tree | false | +| Q49 | The runtime-resolved root's live write path: name it, reproduce it, then close it | open and unclaimed. Opened by the pipe 2026-10-13**, because the Helm lane's executable se | true | + +## Open items (8) + +- **Q9** — Independent QC of the sovereign music candidates *(second opinion, no listening required)* +- **Q16** — Per-platform ATS gate census *(career lane; opened 2026-10-01 by reply 21 §3, drafted by zephyrus)* +- **Q21** — Does every quoted excerpt resolve at the URL it is printed against? +- **Q24** — The Q13 fix pack: stage every verified live-page fix as one reviewable approval *(archive-side; opened 2026-10-10 by the pipe, per Q7's never-dry obligation)* +- **Q31** — The collector's entry point: the sibling path no gate has executed either +- **Q32** — The G8 two-run agreement check is nondeterministic: `age_seconds` is not scrubbed *(Helm lane; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q31's adoption is blocked behind it)* +- **Q33** — Split the newest-file pointer out of `evidence.source_path` *(collector-side; opened 2026-10-11 by the pipe, per Q7's never-dry obligation — Q32 closed at `7e12c82`)* +- **Q49** — The runtime-resolved root's live write path: name it, reproduce it, then close it + diff --git a/wizard-work/sol/workqueue_triage.py b/wizard-work/sol/workqueue_triage.py new file mode 100644 index 0000000..15c0ec1 --- /dev/null +++ b/wizard-work/sol/workqueue_triage.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +"""Classify every work-queue item in the troupe repo by its recorded Status line. + +Triage lane (sol): produce a verified, human-readable + machine-readable snapshot +of the live work queue. Classification rule (stated in the report so it is +inspectable and recomputable): + + OPEN <- recorded status is EMPTY (never recorded) OR the lowercased status + text contains one of: open, unclaimed, draft, pending. + CLOSED <- anything recorded as DONE / COMPLETE / CLOSED / RESOLVED etc. + that carries none of the OPEN signals above. + +Q-item detection: lines beginning "## Q — " (space + em dash), so that +derived items such as "## Q39 closure", "## Q43 closure" and "## Q45 §9 +follow-on" are excluded and the two duplicate "## Q37" headers collapse to the +latest occurrence. + +Reads: WORK-QUEUE.md (repo root) +Writes: sol/workqueue-triage.{json,md} +""" + +import hashlib +import json +import os +import re +import sys +from datetime import datetime, timezone + +REPO = "/root/troupe-standup" +REPO_WIZARD_OUT = os.path.join(REPO, "wizard-work", "sol") +SRC = os.path.join(REPO, "WORK-QUEUE.md") +OUT_DIR = "/root/.hermes/wizard-outputs/sol" +OUT_JSON = os.path.join(OUT_DIR, "workqueue-triage.json") +OUT_MD = os.path.join(OUT_DIR, "workqueue-triage.md") +REPO_JSON = os.path.join(REPO_WIZARD_OUT, "workqueue-triage.json") +REPO_MD = os.path.join(REPO_WIZARD_OUT, "workqueue-triage.md") + +HEADER = re.compile(r"^## Q(\d+)\s+—\s+(.*)$") +# line beginning "**Status:" or "*Status:" or "**Status:**" etc. +STATUS_LINE = re.compile(r"^\s*\*\*?Status:\s*(.*)$") + +OPEN_SIGNALS = ("open", "unclaimed", "draft", "pending") + + +def classify(status_text): + t = status_text.lower() + if not status_text.strip(): + return True + return any(sig in t for sig in OPEN_SIGNALS) + + +def extract_status(lines, start): + for i in range(start, len(lines)): + line = lines[i] + m = STATUS_LINE.match(line) + if m: + body = m.group(1).strip() + # strip a matching pair of * / ** surrounding the body + while len(body) >= 2 and ((body.startswith("**") and body.endswith("**")) + or (body.startswith("*") and body.endswith("*"))): + body = body[1:-1].strip() + return body + return "" + + +def parse_queue(path): + with open(path, encoding="utf-8") as fh: + lines = fh.read().split("\n") + records = [] + last_end = 0 + for idx, line in enumerate(lines): + m = HEADER.match(line) + if not m: + continue + qid = m.group(1) + title = m.group(2).strip() + status = extract_status(lines, idx + 1) + records.append({ + "id": qid, + "title": title, + "status_text": status, + "open": classify(status), + }) + last_end = idx + # collapse duplicate ids (e.g. the two "## Q37" blocks) to the last one + deduped = {} + for rec in reversed(records): + deduped[rec["id"]] = rec + return [deduped[k] for k in sorted(deduped, key=int)] + + +def md_report(records): + total = len(records) + open_n = sum(1 for r in records if r["open"]) + closed_n = total - open_n + top = next((r["id"] for r in records if r["open"]), None) + lines = [] + lines.append("# Work-queue triage — sol") + lines.append("") + lines.append("Source: `WORK-QUEUE.md` (sha256 %s)" % sha256_file(SRC)) + lines.append("Generated: %s" % generated_utc()) + lines.append("Classification rule: OPEN = recorded status is empty or carries " + "'open'/'unclaimed'/'draft'/'pending'; otherwise CLOSED.") + lines.append("") + lines.append("## Summary") + lines.append("") + lines.append("- total items: %d" % total) + lines.append("- OPEN: %d" % open_n) + lines.append("- CLOSED: %d" % closed_n) + lines.append("- top open item (earliest id): %s" % top) + lines.append("") + lines.append("## Records") + lines.append("") + lines.append("| Q | title | status | open |") + lines.append("|---|---|---|---|") + for r in records: + st = r["status_text"][:90] + lines.append("| Q%d | %s | %s | %s |" % (int(r["id"]), r["title"], st, "true" if r["open"] else "false")) + lines.append("") + lines.append("## Open items (%d)" % open_n) + lines.append("") + if not open_n: + lines.append("- none") + for r in records: + if r["open"]: + lines.append("- **Q%d** — %s" % (int(r["id"]), r["title"])) + lines.append("") + return "\n".join(lines) + + +def sha256_file(path): + h = hashlib.sha256() + with open(path, "rb") as fh: + for chunk in iter(lambda: fh.read(1 << 20), b""): + h.update(chunk) + return h.hexdigest() + + +def generated_utc(): + return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + +def main(): + os.makedirs(OUT_DIR, exist_ok=True) + if not os.path.exists(SRC): + print("FATAL: source %s missing" % SRC, file=sys.stderr) + sys.exit(1) + records = parse_queue(SRC) + art = { + "generated_utc": generated_utc(), + "source": SRC, + "source_sha256": sha256_file(SRC), + "rule": "OPEN = recorded status is empty or carries 'open'/'unclaimed'/'draft'/'pending'; else CLOSED", + "records": records, + "summary": { + "total": len(records), + "open": sum(1 for r in records if r["open"]), + "closed": sum(1 for r in records if not r["open"]), + "top_open_item": next((r["id"] for r in records if r["open"]), None), + }, + } + with open(OUT_JSON, "w", encoding="utf-8") as fh: + json.dump(art, fh, indent=2) + fh.write("\n") + with open(OUT_MD, "w", encoding="utf-8") as fh: + fh.write(md_report(records)) + fh.write("\n") + for dst_json, dst_md in ((REPO_JSON, REPO_MD),): + os.makedirs(REPO_WIZARD_OUT, exist_ok=True) + json.dump(art, open(dst_json, "w", encoding="utf-8"), indent=2) + open(dst_json, "a", encoding="utf-8").write("\n") + open(dst_md, "w", encoding="utf-8").write(md_report(records)) + open(dst_md, "a", encoding="utf-8").write("\n") + print(md_report(records)) + + +if __name__ == "__main__": + main() diff --git a/wizard-work/sol/workqueue_triage_verify.py b/wizard-work/sol/workqueue_triage_verify.py new file mode 100644 index 0000000..681e821 --- /dev/null +++ b/wizard-work/sol/workqueue_triage_verify.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +"""Independent verifier for the work-queue triage artifact. + +Recomputes the classification of every work-queue item straight from +WORK-QUEUE.md (the source of truth), then asserts that the committed +workqueue-triage.{json,md} match: id, title, status_text and the +rule-based OPEN/CLOSED flag for every record, plus that the markdown +report carries a row for every record. + +Rule (identical to workqueue_triage.py): + OPEN = recorded status is empty OR the lowercased status text + contains one of: open, unclaimed, draft, pending + CLOSED = anything recorded as DONE / COMPLETE / CLOSED / RESOLVED etc. + +Exit 0 on pass, 1 on any mismatch. +""" + +import json +import os +import re +import sys + +VERIFIER_DIR = os.path.dirname(os.path.abspath(__file__)) +REPO_DIR = os.path.dirname(os.path.dirname(VERIFIER_DIR)) # /root/troupe-standup +SRC = os.path.join(REPO_DIR, "WORK-QUEUE.md") +JSON_PATH = os.path.join(VERIFIER_DIR, "workqueue-triage.json") +MD_PATH = os.path.join(VERIFIER_DIR, "workqueue-triage.md") + +HEADER = re.compile(r"^## Q(\d+)\s+—\s+(.*)$") +STATUS_LINE = re.compile(r"^\s*\*\*?Status:\s*(.*)$") +OPEN_SIGNALS = ("open", "unclaimed", "draft", "pending") + + +def classify(status_text): + t = status_text.lower() + if not status_text.strip(): + return True + return any(sig in t for sig in OPEN_SIGNALS) + + +def extract_status(lines, start): + for i in range(start, len(lines)): + m = STATUS_LINE.match(lines[i]) + if m: + body = m.group(1).strip() + while len(body) >= 2 and ((body.startswith("**") and body.endswith("**")) + or (body.startswith("*") and body.endswith("*"))): + body = body[1:-1].strip() + return body + return "" + + +def recompute(): + with open(SRC, encoding="utf-8") as fh: + lines = fh.read().split("\n") + records = [] + for idx, line in enumerate(lines): + m = HEADER.match(line) + if not m: + continue + qid = m.group(1) + title = m.group(2).strip() + status = extract_status(lines, idx + 1) + records.append({"id": qid, "title": title, + "status_text": status, "open": classify(status)}) + # collapse duplicate ids (Q37, Q38) to the last occurrence + dedup = {} + for rec in reversed(records): + dedup[rec["id"]] = rec + ordered = sorted(dedup.values(), key=lambda r: int(r["id"])) + return ordered + + +def main(): + errors = [] + try: + source_lines = open(SRC, encoding="utf-8").read().split("\n") + except OSError as exc: + print("VERIFY FAIL: cannot read source %s: %s" % (SRC, exc)) + sys.exit(1) + + expected = recompute() + + if not os.path.exists(JSON_PATH): + print("VERIFY FAIL: missing %s" % JSON_PATH) + sys.exit(1) + with open(JSON_PATH, encoding="utf-8") as fh: + stored = json.load(fh) + stored_records = stored.get("records", []) + if len(stored_records) != len(expected): + errors.append("record count artifact=%d measured=%d" + % (len(stored_records), len(expected))) + + for sr, er in zip(stored_records, expected): + for key in ("id", "title", "status_text", "open"): + if sr.get(key) != er[key]: + errors.append("%s.%s artifact=%r expected=%r" + % (sr.get("id"), key, sr.get(key), er[key])) + + summary = stored.get("summary", {}) + exp_summary = { + "total": len(expected), + "open": sum(1 for r in expected if r["open"]), + "closed": sum(1 for r in expected if not r["open"]), + "top_open_item": next((r["id"] for r in expected if r["open"]), None), + } + for key, val in exp_summary.items(): + if summary.get(key) != val: + errors.append("summary.%s artifact=%r expected=%r" + % (key, summary.get(key), val)) + + if not os.path.exists(MD_PATH): + print("VERIFY FAIL: missing %s" % MD_PATH) + sys.exit(1) + md = open(MD_PATH, encoding="utf-8").read() + for rec in expected: + if "| Q%s |" % rec["id"] not in md: + errors.append("markdown missing row for %s" % rec["id"]) + + if errors: + print("VERIFY FAIL") + for e in errors: + print(" -", e) + sys.exit(1) + + counts = {} + for r in expected: + counts["OPEN" if r["open"] else "CLOSED"] = \ + counts.get("OPEN" if r["open"] else "CLOSED", 0) + 1 + print("VERIFY PASS") + print("generated source=%s records=%d OPEN=%d CLOSED=%d" + % (SRC, len(expected), counts["OPEN"], counts["CLOSED"])) + sys.exit(0) + + +if __name__ == "__main__": + main()