Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5aadc9f
[WIP] Tri-state verification outcomes: PASS/FAIL/UNEVALUATED (Refs #3…
valorengels Sep 3, 2026
fdb91bf
[WIP] session-ensure: primary-key readback + candidate provenance gat…
valorengels Sep 3, 2026
235da8e
[WIP] Migrate + extend verification parser tests to the tri-state (Re…
valorengels Sep 3, 2026
35925b4
Converge both verification runners on one bound and one disposition (…
valorengels Sep 3, 2026
13b69ad
Anchor only the newly added expectation forms (Refs #3065)
valorengels Sep 3, 2026
c0416aa
test: session-ensure readback identity and lock-release provenance (R…
valorengels Sep 3, 2026
9c44266
[WIP] Merge predicate reads recorded verification outcomes (Refs #3065)
valorengels Sep 3, 2026
8cd3aba
Merge predicate refuses on a FAIL/UNEVALUATED verification row (Refs …
valorengels Sep 3, 2026
1ed7c23
fix(sdlc-router): route on read facts — decision evidence, G3's docs …
valorengels Sep 3, 2026
035119e
Resolve branch truth once, three-valued, for both router callers (Ref…
valorengels Sep 3, 2026
bdf72b7
Make a wrong recorded lane slug repairable, on unique evidence only (…
valorengels Sep 3, 2026
43f48a6
Repair a proven-wrong lane slug at the fail-closed decision point (Re…
valorengels Sep 3, 2026
15d9b57
Test the slug-repair trigger at the G8 decision point (Refs #3065)
valorengels Sep 3, 2026
27f5a18
Docs: a wrong recorded lane slug is repairable on unique evidence (Re…
valorengels Sep 3, 2026
4f00517
Documentation cascade for the read-facts router and tri-state grading…
valorengels Sep 4, 2026
2f09345
Record the merge gate's new fail-closed read in the SDLC principle (R…
valorengels Sep 4, 2026
2ed0f61
Give the merge gate a writer, and stop rejecting indexed check tables…
valorengels Sep 4, 2026
76e8d30
Arm the merge gate safely: strict argv, fail-closed read, router-side…
valorengels Sep 4, 2026
a9d411b
Make the gate reachable, and stop it refusing lanes that declared no …
valorengels Sep 4, 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
36 changes: 34 additions & 2 deletions .claude/skills-global/do-plan/PLAN_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,12 @@ Each row is a named check with an executable command and expected result.

**Positive expectations** (the command must succeed or produce the expected output):
- `exit code N` — passes when exit_code == N (positive exact-match; e.g. `exit code 0` for success, `exit code 1` for "grep found no matches")
- `output > N` — passes when stdout (as integer) is greater than N
- `exit N` — the same assertion, shorter spelling
- `output > N` / `> N` — passes when stdout (stripped, as an integer) is greater than N
- `output >= N` / `>= N` — passes when stdout is numeric and >= N
- `output == N` / `== N` — passes when stdout is numeric and exactly N
- `` prints `N` `` — passes when stripped stdout equals N exactly (backticks optional)
- `empty output` — passes when stdout is empty or whitespace-only
- `output contains X` — passes when substring X appears in stdout

**Inverse expectations / anti-criteria** (the command must NOT produce a forbidden result):
Expand All @@ -458,6 +463,33 @@ Each row is a named check with an executable command and expected result.
disjoint and unambiguous. The existing `exit code 1` sample row ("No stale xfails") is
a positive exact-match — it stays as-is.

**Every row grades three-valued: `PASS`, `FAIL`, or `UNEVALUATED`.** There is no
pass/fail boolean. `UNEVALUATED` means the grader could not answer the question —
an expectation form not in the list above, an empty `Expected` cell, a `Command`
cell with no backticked span, a timeout, or a runner exception. It blocks exactly
like `FAIL` but is reported as its own token, because it is a finding about the
*row you wrote*, not about the code. If a row comes back `UNEVALUATED`, fix the
row. Note that the three older forms (`exit code N`, `output > N`,
`output contains X`) tolerate a trailing gloss, while every newer form is anchored:
`>= 1 (one call site today)` grades `UNEVALUATED`, not `>= 1`.

**Pipes must be escaped, and the escape composes.** A `|` is the table's own column
separator, so a command containing one is written `\|`; a bare `|` is rejected as a
plan-authoring error rather than executed truncated. The parser unescapes once, after
splitting, which means a cell reaching `grep -E` as alternation and a cell reaching
basic-regex `grep -c` as alternation are spelled differently:

| In the table cell | Reaches the shell as | Under `grep -E` | Under `grep -c` (BRE) |
|---|---|---|---|
| `a\|b` | `a\|b` | alternation | literal `a\|b` |
| `a\\\|b` | `a\\|b` | literal `a\\|b` | alternation |

Anti-criteria are the rows that most often need alternation and most often use
`grep -c`, so they usually want the **doubled** backslash. The sample row below is
written that way on purpose. Prove any anti-criterion two-pole (red against a
deliberately-violating input, green against clean) before trusting it — a row that
cannot fail is not a gate.

**Anti-criteria** are inverse rows in this table that assert a forbidden code-level
outcome from a No-Go cannot be detected in the PR. They are opt-in: only add an
inverse row when you can write a command that mechanically detects the violation.
Expand All @@ -480,7 +512,7 @@ zero checks -- give at least one table a `Command` column, or drop the rows.]
| Lint clean | `python -m ruff check .` | exit code 0 |
| Format clean | `python -m ruff format --check .` | exit code 0 |
| No stale xfails | `grep -rn 'xfail' tests/ \| grep -v '# open bug'` | exit code 1 |
| [Anti-criterion example] | `grep -c "forbidden_pattern" changed/file.py` | match count == 0 |
| [Anti-criterion example] | `grep -c "r\.delete\\\|r\.srem" changed/file.py` | match count == 0 |
| [Feature-specific check] | `[command]` | [expected] |

## Critique Results
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ When creating AgentSessions manually to test worker or queue behavior, use a rec
6. **MINIMAL TOOLS** — loading all tools pollutes context and degrades performance. Start minimal, expand only if needed.
7. **DEFINITION OF DONE** — the authoritative list lives in [`.claude/skills-global/do-build/SKILL.md`](.claude/skills-global/do-build/SKILL.md) and is enforced by `/do-build` and the builder agent.
8. **PARALLEL EXECUTION** — spawn parallel sub-agents for genuinely independent tasks; never for sequential or dependent work. Aggregate results before reporting.
9. **SDLC PIPELINE** — an Eng-role AgentSession handles both orchestration and execution. `/sdlc` is a **single-stage router**: assess state, invoke ONE sub-skill, return. Never write code, run tests, or create plans directly; always delegate through sub-skills. Agent gating reads of a PR's head SHA must resolve through `tools/pr_head_resolver.py::resolve_pr_head_sha` (git-first via `git ls-remote refs/pull/N/head`), never a bare `gh` read: a stale `gh` head SHA matches the recorded verdict's trailer and flips the verdict-staleness gate from fail-closed to fail-open (see [`docs/features/gh-stale-state-verdict-gate.md`](docs/features/gh-stale-state-verdict-gate.md)). Ground truth on stages: [`.claude/skills-global/do-sdlc/SKILL.md`](.claude/skills-global/do-sdlc/SKILL.md).
9. **SDLC PIPELINE** — an Eng-role AgentSession handles both orchestration and execution. `/sdlc` is a **single-stage router**: assess state, invoke ONE sub-skill, return. Never write code, run tests, or create plans directly; always delegate through sub-skills. Agent gating reads of a PR's head SHA must resolve through `tools/pr_head_resolver.py::resolve_pr_head_sha` (git-first via `git ls-remote refs/pull/N/head`), never a bare `gh` read: a stale `gh` head SHA matches the recorded verdict's trailer and flips the verdict-staleness gate from fail-closed to fail-open (see [`docs/features/gh-stale-state-verdict-gate.md`](docs/features/gh-stale-state-verdict-gate.md)). The same rule now governs a second gate: a plan's `## Verification` rows grade `PASS` / `FAIL` / `UNEVALUATED`, and `tools/merge_predicate.py` refuses to merge on a `FAIL` or `UNEVALUATED` row, reading the aggregate the runner recorded rather than re-executing anything. That aggregate is trusted only while its stamped head SHA matches the PR's current head; a mismatched, absent, or unresolvable SHA refuses. Each consumer owns its own disposition for `UNEVALUATED` rather than reading a per-row marker: the merge predicate may never let one ship, and the build gate blocks on one today (see [`docs/features/machine-readable-dod.md`](docs/features/machine-readable-dod.md)). The aggregate is recorded at REVIEW, the first stage with a PR head to stamp it against; BUILD grades the same table but records nothing. Ground truth on stages: [`.claude/skills-global/do-sdlc/SKILL.md`](.claude/skills-global/do-sdlc/SKILL.md).
10. **RESTART RUNNING SERVICES** — see the restart note under Commands.

## Development Workflow
Expand Down
Loading