Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions lib/skills/__tests__/rule-selector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ describe("rule selector slot", () => {
expect(body).toMatch(edge("make_recorded_move", "assemble_draft"));
expect(body).toContain("run_budget {runDb, key: verdict-rounds:<depth>, limit: 2, stage}");
});
test("self-review's diff takes in untracked files without staging them", () => {
const body = compiled.verbs["self-review"];
expect(body).toMatch(/`git ls-files -z --others\s+--exclude-standard`/);
expect(body).toMatch(/`git diff --no-index\s+-- \/dev\/null <path>`/);
expect(body).toContain("never `git add` or `git add -N` to make a new file show up");
expect(body).toContain("`self-review.diff`");
expect(body).toContain("## The diff to review");
});

test("receive-review: every edge into the adjudicator passes select_rules", () => {
const into = [...compiled.verbs["receive-review"].matchAll(/^\s*(\w+) -> dispatch_adjudicator\b/gm)].map((m) => m[1]);
expect(into).toEqual(["select_rules"]);
Expand Down
2 changes: 1 addition & 1 deletion plugins/mattstack/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mattstack",
"version": "0.32.30",
"version": "0.32.31",
"description": "The mattstack skills pack: public doors subagent-review-loop, model-tiering, editing-skills, creating-a-pack, extending-a-pack, getting-current-time, process-digraphs, work-progress, wrap-up, the pack's own compiled shepherdr verb (domain-unbound), and the three writing-style presets (sparse, conversational, structured), plus the compile-native engines (work orchestrator, pipeline stages, review verbs, forge adapters, shepherdr) and attachments (execution strategies, account pool, review include bodies, review-posting, parameterized-skill primitive) that rt skills compile inlines into team verbs at compile time -- reached by name, not by slash menu. Also ships an mcp tools reference read by path, not inlined.",
"author": {
"name": "Matthew Goodwin"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ props:
The domain's own review pass, as it words it. When that pass asks the
human about its findings at a gate of its own (a self-review whose gate
offers Ship as is), the answer stands: the findings it leaves open go
into `review` by name, and this stage never fixes them. A Hold there
into `review` by name, and this stage never fixes them. When the review's
Assessment carries an `Unanswered rules:` line, that line goes into
`review` as written whenever this stage writes `review`. A Hold there
holds this stage too; an Abandon has already failed it, so nothing more is
written. The fix rounds (Review rounds = 3? and Fix each blocking finding test-first, commit) run only when no such gate ran.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ flowchart TB
domain_review_gated{How did the domain review's own gate end?}
git_log_shas[/git log --format=%h <branch-point>..HEAD/]
run_field_set_commits[/"run_field_set {key: commits, value: <all shas, fixes included>, stage: self-review}"/]
run_field_set_review[/"run_field_set {key: review, value: <verdict; findings fixed, waived, or left open by name>, stage: self-review}"/]
run_field_set_review[/"run_field_set {key: review, value: <verdict; findings fixed, waived, or left open by name; the review's Unanswered rules line, when it wrote one>, stage: self-review}"/]
run_stage_fail[/"run_stage {action: fail, stage: self-review, reason: blocking findings after 3 rounds}"/]
stage_failed(((Stage failed)))
held_domain_gate(((Held at the domain review's gate)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ it the full payload:
- a one-or-two-sentence description of the change
- the requirements
- the commit range
- the diff file, when the caller wrote one because the change reaches
past HEAD
- the setup observations from Set up for the depth
- the filled criteria addendum, when the pack binds criteria
- the rule selection text and the verdict request naming the `fence`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ order: 1

- The diff source, already confirmed to resolve. With no named base: the
branch point (`git merge-base origin/HEAD HEAD`, falling back to the
default branch by name), plus uncommitted changes for own-branch flows.
default branch by name), plus uncommitted changes and untracked files
for own-branch flows.
- The requirements, from the ticket or task description.
- A human-readable label for the change.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ order: 2
- the requirements or acceptance criteria the change is judged against
- optional: an already-filled domain addendum block
- optional: setup observations already gathered (commands run, values seen)
- optional, reviewer only: a diff file, when the change reaches past the
commit range (uncommitted changes or untracked files)
- optional: the rule selection text, plus a verdict request naming the
`fence` value when the caller asks for one (an adjudicator never does)
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ Append to every dispatched prompt, in this order, after its filled template:

1. Setup observations: `## Already checked before dispatch (fold in; do not
redo)`, followed by the caller's observations, or `none`.
2. The caller's addendum block, verbatim when provided, except that each
2. The diff file, only when the caller hands one: `## The diff to review`,
the file's absolute path, and this sentence: "Review this file: it holds
every change, including ones past HEAD that the commit range above does
not cover. Where the two differ, the file wins." With no diff file this
block is left out.
3. The caller's addendum block, verbatim when provided, except that each
`@key` in it goes as the absolute path `skills_resolve` returned for it.
3. The rule selection, only when the caller hands one: `## Rules this
4. The rule selection, only when the caller hands one: `## Rules this
change triggers`, the selection text verbatim, then, when the caller
asks for one, the verdict request. The request says: end the reply with
the verdict set in one fenced block tagged with the `fence` value, in
Expand All @@ -19,7 +24,7 @@ Append to every dispatched prompt, in this order, after its filled template:
"old"}], "note"}]}`, with one verdict for every rule id in the
selection (the `id` of each entry in `selection.json`'s `rules[]`).
With no selection text this block is left out.
4. No fabrication: do not invent requirements, files, or findings; if the
5. No fabrication: do not invent requirements, files, or findings; if the
diff, the requirements, or a referenced file cannot be read, say so for
that item and stop rather than guessing.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ node: dispatch_reviewer

# Dispatch the fresh reviewer on your own diff

The review flow's Dispatch the review, on the merge-base diff as it stands
The review flow's Dispatch the review, on the self-review diff as it stands
now, with the requirements and a label (the branch or task name). One
dispatch, never skipped, however small the change.

The commit range (merge base to HEAD) covers commits only. When the tree
has uncommitted changes or untracked files, write the self-review diff to
`self-review.diff` in the review scratch dir (one new directory in this
session's scratchpad, made here when none exists yet) and hand it to the
dispatch as the diff file (Review dispatch's Standard blocks), so the
reviewer judges that file, not the range.
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,15 @@ node: find_merge_base
# Find the self-review merge-base

`git merge-base origin/HEAD HEAD`, or the default branch by name when
`origin/HEAD` is unset. The diff runs from that base through the working
tree, uncommitted changes included.
`origin/HEAD` is unset. **The self-review diff** runs from that base
through the working tree, uncommitted changes and untracked files
included, built read-only:

1. `git diff <merge base>`: the commits and the uncommitted changes.
2. Then read the NUL-separated paths `git ls-files -z --others
--exclude-standard` prints, and for each one append `git diff --no-index
-- /dev/null <path>`. It exits 1 when it prints a diff; that is not a
failure.

Ignored files stay out. Nothing is staged and no file changes:
never `git add` or `git add -N` to make a new file show up.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ node: select_rules
# Select the rules for the change

Rule selector's Select the rules, run once the depth checks are done. The
diff it gets is the diff the reviewer judges: the working-tree diff from
the merge base, uncommitted changes included (`git diff <merge base>`, the
same diff `find_merge_base` and `dispatch_reviewer` describe), so the rules
match what the reviewer sees. With no selector bound, or `selector: none`,
skip it and go on to the repro check.
diff it gets on stdin is the self-review diff (Find the self-review
merge-base), untracked files included, built afresh from the tree as it
stands on every pass (an iteration that skips Find the self-review
merge-base reuses its base, never an earlier diff), so the rules match
what the reviewer judges. With no selector bound, or `selector: none`, skip it and
go on to the repro check.
Loading
Loading