@dogfood-lab/study-swarm 1.3.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@
12
12
  > retrieval-grounded research agents; every finding below was fetched this session and the whole set is
13
13
  > gated through Step 4 (`roleos verify-citations` → prism, a different model family) **before** it informs
14
14
  > the architecture. The synthesizer is Claude/Opus; the groundedness lens is Mistral; the existence oracle
15
- > is deterministic retrieval — none of them Claude. Run `study-swarm lint study-swarm-canon-rollback.dispatch.md`
15
+ > is deterministic retrieval — none of them Claude. Run `study-swarm lint examples/study-swarm-canon-rollback.dispatch.md`
16
16
  > (it passes).
17
17
 
18
18
  ## Step 1 — Load-bearing questions
@@ -27,7 +27,7 @@ Each passes the load-bearing test (two real designs hinge on the answer; an adja
27
27
 
28
28
  ## Step 2 — Research dispatch
29
29
 
30
- Five parallel research agents (one per question), each retrieval-required — a source an agent could not fetch did not enter the dispatch — followed by a per-question **coverage-recovery sweep** that re-retrieved and ran a retrieval-based **existence audit** of the first sweep's citations. The recovery pass earned its keep: it corrected the **IETF Idempotency-Key** draft's authors (Jena & Dalal 2025, not the first sweep's guess), softened a **COPE** claim that overstated the source ("watermarked" is Crossref/NISO wording, not COPE's "unmistakably identified"; COPE was then dropped in favour of NISO + Crossref, which cover retain-and-mark directly), resolved **Hsiao & Schneider 2021** on the second pass (the first marked it `retrieved:false`), and flagged a **Bazel** claim as slightly ahead of its cited page (dropped in favour of *Build Systems à la Carte*, which states the verifying-trace mechanism precisely). All corrections are folded into Step 3; the audit is recorded in Step 4.
30
+ Five parallel research agents (one per question), each retrieval-required — a source an agent could not fetch did not enter the dispatch — followed by a per-question **coverage-recovery sweep** that re-retrieved and ran a retrieval-based **existence audit** of the first sweep's citations. The recovery pass earned its keep: it corrected the **IETF Idempotency-Key** draft's authors (Jena & Dalal 2025, not the first sweep's guess), softened a **COPE** claim that overstated the source ("watermarked" is Crossref/NISO wording, not COPE's "unmistakably identified"; COPE was then dropped in favour of NISO + Crossref, which cover retain-and-mark directly), left **Hsiao & Schneider 2021** out (the pinned run recorded `retrieved:false` after the publisher page returned 403; the 5.4% figure is not a finding of this dispatch), and flagged a **Bazel** claim as slightly ahead of its cited page (dropped in favour of *Build Systems à la Carte*, which states the verifying-trace mechanism precisely). All corrections are folded into Step 3; the audit is recorded in Step 4.
31
31
 
32
32
  ## Step 3 — Research grounding
33
33
 
@@ -47,7 +47,6 @@ Five parallel research agents (one per question), each retrieval-required — a
47
47
  12. **(Q3) NISO's CREC recommended practice preserves a retracted item's status as machine-readable metadata, flagged not deleted, and consumable by automated downstream processes.** NISO CREC Working Group 2024 (NISO RP-45-2024, https://www.niso.org/publications/rp-45-2024-crec). Implication: the tombstone is machine-readable so the fail-closed gate consumes it deterministically (pure JSON + SHA-256, no model call), and the record is retained (C5, C6).
48
48
  13. **(Q3) Crossref keeps the original DOI/record and issues a SEPARATE retraction notice with its own DOI, linked to the original (which is marked), rather than removing it.** Crossref 2024 (https://www.crossref.org/documentation/principles-practices/best-practices/versioning/). Implication: the withdrawal receipt is a separate content-addressed record pointing at the withdrawn identifier; the dependent dispatches are marked in place and retained (C8, C5).
49
49
  14. **(Q3) A randomized controlled trial emailing authors who cited a now-retracted article did NOT significantly reduce future citation of retracted papers.** DeVito, Cunningham & Goldacre 2024 (RetractoBot, https://peerreviewcongress.org/abstract/notifying-authors-that-they-have-cited-a-retracted-article-and-future-citations-of-retracted-articles-the-retractobot-randomized-controlled-trial/). Implication: a soft alert is empirically insufficient — the compensator must FAIL CLOSED (a non-zero gate, the andon halt), not merely notify (C6).
50
- 15. **(Q3) Only ~5.4% of post-retraction citations acknowledged the retraction — the overwhelming majority kept using retracted papers as if valid.** Hsiao & Schneider 2021 (DOI:10.1162/qss_a_00155). Implication: without an enforced gate, withdrawn findings keep propagating silently; `requalify --check` must be the default-on barrier, not a notice humans may ignore (C6).
51
50
  16. **(Q3) Retracted research keeps causing downstream harm via an "attention escape" mechanism that disproportionately affects INDIRECTLY citing work.** Huang et al. 2025 (arXiv:2501.00473). Implication: `withdraw` scans the WHOLE corpus, not a single directory — every dispatch citing the withdrawn identifier is flagged, because harm escapes to the indirect layer (C2).
52
51
  17. **(Q4) A saga pairs each transaction with a compensating transaction that undoes its effect "from a semantic point of view" and does not necessarily restore the exact prior state.** Garcia-Molina & Salem 1987 (DOI:10.1145/38713.38742). Implication: the compensator is SEMANTIC, not syntactic — it does not `git revert` the propagation; it flags the dependent so the system reaches a valid, known state. This is *why* a named compensator beyond `revert_dispatch_commit` is required (C1).
53
52
  18. **(Q4) A compensating transaction does not return the system to its start state; because compensation can itself fail and be retried, each step must be idempotent and record progress to resume.** Microsoft 2026 (Azure Architecture Center, https://learn.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction). Implication: `requalify --resolve` is idempotent and records progress in the sidecar, so a re-run resumes correctly rather than double-applying (C7).
@@ -58,20 +57,20 @@ Five parallel research agents (one per question), each retrieval-required — a
58
57
  23. **(Q5) Build Systems à la Carte models incremental builds via rebuilders that consult "verifying traces" — stored dependency hashes — and rebuild a target only when those recorded hashes no longer match.** Mokhov, Mitchell & Peyton Jones 2018 (DOI:10.1145/3236774). Implication: `requalify --check` IS a deterministic `verifyVT` (a fail-closed hash/status comparison); the sibling runner supplies the re-verified value (`recordVT`), keeping the CLI a pure verifier (C11, C12).
59
58
  24. **(Q5) Snakemake re-runs an output when its inputs, parameters, code, or environment change, using checksums rather than trusting timestamps.** Snakemake 2024 (https://snakemake.readthedocs.io/en/stable/project_info/faq.html). Implication: a withdrawn citation is a changed-input trigger — a dependent must be requalified (re-grounded) before it is considered current; clearing the flag is the analog of a re-run producing a fresh, validated output (C6, C12).
60
59
  25. **(Q5) Cassandra deletes by writing a timestamped tombstone marker rather than removing the value, because a hard delete lets an offline replica resurrect the data as a zombie; the marker itself propagates and is auditable.** Apache Cassandra 2024 (https://cassandra.apache.org/doc/latest/cassandra/managing/operating/compaction/tombstones.html). Implication: the tombstone sidecar prevents a withdrawn finding from "resurrecting" into a dependent design on a later run, and the marker (not the absence of data) is what carries the audit (C5).
61
- 26. **(Q5) In a study of N=628, contrastive explanations — the difference between the AI's choice and the user's likely choice — improved independent decision-making versus unilateral explanations, without sacrificing accuracy.** Buçinca et al. 2024 (arXiv:2410.04253). Implication: a withdrawal is surfaced contrastively — "finding N withdrawn because X; you may have relied on it; dispatches A, B flagged — re-ground or override" — never a silent drop (C10).
62
- 27. **(Q5) AI explanations did not improve complementary human-AI team performance; they increased the chance humans accepted the AI's recommendation regardless of correctness (over-reliance).** Bansal et al. 2021 (arXiv:2006.14779). Implication: a silent or unexplained removal of a withdrawn finding risks the same over-reliance — users keep trusting the now-empty design — so the compensator fails closed and forces an explicit re-ground/override (C6, C10).
60
+ 26. **(Q5) In a study of N=628, contrastive explanations — the difference between the AI's choice and the user's likely choice — improved independent decision-making versus unilateral explanations, without sacrificing accuracy.** Buçinca et al. 2024 (arXiv:2410.04253). Implication: a withdrawal is surfaced contrastively — "finding N withdrawn because X; you may have relied on it; dispatches A, B flagged — requalify --resolve --mode removed, or --mode regrounded --note" — never a silent drop (C10).
61
+ 27. **(Q5) AI explanations did not improve complementary human-AI team performance; they increased the chance humans accepted the AI's recommendation regardless of correctness (over-reliance).** Bansal et al. 2021 (arXiv:2006.14779). Implication: a silent or unexplained removal of a withdrawn finding risks the same over-reliance — users keep trusting the now-empty design — so the compensator fails closed and forces an explicit `--mode removed` or `--mode regrounded` (C6, C10).
63
62
 
64
63
  ## Step 4 — External verification
65
64
 
66
65
  <!-- Run against this dispatch's citations through the live runner before Step 5 was locked. -->
67
66
 
68
- **Run against this dispatch's 27 citations through the LIVE runner before Step 5 was locked.** Synthesizer = Claude/Opus; verifier = the deterministic arXiv→Crossref retrieval oracle + a groundedness lens on **`mistral-small:24b`** (ModelFamily `local`, reasoning-stripped — the synthesizer's `anthropic` family is excluded by construction). Command: `roleos verify-citations examples/study-swarm-canon-rollback.dispatch.md --provider ollama` → `prism verify --type citations` (prism v1.6.0). **No verifier was Claude — the protocol did not grade its own homework.**
67
+ **Run against this dispatch's citations through the LIVE runner before Step 5 was locked.** Synthesizer = Claude/Opus; verifier = the deterministic arXiv→Crossref retrieval oracle + a groundedness lens on **`mistral-small:24b`** (ModelFamily `local`, reasoning-stripped — the synthesizer's `anthropic` family is excluded by construction). Command: `roleos verify-citations examples/study-swarm-canon-rollback.dispatch.md --provider ollama` → `prism verify --type citations` (prism v1.6.0). **No verifier was Claude — the protocol did not grade its own homework.**
69
68
 
70
69
  - [x] existence established by **retrieval, not memory** — the structured oracle for the academic subset (arXiv + Crossref DOIs), plus an independent in-session retrieval existence-audit (the coverage-recovery pass) for the RFC/spec/vendor-doc subset.
71
70
  - [x] groundedness checked by a **different family** (`mistral-small:24b`, reasoning-stripped) where the oracle returned an abstract; abstract-less and oracle-unavailable citations **escalated, never auto-passed**.
72
71
  - [x] **≥ 3 decorrelated lenses**: the deterministic arXiv/Crossref oracle + the Mistral groundedness lens + the independent coverage-recovery retrieval existence-audit.
73
72
 
74
- **Verdict: `escalate` (advisory, non-blocking). 0 fabricated, 0 refused.** As on the v1.2 lock dispatch, the gate discriminated by source type: this dispatch is **heavily RFC / OASIS / NISO / vendor-spec sourced**, so most citations are reported `unparsed` by the arXiv/Crossref extractor — **that is not fabrication**; each was existence-verified by direct retrieval this session (the coverage-recovery audit resolved all of them and produced the corrections folded into Step 3). The academic subset (Garcia-Molina & Salem `10.1145/38713.38742`; Build Systems à la Carte `10.1145/3236774`; Hsiao & Schneider `10.1162/qss_a_00155`; Buçinca `arXiv:2410.04253`; Bansal `arXiv:2006.14779`; Huang `arXiv:2501.00473`) was resolved through the oracle. **Receipt captured + cryptographically verified** — see the receipt id and chain hash pinned into this dispatch's [`study-swarm-canon-rollback.lock.json`](study-swarm-canon-rollback.lock.json) (L10), public-key-verified via `prism verify-receipt --public-key` → `signature_valid: true`. Honest ceiling: the signing key is ephemeral and scratchpad-local, so the receipt buys third-party *verifiability*, not anti-forgery.
73
+ **Verdict: `escalate` (advisory, non-blocking). 0 fabricated, 0 refused.** As on the v1.2 lock dispatch, the gate discriminated by source type: this dispatch is **heavily RFC / OASIS / NISO / vendor-spec sourced**, so most citations are reported `unparsed` by the arXiv/Crossref extractor — **that is not fabrication**; each was existence-verified by direct retrieval this session (the coverage-recovery audit resolved all of them and produced the corrections folded into Step 3). The academic subset (Garcia-Molina & Salem `10.1145/38713.38742`; Build Systems à la Carte `10.1145/3236774`; Buçinca `arXiv:2410.04253`; Bansal `arXiv:2006.14779`; Huang `arXiv:2501.00473`) was resolved through the oracle. Hsiao & Schneider 2021 (`10.1162/qss_a_00155`) is a real paper — the 5.4% post-retraction acknowledgment figure is in the PMC text — but this dispatch's pinned run recorded `retrieved:false`, so it is not a finding here. **Receipt captured + cryptographically verified** — see the receipt id and chain hash pinned into this dispatch's [`study-swarm-canon-rollback.lock.json`](study-swarm-canon-rollback.lock.json) (L10), public-key-verified via `prism verify-receipt --public-key` → `signature_valid: true`. Honest ceiling: the signing key is ephemeral and scratchpad-local, so the receipt buys third-party *verifiability*, not anti-forgery.
75
74
 
76
75
  ## Step 5 — Architecture (the canon-rollback compensator)
77
76
 
@@ -86,11 +85,11 @@ Each choice traces to findings by number. Three deterministic, network-free verb
86
85
  - **C3 — A closed, machine-readable reason enum, never free text.** `--reason` is one of `fabricated | misattributed | retracted | verifier-flipped | other`; a withdrawal with no structured cause is rejected. (finding 8)
87
86
  - **C4 — A co-located tombstone sidecar (`<slug>.withdrawn.json`).** Status travels WITH the artifact (the OCSP-stapling property), so a runner reading the dispatch gets the withdrawal status inline with no network call. (finding 2)
88
87
  - **C5 — Flag, never delete (a retained tombstone).** Every mature system retains-and-flags rather than hard-deletes a thing with dependents; the sidecar marks the dispatch and is retained for audit, and a withdrawn finding cannot silently resurrect on a later run. (findings 1, 3, 5, 12, 13, 25)
89
- - **C6 — The gate fails closed (the andon).** `requalify --check` exits non-zero for any unresolved `evidence-withdrawn` flag — a missing re-verification is failure, not an implicit pass — because notification alone provably fails to stop downstream propagation and silent drops drive over-reliance. (findings 6, 14, 15, 24, 27)
88
+ - **C6 — The gate fails closed (the andon).** `requalify --check` exits non-zero for any unresolved `evidence-withdrawn` flag — a missing re-verification is failure, not an implicit pass — because notification alone provably fails to stop downstream propagation and silent drops drive over-reliance. (findings 6, 14, 24, 27)
90
89
  - **C7 — Idempotent resolve + an append-only audit trail.** `requalify --resolve` is idempotent (re-running on a cleared finding is a no-op) and records progress; the sidecar is append-only and version-incremented — a flag or clear is an appended event, never an in-place edit. (findings 4, 9, 18, 19, 21)
91
90
  - **C8 — Content-addressed receipt + sidecar, drift-detectable.** Both carry a self-describing `sha256-…` digest (RFC 8785 JCS + SHA-256) over their body; the receipt's key is the withdrawn identifier and its fingerprint is `receipt_sha256`, so a replay is a safe no-op and any tamper is drift-detectable — the same self-integrity model as `dispatch.lock.json`. (findings 7, 9, 13, 20, 22)
92
91
  - **C9 — Two resolution modes: `removed` vs `regrounded`.** A finding that was fabricated/misattributed is `removed` (the citation is gone — a false-positive analog, checked deterministically); one re-verified in place is `regrounded`, which requires a `--note` attestation, mirroring "resolved-with-evidence." (findings 10, 11)
93
- - **C10 — Contrastive surfacing, never a silent drop.** `withdraw` and `requalify --check` emit a contrastive frame ("you may have relied on this; re-ground or override"), pairing with Step 4's `CANNOT_CONFIRM` checkpoint, because contrastive surfacing improves independent decisions and a silent drop risks over-reliance. (findings 26, 27)
92
+ - **C10 — Contrastive surfacing, never a silent drop.** `withdraw` and `requalify --check` emit a contrastive frame ("you may have relied on this; requalify --resolve --mode removed, or --mode regrounded --note"), pairing with Step 4's `CANNOT_CONFIRM` checkpoint, because contrastive surfacing improves independent decisions and a silent drop risks over-reliance. (findings 26, 27)
94
93
  - **C11 — The compensator operates on the VOLATILE evidence layer, not the STABLE protocol/lock shape.** The tombstone (per-dispatch evidence) is a separate module from the lock (replay-pinning) and `PROTOCOL.md` (the methodology); `requalify --check` is the `verifyVT` of a build system, and `lock --verify` is unaffected by a withdraw/resolve — a Parnas secret-hiding boundary the smoke suite proves holds. (finding 23)
95
94
  - **C12 — Honest ceiling: the CLI flags, gates, and receipts; re-verification defers to the sibling runner.** Like a build system's `recordVT`, the new re-verified value comes from outside (`roleos verify-citations` → prism); `requalify --resolve --mode regrounded` records that it happened, it does not itself re-verify — keeping the CLI zero-dependency, network-free, and deterministic. (findings 11, 23, 24)
96
95
 
@@ -1,63 +1,63 @@
1
1
  {
2
- "schema": "dispatch.lock/v1",
3
- "study_swarm_version": "1.3.0",
4
- "protocol_sha256": "sha256-seELxwXtj+xVxa3mas2cP0J0iMTTpq4vHqFMiUGqmuU=",
5
- "dispatch_sha256": "sha256-V7b/nROpdDfH6TBUDrBwcyxFwR99yihkfIaNFE5yGkk=",
2
+ "schema": "dispatch.lock/v2",
3
+ "study_swarm_version": "2.1.0",
4
+ "protocol_sha256": "sha256-p9LMoGfOGIASHIfFo6RkgpiCtnHlTtxcuPsTzQ+fuYY=",
5
+ "dispatch_sha256": "sha256-ijvMoQs5/bOj7qpVJCd+LTfkyqkmd0nSMAEA936cvBs=",
6
6
  "steps": [
7
7
  {
8
8
  "question_id": "Q1-revocation-propagation",
9
9
  "resolved_model": "claude-opus-4-8",
10
- "prompt_sha256": "sha256-UM5MzdUiL88wbj+GaUsrlwiAwSffNYD6G5KcIRSFcn0=",
11
- "tool_schema_sha256": "sha256-Tuyydf1fteUasUVBy+VzlGijelrqPfvHjI7wHvE9Omk=",
10
+ "prompt_sha256": "sha256-itBKUD1vfwbDaQFlItEbIrWRx4auszx3/MeDUggQRI4=",
11
+ "tool_schema_sha256": "sha256-rAn5uvRldR9ctw1Sb8ZkXIuVRzA8spJBRmFJqkAqUO0=",
12
12
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
13
13
  "params": {
14
14
  "effort": "high"
15
15
  },
16
- "output_sha256": "sha256-utlcmvknCo6mvVE0CJSptTHKAWjAbyAccCUXlV4cuyk="
16
+ "output_sha256": "sha256-nIWvzFM74zz5s6DddRBXeoZXUUrn5W5YB7L9symaFXo="
17
17
  },
18
18
  {
19
19
  "question_id": "Q2-status-propagation-states",
20
20
  "resolved_model": "claude-opus-4-8",
21
- "prompt_sha256": "sha256-AY9HKlNQhdAw8Woxni4903GeG3GwItWaHLucloitZlQ=",
22
- "tool_schema_sha256": "sha256-Tuyydf1fteUasUVBy+VzlGijelrqPfvHjI7wHvE9Omk=",
21
+ "prompt_sha256": "sha256-rLMa1hQeYobjvEeCWjmhhwjx0ZV7A/JG4xN+Gn/Taus=",
22
+ "tool_schema_sha256": "sha256-rAn5uvRldR9ctw1Sb8ZkXIuVRzA8spJBRmFJqkAqUO0=",
23
23
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
24
24
  "params": {
25
25
  "effort": "high"
26
26
  },
27
- "output_sha256": "sha256-yU0hMIEGjOL7imQbLJWzXhJQze1onwHDVmPY0dKR8ow="
27
+ "output_sha256": "sha256-PY9+TX8amO4HEnSj2m5667eCPzSxQoJLLlRifWNjSAE="
28
28
  },
29
29
  {
30
30
  "question_id": "Q3-scholarly-retraction",
31
31
  "resolved_model": "claude-opus-4-8",
32
- "prompt_sha256": "sha256-TEeHZdUC26paRW9TSYHuiDx0Xn6olBysMIkPDDw4jXo=",
33
- "tool_schema_sha256": "sha256-Tuyydf1fteUasUVBy+VzlGijelrqPfvHjI7wHvE9Omk=",
32
+ "prompt_sha256": "sha256-edU5+lj80xAt/lICOwERznjxy7Xavrt4zkRbHAL4lL8=",
33
+ "tool_schema_sha256": "sha256-rAn5uvRldR9ctw1Sb8ZkXIuVRzA8spJBRmFJqkAqUO0=",
34
34
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
35
35
  "params": {
36
36
  "effort": "high"
37
37
  },
38
- "output_sha256": "sha256-gWAS2GsMJmkDgODKPL3tR0bX1qqc7pIh9MVevzVUkHQ="
38
+ "output_sha256": "sha256-ffW4pz8IyjoeRqgNHe6xTfnvo8zs9wKSCZJczG4qBTc="
39
39
  },
40
40
  {
41
41
  "question_id": "Q4-sound-compensators",
42
42
  "resolved_model": "claude-opus-4-8",
43
- "prompt_sha256": "sha256-aavKw3GRZWQPAQf3UbsptfbiOjQSLfqOoQJ9zqvQeJM=",
44
- "tool_schema_sha256": "sha256-Tuyydf1fteUasUVBy+VzlGijelrqPfvHjI7wHvE9Omk=",
43
+ "prompt_sha256": "sha256-f2549e25ZsyA+QgebqdIeNsh3a+u/iAer+t439zh+J4=",
44
+ "tool_schema_sha256": "sha256-rAn5uvRldR9ctw1Sb8ZkXIuVRzA8spJBRmFJqkAqUO0=",
45
45
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
46
46
  "params": {
47
47
  "effort": "high"
48
48
  },
49
- "output_sha256": "sha256-5ui1SfolNP+Dj4wqut/XysFeXlRD2wtlAd9cUzFgkSU="
49
+ "output_sha256": "sha256-e8mm2j3uOX0pUvdgMpck8OMqtvs+NG3FuVMn4LMQhDU="
50
50
  },
51
51
  {
52
52
  "question_id": "Q5-stale-tombstone-contrastive",
53
53
  "resolved_model": "claude-opus-4-8",
54
- "prompt_sha256": "sha256-4K8vxSk4rRNpH76T+dBc5pmMRqdP1nCPKahSB650cKc=",
55
- "tool_schema_sha256": "sha256-Tuyydf1fteUasUVBy+VzlGijelrqPfvHjI7wHvE9Omk=",
54
+ "prompt_sha256": "sha256-Ml4IoYnSajRyAjaWyjrA44kdzpmDGbrSFGAPOfYUPVo=",
55
+ "tool_schema_sha256": "sha256-rAn5uvRldR9ctw1Sb8ZkXIuVRzA8spJBRmFJqkAqUO0=",
56
56
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
57
57
  "params": {
58
58
  "effort": "high"
59
59
  },
60
- "output_sha256": "sha256-0UKzfcvegCvkXik9Dq/xSW2e2kDW1LNgKaOt+omoMq8="
60
+ "output_sha256": "sha256-wpEjen2OeX44jBIkf50iRfY4VLQMWCcJyoiyBYq33lI="
61
61
  }
62
62
  ],
63
63
  "verification": {
@@ -74,5 +74,5 @@
74
74
  "citations_sha256": "70a0d84650477090be49925bf4b53ab52b8fdb88ebf5d2487f3000ea96fc810a",
75
75
  "receipt_chain_sha256": "dcd57fc2ec8d66992e9762e1e551aee75829dda2bf9cc0837bc3106f48cece94"
76
76
  },
77
- "lock_sha256": "sha256-ux8eG1feaHkbKoSd4qxcoK/UE7jgXe1jd21LBfxviNc="
77
+ "lock_sha256": "sha256-mWahjOhCcfrb4j6SOluUivQyAW5XlK8eKZDBmAiyMPo="
78
78
  }
@@ -7,6 +7,7 @@ on:
7
7
  pull_request:
8
8
  paths:
9
9
  - '**/*.dispatch.md'
10
+ - '**/*.withdrawn.json'
10
11
  - '.github/workflows/dispatches.yml'
11
12
  workflow_dispatch:
12
13
 
@@ -25,7 +26,7 @@ jobs:
25
26
  node-version: '20'
26
27
  # Lint every dispatch under dispatches/ (a file, a dir, or '-' for stdin all work).
27
28
  # Exit 1 on any sourcing violation fails the check. Add --json for machine-readable output.
28
- - run: npx @dogfood-lab/study-swarm@latest lint dispatches/
29
+ - run: npx --yes @dogfood-lab/study-swarm@2.1.0 lint dispatches/
29
30
  # Halt the build while any finding that became canon is withdrawn and not yet removed or
30
31
  # re-grounded — the canon-rollback andon. Exit 1 on any unresolved evidence-withdrawn flag.
31
- - run: npx @dogfood-lab/study-swarm@latest requalify --check dispatches/
32
+ - run: npx --yes @dogfood-lab/study-swarm@2.1.0 requalify --check dispatches/
@@ -9,7 +9,7 @@
9
9
  > parallel retrieval-grounded research agents; every finding below was fetched this session, and the whole
10
10
  > set is gated through Step 4 (`roleos verify-citations` → prism, a different model family) **before** it
11
11
  > informs the architecture. The synthesizer is Claude/Opus; the groundedness lens is Mistral; the existence
12
- > oracle is deterministic retrieval — none of them Claude. Run `study-swarm lint study-swarm-lock.dispatch.md`
12
+ > oracle is deterministic retrieval — none of them Claude. Run `study-swarm lint examples/study-swarm-lock.dispatch.md`
13
13
  > (it passes).
14
14
 
15
15
  ## Step 1 — Load-bearing questions
@@ -93,15 +93,15 @@ Each choice traces to findings by number. The shape:
93
93
 
94
94
  ```json
95
95
  {
96
- "schema": "dispatch.lock/v1",
97
- "study_swarm_version": "1.2.0",
98
- "protocol_sha256": "<full sha256 of the vendored PROTOCOL.md>",
99
- "dispatch_sha256": "<sha256 of the dispatch .md bytes>",
96
+ "schema": "dispatch.lock/v2",
97
+ "study_swarm_version": "2.0.0",
98
+ "protocol_sha256": "sha256-<base64 of the tag study-swarm/v2/text plus a newline, then the text-normalized PROTOCOL.md>",
99
+ "dispatch_sha256": "sha256-<base64 of the tag study-swarm/v2/text, a newline, then the text-normalized dispatch>",
100
100
  "steps": [
101
101
  {
102
102
  "question_id": "Q1-replay-manifest",
103
103
  "resolved_model": "claude-opus-4-8",
104
- "prompt_sha256": "sha256-<base64>",
104
+ "prompt_sha256": "sha256-<base64 of the tag study-swarm/v2/text, a newline, then the text-normalized prompt>",
105
105
  "tool_schema_sha256": "sha256-<base64>",
106
106
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
107
107
  "params": { "effort": "high" },
@@ -114,24 +114,24 @@ Each choice traces to findings by number. The shape:
114
114
  "verifier_model": "mistral-small:24b",
115
115
  "verifier_family": "local",
116
116
  "receipt_id": "prism-...",
117
- "receipt_chain_sha256": "sha256-<base64>"
117
+ "receipt_chain_sha256": "<bare hex of the verifier receipt chain>"
118
118
  },
119
119
  "lock_sha256": "sha256-<base64>"
120
120
  }
121
121
  ```
122
122
 
123
- - **L1 — One lock per dispatch; the lock IS the dispatch's content-address.** `lock_sha256` binds every per-step record and the verifier block together, so a replay cannot stitch a step from one dispatch onto another. (findings 4, 13, 17, 18)
123
+ - **L1 — One lock per dispatch; the lock IS the dispatch's content-address.** `lock_sha256` binds every per-step record and the verifier block together, so a replay cannot stitch a step from one dispatch onto another — the per-step record carries exactly PROV's minimal lineage quadruple (input hashes, output hashes, actor, rollup link). (findings 4, 13, 17, 18, 25)
124
124
  - **L2 — The harness emits the record; the CLI canonicalizes + hashes + validates it.** This producer/verifier split is universal across the provenance literature, and it is what keeps the CLI zero-dependency, network-free, and deterministic — it never calls a model. (findings 17, 19, 21, 22)
125
- - **L3 — Hash the prompt as normalized text, not JCS-restructured JSON.** The prompt is the literal string the model conditioned on, so it is hashed directly rather than canonicalized as JSON (the JWS/DSSE hash-known-bytes rule) — under one necessary text normalization (BOM strip + CRLF→LF + NFC), without which the same prompt hashes differently across platforms. (findings 12, 23; 10, 11)
125
+ - **L3 — Hash the prompt as the domain tag plus normalized text.** The preimage is the tag `study-swarm/v2/text`, a newline, then the prompt after BOM strip, CRLF→LF, and NFC. Hashing the normalized prompt alone does not match `prompt_sha256`. The dispatch text and PROTOCOL.md use that same preimage. The prompt is not re-parsed as JSON. (findings 12, 23; 10, 11)
126
126
  - **L4 — Normalize every text input before hashing (BOM strip + CRLF→LF + NFC), and JCS-canonicalize the structured JSON (tool surface, lock body).** This is the only way the same dispatch hashes identically on Windows, macOS, and Linux — the prompt, the dispatch text, `PROTOCOL.md`, and every JSON string value all pass through it. (findings 9, 10, 11) *(CI caught a real CRLF drift here when an early build hashed raw `PROTOCOL.md` bytes — the fix is exactly this normalization, and a line-ending-invariance test now guards it.)*
127
- - **L5 — Capture the tool surface as the canonicalized array `{name, description, inputSchema, outputSchema}` plus the effective JSON Schema dialect.** Neither MCP nor the provider APIs ship a per-tool version or hash, so the lock's content hash is the missing drift detector, and the dialect is part of the contract. (findings 7, 33, 34, 35, 37)
127
+ - **L5 — Capture the tool surface as the canonicalized array `{name, description, inputSchema, outputSchema}` plus the effective JSON Schema dialect.** Neither MCP nor the provider APIs ship a per-tool version or hash, so the lock's content hash is the missing drift detector, and the dialect is part of the contract. The CLI requires `tool_schema` to be a JSON object and hashes its canonical form. It does not evaluate that object as a JSON Schema. (findings 7, 33, 34, 35, 36, 37)
128
128
  - **L6 — Pin the RESOLVED model id, never an alias.** A named model can be re-tuned server-side; the concrete platform identity is what makes a step replayable. (findings 19, 29)
129
129
  - **L7 — `output_sha256` records outputs for DRIFT DETECTION, not determinism.** Pinning model + prompt + temperature does not yield bit-identical outputs (batch-invariance, FP non-associativity, MoE routing, provider drift), so the honest claim is **"replayable inputs + drift-detectable outputs,"** never "deterministic replay." (findings 8, 19, 26, 27, 28, 30, 31, 32)
130
- - **L8 — `lock --verify` is fail-closed strict-match.** Re-derive every deterministic hash and assert equality; any mismatch — and any unrecognized field — exits non-zero, never auto-heals. (findings 5, 6, 20, 38)
130
+ - **L8 — `lock --verify` is fail-closed strict-match.** Re-derive every deterministic hash and assert equality; any mismatch — and any unrecognized field — exits non-zero, never auto-heals — the cache-invalidation rule that any change to a folded input re-executes rather than serving a stale hit. (findings 2, 5, 6, 20, 38)
131
131
  - **L9 — Self-describing digests + domain separation in the rollup, hashed as one flat canonical array.** Digests carry their algorithm prefix; the canonical JSON object's distinct keys and the array's explicit length supply domain separation and sidestep the odd-leaf-duplication collision class. (findings 14, 15, 24, 38)
132
132
  - **L10 — Pin the verifier receipt offline-verifiably.** Store `receipt_id` + `receipt_chain_sha256`; `lock --verify` confirms the verification happened without re-contacting the verifier. The Ed25519 receipt is a stable pin; the ephemeral key buys verifiability, not anti-forgery — stated, not oversold. (findings 16, 21, 22)
133
133
  - **L11 — Pin content, not mtimes.** The lock is robust to file-touch noise by construction. (findings 1, 3)
134
134
 
135
135
  **Optional actionable drift output (design note, not a numbered citation):** beyond a flipped SHA, `lock --verify` may classify *what* changed in the tool surface (added tool = additive, removed/renamed parameter = breaking), mirroring the breaking/non-breaking split that the [oasdiff](https://github.com/oasdiff/oasdiff) OpenAPI differ surfaces in CI. This is a usability layer over the authoritative hash check, not a substitute for it.
136
136
 
137
- **Net:** the lock turns a study-swarm dispatch into a content-addressed, byte-replayable manifest — resolved model + prompt + tool-schema + verifier receipt pinned per step, rolled into one `lock_sha256`, drift-checked fail-closed — while telling the truth about its ceiling: it makes inputs replayable and outputs drift-detectable, not LLM outputs deterministic.
137
+ **Net:** the lock turns a study-swarm dispatch into a content-addressed manifest — resolved model + prompt + tool-schema + verifier receipt pinned per step, rolled into one `lock_sha256`, drift-checked fail-closed — while telling the truth about its ceiling: it makes inputs replayable and outputs drift-detectable, not LLM outputs deterministic.
@@ -1,46 +1,46 @@
1
1
  {
2
- "schema": "dispatch.lock/v1",
3
- "study_swarm_version": "1.3.0",
4
- "protocol_sha256": "sha256-seELxwXtj+xVxa3mas2cP0J0iMTTpq4vHqFMiUGqmuU=",
5
- "dispatch_sha256": "sha256-mPdwnlPuRlCtky20zG6l5AFJ8iRAZjHISnoGDUuGSOo=",
2
+ "schema": "dispatch.lock/v2",
3
+ "study_swarm_version": "2.1.0",
4
+ "protocol_sha256": "sha256-p9LMoGfOGIASHIfFo6RkgpiCtnHlTtxcuPsTzQ+fuYY=",
5
+ "dispatch_sha256": "sha256-OLbenEn4TkhWu679FDvCw9940CkPeSRQol88sAVIB68=",
6
6
  "steps": [
7
7
  {
8
8
  "question_id": "Q1-replay-manifest",
9
9
  "resolved_model": "claude-opus-4-8",
10
- "prompt_sha256": "sha256-hcdcTxvqJNij0z9ItUPIzQhBWbrVZy3VvY4umPHaM5I=",
11
- "tool_schema_sha256": "sha256-kUC7s+wAFV4lzwrFKYp36khxCRQZWlWeFDOwhPIqGCk=",
10
+ "prompt_sha256": "sha256-S/YE49Ry8VUND0oyNE2ls9NQ8prCfASakEn4VPAE/Yc=",
11
+ "tool_schema_sha256": "sha256-x6ygSP9mm+7sp06lFaxpe5W3RsNc0h57hz6aHoXPYXo=",
12
12
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
13
13
  "output_sha256": "sha256-k5rkOOyAHGBCVacEk8LPULp+s5YHVzaUyCHJY4tD5jE="
14
14
  },
15
15
  {
16
16
  "question_id": "Q2-canonicalization",
17
17
  "resolved_model": "claude-opus-4-8",
18
- "prompt_sha256": "sha256-Gj+ri3gWVWxP7M9fv50c0xsgiZ2j3T6kn3A3c3EhSos=",
19
- "tool_schema_sha256": "sha256-kUC7s+wAFV4lzwrFKYp36khxCRQZWlWeFDOwhPIqGCk=",
18
+ "prompt_sha256": "sha256-9ZbmzzaBscf6H4AUj/BRIA8UjG65KtFuMHdkqjucjhA=",
19
+ "tool_schema_sha256": "sha256-x6ygSP9mm+7sp06lFaxpe5W3RsNc0h57hz6aHoXPYXo=",
20
20
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
21
21
  "output_sha256": "sha256-ymPE5lJqoygN0MpzqftgE1tYlyp7z+poCK2Z1Zj3mi8="
22
22
  },
23
23
  {
24
24
  "question_id": "Q3-provenance-attestation",
25
25
  "resolved_model": "claude-opus-4-8",
26
- "prompt_sha256": "sha256-g5/dW+zJvMObKyqnAdy70pUPtJcGD0DrsjkeEx/AcIY=",
27
- "tool_schema_sha256": "sha256-kUC7s+wAFV4lzwrFKYp36khxCRQZWlWeFDOwhPIqGCk=",
26
+ "prompt_sha256": "sha256-yUGaXe7X4bRhFHSKtDjxHh3xuPtg1+BmLV6jza4C0fo=",
27
+ "tool_schema_sha256": "sha256-x6ygSP9mm+7sp06lFaxpe5W3RsNc0h57hz6aHoXPYXo=",
28
28
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
29
29
  "output_sha256": "sha256-OSUAIhytytKihfFM1Y+p1BllUSTC+KEfb/NX86X+Kc0="
30
30
  },
31
31
  {
32
32
  "question_id": "Q4-llm-determinism",
33
33
  "resolved_model": "claude-opus-4-8",
34
- "prompt_sha256": "sha256-OfQ00IyAulvEOnZ/UpiLp+JTwF4jYUzQRaqCp3zgIbE=",
35
- "tool_schema_sha256": "sha256-kUC7s+wAFV4lzwrFKYp36khxCRQZWlWeFDOwhPIqGCk=",
34
+ "prompt_sha256": "sha256-Pq1qlM2d+twv0Bpj9oKai/wqDgprgbgrX82++lwL01A=",
35
+ "tool_schema_sha256": "sha256-x6ygSP9mm+7sp06lFaxpe5W3RsNc0h57hz6aHoXPYXo=",
36
36
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
37
37
  "output_sha256": "sha256-aFDm9p4/94p97NJg/vWKbYXchv6N1b0swpIfYoep1iw="
38
38
  },
39
39
  {
40
40
  "question_id": "Q5-tool-schema-drift",
41
41
  "resolved_model": "claude-opus-4-8",
42
- "prompt_sha256": "sha256-qIr9Dl8GmGeikUrgCJ62QQh8FvTNUhvdxL0Ivk/Di3M=",
43
- "tool_schema_sha256": "sha256-kUC7s+wAFV4lzwrFKYp36khxCRQZWlWeFDOwhPIqGCk=",
42
+ "prompt_sha256": "sha256-M/W3TeerL+sC7rgduBkXme0awKZIGWc12h82tMe22UM=",
43
+ "tool_schema_sha256": "sha256-x6ygSP9mm+7sp06lFaxpe5W3RsNc0h57hz6aHoXPYXo=",
44
44
  "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
45
45
  "output_sha256": "sha256-Y1lsUdKoplgdos0r4faN6UgxXX74D/Se0AVHCiUA9dM="
46
46
  }
@@ -58,5 +58,5 @@
58
58
  "receipt_signature": "272c892124e3bc13a76b2674fa361b1d65aee6a588c74604cf4ae4e7c9440a8ba7888175b9ec1286fe87490121f694f64cd30adc3ffc0e1b31cd3365b7b38901",
59
59
  "receipt_chain_sha256": "499b63905064a5e25fd1801c5530504c94742f2183c4d3c8eb545a20cfbb112e"
60
60
  },
61
- "lock_sha256": "sha256-AOzuFtiRt4iXnsVqEvcB5hms1oO1LcjRrin96aQnUHE="
61
+ "lock_sha256": "sha256-njv3Da3GHKQqkMfj12S1Dh7+OBRtapWs1n9Nv7rWyPI="
62
62
  }
@@ -7,7 +7,7 @@
7
7
  > Every citation below was gated through Step 4 (retrieval oracle for existence + two different-family
8
8
  > groundedness lenses, reasoning-stripped) **before** it informed the architecture. The synthesizer is
9
9
  > Claude/Opus; the verifier families are Mistral + IBM Granite + the deterministic arXiv oracle — none of
10
- > them Claude. Run `study-swarm lint study-swarm-v1_1.dispatch.md` (it passes).
10
+ > them Claude. Run `study-swarm lint examples/study-swarm-v1_1.dispatch.md` (it passes).
11
11
 
12
12
  ## Step 1 — Load-bearing questions
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogfood-lab/study-swarm",
3
- "version": "1.3.0",
3
+ "version": "2.1.0",
4
4
  "description": "Ground design decisions in cited research, then verify every citation with a different model family before it becomes canon — a research-grounded design protocol, with a thin CLI.",
5
5
  "keywords": [
6
6
  "methodology",