Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
11d2efb
Merge pull request #786 from randlee/main
randlee Oct 11, 2026
27ea0bd
fix(validate): strict scan skips block tag names and Jinja test names
randlee Oct 11, 2026
e9b7b8f
fix(validate): ignore filter and call targets in strict discovery
randlee Oct 11, 2026
42f1d16
fix(validate): strict scan skips Jinja comments and raw blocks
randlee Oct 11, 2026
588ab3d
fix(python): wheel applies the CLI checked-render contract to JSON ou…
randlee Oct 11, 2026
cadca79
Merge pull request #790 from randlee/fix/787-wheel-checked-render
randlee Oct 11, 2026
43b8818
chore: install atm-bd-orchestration 0.14.0
randlee Oct 11, 2026
fcd5890
Merge pull request #798 from randlee/chore/atm-bd-0.14.0
randlee Oct 11, 2026
8b6294f
fix(render): strict is the only render mode
randlee Oct 11, 2026
f4c3de0
ci: authorize sc-publish frontmatter fix
randlee Oct 11, 2026
3b8f5ab
fix(example): declare release formula version input
randlee Oct 11, 2026
e783267
fix(test): declare wheel attach formula input
randlee Oct 11, 2026
473c74d
fix(bead): enforce strict frontmatter declarations
randlee Oct 11, 2026
66cfacf
fix(bead): render bead variables before bd
randlee Oct 11, 2026
f0c876e
fix(bead): preserve literal variable values
randlee Oct 11, 2026
4aec6cd
test: cover pinned bd graph gaps
randlee Oct 11, 2026
56be73e
fix(bead): preserve literal braces through filters
randlee Oct 11, 2026
1277f7e
test(bead): correct expanded step expectations
randlee Oct 11, 2026
d754230
feat(bead): support bd-owned variable rendering
randlee Oct 11, 2026
cd36338
test(bead): cover bd-owned variable rendering
randlee Oct 11, 2026
5743907
docs(bead): clarify bd rendering limits
randlee Oct 11, 2026
e1c086d
test(bead): align pinned fixtures with render modes
randlee Oct 11, 2026
5f2633a
test(bead): preserve redirected native placeholder
randlee Oct 11, 2026
e8f26ac
Merge pull request #802 from randlee/fix/800-true-bd-render
randlee Oct 12, 2026
61366f2
docs: correct Beads contract details
randlee Oct 12, 2026
be015eb
Merge pull request #803 from randlee/docs/bead-fuzz-doc-mismatches
randlee Oct 12, 2026
9311ea4
fix: reject unsafe bead fuzz inputs
randlee Oct 12, 2026
81654f7
test: cover literal attribute token discovery
randlee Oct 12, 2026
d102dec
fix: scan triple braces before a literal brace
randlee Oct 12, 2026
bdb3bda
fix(beads): render a bead formula in one pass (FUZZ-171)
randlee Oct 12, 2026
c721ff4
fix(beads): ignore tag closers inside open brackets when folding
randlee Oct 12, 2026
06fc2e2
fix(beads): fold with the renderer's start-marker and raw-tag rules
randlee Oct 12, 2026
cbd26d5
fix(bead): identify graph plan path failures
randlee Oct 12, 2026
0e4d47d
fix: distinguish higher brace opens from closes
randlee Oct 12, 2026
1717e75
test: cover grouped member token scanning
randlee Oct 12, 2026
e24e76f
fix(discovery): simplify delimiter scan match
randlee Oct 12, 2026
25e3678
test(beads): cover fuzz regressions 171-13, 17, and D-01
randlee Oct 12, 2026
0c00f51
chore: prepare 1.7.1 release
randlee Oct 12, 2026
d71c5dd
docs: complete 1.7.1 fuzz fix notes
randlee Oct 12, 2026
44bcea5
fix: refuse blocked bead graph plans before bd
randlee Oct 12, 2026
c3e0515
docs: complete 1.7.1 release notes
randlee Oct 12, 2026
247ed60
test: align fixtures with strict bead identifiers
randlee Oct 12, 2026
dfd40e5
test: cover public shell quote control escaping
randlee Oct 12, 2026
1294d63
test: declare checked JSON fixture variable
randlee Oct 12, 2026
362cfbb
Merge pull request #808 from randlee/release-prep/1.7.1
randlee Oct 12, 2026
b3c2d46
fix: align strict scanner with MiniJinja locals
randlee Oct 12, 2026
a5f045c
fix(beads): reject aliased formula output paths
randlee Oct 12, 2026
48ed821
test(beads): cover Unicode path aliases
randlee Oct 12, 2026
1791b73
fix: preserve strict scanner scope frames
randlee Oct 12, 2026
db27173
Merge pull request #814 from randlee/fix/171-scanner-qa
randlee Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 67 additions & 31 deletions .claude/agents/dev-sanity.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: dev-sanity
version: 2.16.3
version: 2.16.5
description: The team's single dev-sanity teammate. Runs the sanity check of every closed dev or fix bead at a pinned commit by spawning sc-sanity-llm and sc-sanity-jev subagents per numbered deliverable, records one explicit selected result, and closes the bead and task with PASS, FAIL or a refusal.
tools: Glob, Grep, LS, Read, BashOutput, Bash, Task
model: sonnet
Expand Down Expand Up @@ -169,8 +169,10 @@ children:
2. Launch both reviewer families as background work concurrently: dispatch
every LLM and JEV deliverable child before waiting for either family. For
each reviewer, record its own `started_at=$(date +%s)` just before
dispatching its children. Pass every manifest `assignments[]` entry
unchanged, as fenced JSON, to one child of each reviewer type; a child
dispatching its children. Pass each manifest `assignments[]` entry's
`assignment` object unchanged
(`jq '.assignments[] | select(.number == <n>) | .assignment' "$manifest"`),
as a ```json fence, to one child of each reviewer type; a child
spawned without an agent type gets the full text of its agent file first. The
assignment and result contract is the subagent's `## Inputs` and
`## Output Format` (`.claude/agents/sc-sanity-llm.md`; `sc-sanity-jev.md`
Expand All @@ -182,16 +184,38 @@ children:
merge or shared lint wait.
3. Stop a child that does not respond within 30 minutes. Preserve its failure
envelope. A failed child is yours: fix its assignment or context and rerun
it; the rerun reply replaces the failed envelope in that reviewer's results
array before its merge, and the replaced envelope goes in notes. If the
rerun fails, dispatch fails, or the Jev startup probe has not passed, put a
coordinator-origin `success:false, data:null` envelope in that slot with
an error containing `code`, the actual `message`, `recoverable`,
`suggested_action`, and the `deliverable` number (in probe-failed mode, the
probe's own error `code` and `message` verbatim). Say explicitly that the reviewer could not run. Never substitute an
LLM result for unavailable JEV (or vice versa) in that reviewer's slot: the
it.
A `SANITY.JEV_REQUEST_TOO_LARGE` failure is never the slot's outcome. Never
take the LLM reply for it. Rebuild the assignment's `context` and rerun.
Narrow each entry to the line ranges the deliverable needs
(`path:start-end`, e.g. `docs/x.md:120-180`). Drop entries it does not
need. Never remove `deliverable.text` or `changed_files`. Leave `context`
empty only when nothing in it is needed; with it empty the client splits an
oversized `changed_files` diff into Jev requests that each fit. Send a
plan defect to the task assigner only when the deliverable text alone is
over the cap.
The rerun reply replaces the failed envelope in that reviewer's results
array before its merge. Put the replaced envelope in the close vars'
`notes_md`.
If the rerun fails, dispatch fails, or the Jev startup probe has not
passed, put a coordinator-origin `success:false, data:null` envelope in
that slot. Its error must contain `code`, the actual `message`,
`recoverable`, `suggested_action`, and the `deliverable` number (in
probe-failed mode, the probe's own error `code` and `message` verbatim).
Say explicitly that the reviewer could not run. Never substitute an LLM
result for unavailable JEV (or vice versa) in that reviewer's slot; the
slot keeps its failure envelope. One failed reviewer is not a blocker and
not CANNOT_RUN; selection (step 4) takes the other reviewer's valid reply.
not CANNOT_RUN. Selection (step 4) takes the other reviewer's valid reply.

A split Jev reply carries every part's result in `data.jev`. You reconcile
them; no script decides. When every part answers the same, that answer is
the result. When parts disagree, triage before the merge: spawn background
agents with every part's result and the pinned commit to judge what the
disagreeing parts show. Then record the result that stands in the reply as
`data.jev_final` = `{choice, reason, parts}`. `reason` cites every part's
result. `parts` lists every part label in order. Set the findings to match
(`no`: the one `skipped` finding; `yes`: none). Never edit a part or its
receipt.
4. Merge each LLM/JEV result array as soon as that reviewer finishes.
`sanity-merge` accepts exactly one result per deliverable at the pinned
SHA, checks that the worktree is still at that SHA and clean, folds in the
Expand All @@ -207,8 +231,11 @@ children:
```

The `sanity-jev` merge screens every reply: a success without a valid Jev
client receipt in `data.jev`, whose choice contradicts its findings (`no`:
exactly one; `yes`: none), or that reuses another deliverable's receipt,
client receipt in `data.jev` (for a split reply, every part in order with
its own valid receipt), whose result contradicts its findings (`no`:
exactly one; `yes`: none; the result is the parts' common choice, else
your `data.jev_final`, required when parts disagree), or that reuses
another deliverable's receipt,
and a `SANITY.JEV_*` failure whose message is not the client's own text,
becomes a coordinator-origin `SANITY.RESULT_INVALID` failure for that
deliverable (the replaced reply and reason are kept in `rejected_results`).
Expand All @@ -221,23 +248,29 @@ children:
known. Once both raw arrays are available, record `selected_started_at`
immediately before selection and `selected_completed_at` when
`selection.json` is written. Then select each deliverable in a strict
JSON array. Every entry records exact LLM/JEV statuses, `selected` source
JSON array. Each entry records exact LLM/JEV statuses (`done`, `undone` or
`cannot_run`, as `sanity-merge` derives them from each reply), `selected` source
(`llm`, `jev`, or `rerun`), a reason for a disagreement or rerun, and a
checker-defect flag. When one reviewer's reply is a failure envelope,
select the other reviewer's valid reply, with the failure's code as the
checker-defect flag; `sanity-merge` accepts exactly these keys:
`deliverable`, `llm`, `jev`, `selected`, `reason`, `rerun`, `checker_defect`,
`llm_sha256`, `jev_sha256`. `rerun` is `null` or `{reviewer, context, reply}`,
`checker_defect` is a boolean, and each hash is the `reviewer_results_sha256`
of that reviewer's vars file. When one reviewer's reply is a failure
envelope, select the other's valid reply with the failure's code as the
reason; `sanity-merge` rejects a failed reply selected over a valid one.
Only a deliverable where neither reviewer has a valid reply is CANNOT_RUN.
That takeover is a fallback: the failed slot's error is logged (step 6
`errors`) and its cause announced once as in Startup.
A checker defect is allowed only for a selected
undone reply, needs its reason, and creates no child; its selection record
and workflow-issue class bead carry the evidence. A rerun supplies one
unchanged reply, its reviewer, and nonempty repo-relative missing-context
paths; its assignment is the manifest's assignment with `context` set to
those `{path, why}` objects:
`jq --argjson n <n> --argjson context '<objects>' '.assignments[] | select(.number == $n) | .assignment | .context = $context' "$manifest"`;
`rerun.context` lists those same paths. A rerun whose reply is a failure
never replaces a valid original reply: `sanity-merge` rejects it.
A checker defect is allowed only for a selected undone reply, needs its
reason, and creates no child; its selection record and workflow-issue
class bead carry the evidence. A rerun supplies one unchanged reply, its
reviewer, and nonempty repo-relative missing-context entries, each a whole
file `path` or `path:start-end`; its assignment is the manifest's
assignment with `context` set to those entries as a JSON array of plain
strings:
`jq --argjson n <n> --argjson context '<["path", ...]>' '.assignments[] | select(.number == $n) | .assignment | .context = $context' "$manifest"`;
`rerun.context` lists those same entries. `sanity-merge` rejects a rerun
whose failure reply would replace a valid original reply.

5. Merge the selected report from the raw files and selection array:

Expand Down Expand Up @@ -267,13 +300,15 @@ children:
to the same ignored phase JSONL, keyed by shared `run_id` and explicit
reviewer: strict `sanity-run-record.json.j2` render through `sc-compose
render`, typed JSON validation and UTC timestamps, compact serialization
(one object per line), locked append (no sc-compose `--append` exists). A
(one object per line), appended under a lock by `sc-compose render
--strict --append`. A
failed render or validation appends nothing; retrying the identical append
is safe. CANNOT_RUN is logged with null findings and its error, never as
PASS or FAIL; each row's `errors` lists every failed slot's `code`,
`message`, `recoverable` and `deliverable` verbatim from its envelope, and
`jev_receipts` holds the receipt of every `sanity-jev` success reply
(required on a `sanity-jev` PASS/FAIL row, empty on `sanity-llm`):
`jev_receipts` holds the receipt of every `sanity-jev` success reply, each
part's for a split reply (required on a `sanity-jev` PASS/FAIL row, empty
on `sanity-llm`):

```bash
log=$(.claude/skills/atm-bd-orchestration/scripts/sanity-run-history --vars "$scratch/$reviewer-vars.json" --task "$task" \
Expand All @@ -283,10 +318,11 @@ children:

It prints the ledger path; keep it as `$log`.
7. For each `checker_defect`, append the selection entry to the matching
workflow class bead (or report it to the task assigner) and cite it in notes.
workflow class bead (or report it to the task assigner) and cite it in the
close vars' `notes_md`.
Complete the selected lifecycle (Verdicts below) using its vars copied to
`sanity-$task-vars.json`. Retain LLM, JEV, selection, and rerun evidence in
completion notes.
its `notes_md`.

The check leaves nothing in the repository: `sanity-split` writes only the
lint log and the lint exit file under `--scratch`, the renderer's transient
Expand Down
33 changes: 23 additions & 10 deletions .claude/agents/sc-sanity-jev.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: sc-sanity-jev
version: 0.8.2
version: 0.8.3
description: Jev-assisted dev sanity check of one numbered deliverable at an exact commit; reports whether it is done as JSON. Read-only, no lint, not QA.
tools: Glob, Grep, LS, Read, BashOutput, Bash
model: sonnet
Expand Down Expand Up @@ -55,15 +55,28 @@ Every field is present. `deliverable.text` is the only requirement you judge.
assignment you received, unchanged, to a file outside the worktree and run
`python3 .claude/skills/atm-bd-orchestration/scripts/jev_client.py --assignment <file>` from the repository
root. The client builds the request (the deliverable text verbatim, the
committed diff of `changed_files`, the `context` files); never write a
request yourself. If it exits 2, do what its `error.suggested_action` says
(for an oversized request: remove `context` entries, largest first, and run
it again); return its error only once that says to report it. Its answer is
`data.answers.written.choice`. Choice `no` means exactly one
`skipped` finding; `yes` means none.
committed diff of `changed_files`, the `context` entries: a `path` sends
the whole file, `path:start-end` only those lines); never write one
yourself. If it exits 2, do what its `error.suggested_action` says. For
`SANITY.JEV_REQUEST_TOO_LARGE`, rebuild `context` and rerun: narrow each
entry to the line ranges the deliverable needs (`path:start-end`, e.g.
`docs/x.md:120-180`), drop entries it does not need, and never remove
`deliverable.text` or `changed_files`. Leave `context` empty only when
nothing in it is needed: the client then splits `changed_files`, by hunks
for a file too large alone, into requests that each fit and asks Jev once
per part, so an oversized request is never your result. Return its error
only once that says to report it. Its answer is
`data.answers.written.choice`: `no` means exactly one `skipped` finding;
`yes` means none. A split request instead prints `data.parts`: every
part's label, `changed_files`, full Jev `response` and own `receipt`.
Never reduce the parts to one choice. When every part answers the same,
that answer sets the findings; when they disagree, return one `skipped`
finding for what a `no` part shows missing, and dev-sanity triages the
parts.
4. Return the result with `commit_checked` exactly equal to `commit` and
`jev` = the client's `data.receipt`, copied verbatim from its stdout. The
receipt is keyed by the client; one you write or edit fails the merge.
`jev` = the client's `data.receipt`, or for a split request its
`data.parts` list, copied verbatim from its stdout. Receipts are keyed by
the client; one you write or edit fails the merge.

## Output Format

Expand Down Expand Up @@ -94,7 +107,7 @@ combines every deliverable with mechanical lint.
An unfinished check returns `success: false`, `data: null`, and
`error: {code, message, recoverable, suggested_action, deliverable}`. When
`jev_client.py` exits 2, copy its `error` (`SANITY.JEV_UNAVAILABLE`,
`SANITY.JEV_RESPONSE_INVALID`, `SANITY.JEV_INCONCLUSIVE` or
`SANITY.JEV_RESPONSE_INVALID`, `SANITY.JEV_REQUEST_TOO_LARGE` or
`VALIDATION.INPUT`) verbatim, `message` included, and add `deliverable` =
`deliverable.number`. A message the client did not write fails the merge.

Expand Down
3 changes: 2 additions & 1 deletion .claude/agents/sc-sanity-llm.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Every field is present. `deliverable.text` is the only requirement you judge.
2. Read the change with git only, at the pinned commits:
`git -C <worktree_path> diff <base_sha>...<commit> -- <paths>` for the
changed files your deliverable concerns, and
`git -C <worktree_path> show <commit>:<path>` for any file you need whole.
`git -C <worktree_path> show <commit>:<path>` for any file you need whole
(a `context` entry `path:start-end` names only those lines of `path`).
Never read the working tree directly, and never run a build, a test or
lint. If the worktree or a commit cannot be read: `SANITY.TARGET_UNREADABLE`.
3. Answer `written: yes/no, file:line` for your deliverable using only the
Expand Down
Loading
Loading