okstra 0.223.2 → 0.225.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.
- package/dist/commands/execute/render-bundle.mjs +7 -5
- package/dist/commands/execute/render-bundle.mjs.map +1 -1
- package/docs/cli.md +10 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/lib/okstra/cli.sh +5 -1
- package/runtime/bin/lib/okstra/globals.sh +1 -0
- package/runtime/bin/lib/okstra/usage.sh +4 -1
- package/runtime/bin/okstra-provider-exec.py +32 -16
- package/runtime/bin/okstra.sh +1 -0
- package/runtime/prompts/coding-preflight/clean-code.md +8 -1
- package/runtime/prompts/duties/code-reviewer.json +5 -3
- package/runtime/prompts/wizard/prompts.ko.json +10 -0
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +2 -0
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +3 -1
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -0
- package/runtime/python/okstra_ctl/adapters/providers/zai/adapter.py +5 -1
- package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +25 -0
- package/runtime/python/okstra_ctl/code_review_coverage.py +213 -0
- package/runtime/python/okstra_ctl/code_review_target.py +31 -2
- package/runtime/python/okstra_ctl/coverage_census.py +2 -2
- package/runtime/python/okstra_ctl/dispatch_core.py +15 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +6 -0
- package/runtime/python/okstra_ctl/incremental_carry.py +10 -16
- package/runtime/python/okstra_ctl/phases/final_verification/profile.md +1 -1
- package/runtime/python/okstra_ctl/phases/implementation/instructions/_implementation-diff-review.md +1 -1
- package/runtime/python/okstra_ctl/phases/implementation/instructions/_implementation-verifier.md +2 -2
- package/runtime/python/okstra_ctl/phases/implementation_planning/authoring.py +164 -33
- package/runtime/python/okstra_ctl/phases/implementation_planning/instructions/plan-body-verification.md +27 -3
- package/runtime/python/okstra_ctl/phases/implementation_planning/plan_body.py +33 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/profile.md +1 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/round_completion.py +177 -0
- package/runtime/python/okstra_ctl/plan_item_evidence.py +237 -0
- package/runtime/python/okstra_ctl/plan_items.py +12 -9
- package/runtime/python/okstra_ctl/plan_review_context.py +82 -0
- package/runtime/python/okstra_ctl/render.py +2 -0
- package/runtime/python/okstra_ctl/run.py +23 -2
- package/runtime/python/okstra_ctl/team.py +12 -18
- package/runtime/python/okstra_ctl/verdict_blocks.py +17 -1
- package/runtime/python/okstra_ctl/wizard/__init__.py +1 -0
- package/runtime/python/okstra_ctl/wizard/confirmation.py +2 -0
- package/runtime/python/okstra_ctl/wizard/engine.py +26 -5
- package/runtime/python/okstra_ctl/wizard/ids.py +3 -0
- package/runtime/python/okstra_ctl/wizard/registry.py +13 -0
- package/runtime/python/okstra_ctl/wizard/render.py +1 -0
- package/runtime/python/okstra_ctl/wizard/state.py +8 -0
- package/runtime/python/okstra_ctl/wizard/steps_identity.py +99 -16
- package/runtime/python/okstra_ctl/wizard/steps_options.py +52 -1
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +14 -0
- package/runtime/python/okstra_ctl/worker_dispatch.py +9 -0
- package/runtime/python/okstra_ctl/worker_request.py +12 -1
- package/runtime/schemas/execution-manifest-v2.schema.json +1 -0
- package/runtime/schemas/final-report-v2.0.schema.json +3 -1
- package/runtime/schemas/final-report-v3.0.schema.json +3 -1
- package/runtime/skills/_fragments/bash-invocation-rule.md +1 -1
- package/runtime/skills/_fragments/host-question-interface.md +1 -0
- package/runtime/skills/_fragments/host-runtime-selection.md +1 -0
- package/runtime/skills/_fragments/wizard-bash-invocation-rule.md +1 -1
- package/runtime/skills/_fragments/wizard-preflight.md +1 -1
- package/runtime/skills/_fragments/wizard-render-bundle.md +4 -4
- package/runtime/skills/okstra-brief-gen/SKILL.md +45 -47
- package/runtime/skills/okstra-brief-gen/references/reporter-confirmations.md +3 -3
- package/runtime/skills/okstra-brief-gen/references/tracker-recursion.md +1 -1
- package/runtime/skills/okstra-chat/SKILL.md +1 -1
- package/runtime/skills/okstra-code-review/SKILL.md +26 -15
- package/runtime/skills/okstra-code-review/references/census-rules.md +38 -2
- package/runtime/skills/okstra-code-review/references/review-calibration.md +39 -15
- package/runtime/skills/okstra-container-build/SKILL.md +6 -2
- package/runtime/skills/okstra-discussion/SKILL.md +6 -6
- package/runtime/skills/okstra-inspect/SKILL.md +5 -3
- package/runtime/skills/okstra-manager/SKILL.md +8 -4
- package/runtime/skills/okstra-memory/SKILL.md +1 -1
- package/runtime/skills/okstra-pr-gen/SKILL.md +10 -6
- package/runtime/skills/okstra-rollup/SKILL.md +6 -2
- package/runtime/skills/okstra-run/SKILL.md +8 -7
- package/runtime/skills/okstra-schedule-gen/SKILL.md +13 -6
- package/runtime/skills/okstra-setup/SKILL.md +8 -4
- package/runtime/skills/okstra-setup/references/project-config.md +3 -3
- package/runtime/skills/okstra-usage/SKILL.md +5 -1
- package/runtime/skills/okstra-user-response/SKILL.md +7 -3
|
@@ -9557,7 +9557,8 @@
|
|
|
9557
9557
|
"block": {"type": "string", "enum": ["execution", "record"]},
|
|
9558
9558
|
"stageScope": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9559
9559
|
"contentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 of subject+payload+block+stageScope for the current extract."},
|
|
9560
|
-
"verifiedContentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "
|
|
9560
|
+
"verifiedContentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Body hash at the last apply-verdicts; insufficient on its own for runtime verdict reuse."},
|
|
9561
|
+
"verifiedReviewHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Runtime fingerprint of the judged body, declared evidence closure, contract, roster and detailed votes."},
|
|
9561
9562
|
"id": {
|
|
9562
9563
|
"type": "string",
|
|
9563
9564
|
"minLength": 1
|
|
@@ -9597,6 +9598,7 @@
|
|
|
9597
9598
|
"additionalProperties": false,
|
|
9598
9599
|
"properties": {
|
|
9599
9600
|
"claimKind": {"description": "Set only on DISAGREE. `fact` claims are settled by reproduction, `judgement` by quorum.", "enum": ["fact", "judgement", null]},
|
|
9601
|
+
"dependencies": {"type": "object", "required": ["complete", "itemIds", "paths"], "additionalProperties": false, "properties": {"complete": {"type": "boolean"}, "itemIds": {"type": "array", "items": {"type": "string", "minLength": 1}}, "paths": {"type": "array", "items": {"type": "string", "minLength": 1}}}},
|
|
9600
9602
|
"reproduction": {"description": "Set only on a `fact` claim. The probe okstra runs; see okstra_ctl/claim_reproduction.py.", "type": ["object", "null"]},
|
|
9601
9603
|
"reproductionResult": {"description": "Written by okstra, not by the worker.", "enum": ["reproduced", "not-reproduced", "not-runnable", null]},
|
|
9602
9604
|
"worker": {
|
|
@@ -9849,7 +9849,8 @@
|
|
|
9849
9849
|
"block": {"type": "string", "enum": ["execution", "record"]},
|
|
9850
9850
|
"stageScope": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9851
9851
|
"contentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 of subject+payload+block+stageScope for the current extract."},
|
|
9852
|
-
"verifiedContentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "
|
|
9852
|
+
"verifiedContentHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Body hash at the last apply-verdicts; insufficient on its own for runtime verdict reuse."},
|
|
9853
|
+
"verifiedReviewHash": {"type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Runtime fingerprint of the judged body, declared evidence closure, contract, roster and detailed votes."},
|
|
9853
9854
|
"id": {
|
|
9854
9855
|
"type": "string",
|
|
9855
9856
|
"minLength": 1
|
|
@@ -9896,6 +9897,7 @@
|
|
|
9896
9897
|
"additionalProperties": false,
|
|
9897
9898
|
"properties": {
|
|
9898
9899
|
"claimKind": {"description": "Set only on DISAGREE. `fact` claims are settled by reproduction, `judgement` by quorum.", "enum": ["fact", "judgement", null]},
|
|
9900
|
+
"dependencies": {"type": "object", "required": ["complete", "itemIds", "paths"], "additionalProperties": false, "properties": {"complete": {"type": "boolean"}, "itemIds": {"type": "array", "items": {"type": "string", "minLength": 1}}, "paths": {"type": "array", "items": {"type": "string", "minLength": 1}}}},
|
|
9899
9901
|
"reproduction": {"description": "Set only on a `fact` claim. The probe okstra runs; see okstra_ctl/claim_reproduction.py.", "type": ["object", "null"]},
|
|
9900
9902
|
"reproductionResult": {"description": "Written by okstra, not by the worker.", "enum": ["reproduced", "not-reproduced", "not-runnable", null]},
|
|
9901
9903
|
"worker": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Run one
|
|
1
|
+
Run one shell-command tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — literal command tokens keep execution permissions reviewable):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
For authored questions, `prompt_user` means the current host's available question interface, not a literal tool name. Use the selected host relay when one is provided. Preserve every question, option, description, and answer; use native controls only when the live session permits them and the complete interaction fits its limits. Otherwise show complete numbered choices and accept the user's reply; collect free text through normal conversation. If a native control is refused, follow the relay's recovery mapping, or use text when no relay is provided. A delivery acknowledgement or preselected option is not an answer; wait for the user's actual response.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Resolve `<host-runtime>` from the launcher's `OKSTRA_RUNTIME_HOST` when present; otherwise use the registered host ID declared by the current harness. Do not infer the host from worker models, installed executables, or `PATH`. If neither source identifies the host, report that it is unknown instead of substituting another host. Keep the same resolved host when retrying against another project directory.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
**
|
|
1
|
+
**Shell invocation rule (permission-friendly)**: every shell command in this skill begins with the literal token `okstra` (or another already-allowed binary) and passes literal argument values. Do not introduce shell variables (`$STATE_FILE`, `$ANSWER`, `$projectRoot`, ...), `$(...)` command substitution, or leading `VAR=...` assignments — any of those make the command harder to audit; apply the selected host adapter's execution-permission guidance. When a prior tool call emitted a path or value, read it from the tool output and paste the literal string into the next command.
|
|
@@ -6,7 +6,7 @@ Record the semantic functions that the live harness can actually perform. Always
|
|
|
6
6
|
|
|
7
7
|
The host-native provider runs as the current lead session when its role is supported. Other selected providers run through their registered CLI wrappers. Claude remains only the model-policy default; it is not the process owner.
|
|
8
8
|
|
|
9
|
-
Run one
|
|
9
|
+
Run one shell-command tool call (Shell invocation rule from the top of this file applies):
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
okstra preflight --runtime <host-runtime>
|
|
@@ -29,9 +29,9 @@ okstra config set pr-template-path "<value>" --scope global
|
|
|
29
29
|
|
|
30
30
|
If an action has an unknown `command`, `key`, or `scope`, stop and report the wizard output instead of inventing a command.
|
|
31
31
|
|
|
32
|
-
Before rendering the next phase's bundle — and between worker rounds within a phase (reverify/critic/gapverify batches), after you have collected that round's results and token usage and before you dispatch the next round — close the panes of the dispatches that finished in the prior round so they do not accumulate: `okstra team reclaim --project-root <projectRoot> --run-manifest <RUN_MANIFEST_PATH>` closes them, records `phase-batch-cleanup panes=<n>` with the number it closed, and prints that `PROGRESS:` line last — emit it as printed and do not call `okstra lead-progress append` for it. The command reads each dispatch's recorded status, so an in-progress worker keeps its pane whichever moment you call it. It closes only the panes okstra opened and recorded — a pane the harness opened for its own teammate carries no recorded id and is not okstra's to close.
|
|
32
|
+
Before rendering the next phase's bundle — and between worker rounds within a phase (reverify/critic/gapverify batches), after you have collected that round's results and token usage and before you dispatch the next round — close the panes of the dispatches that finished in the prior round so they do not accumulate: `okstra team reclaim --project-root <projectRoot> --run-manifest <RUN_MANIFEST_PATH>` closes them, records `phase-batch-cleanup panes=<n>` with the number it closed, and prints that `PROGRESS:` line last — emit it as printed and do not call `okstra lead-progress append` for it. The command reads each dispatch's recorded status, so an in-progress worker keeps its pane whichever moment you call it. It closes only the panes okstra opened and recorded — a pane the harness opened for its own teammate carries no recorded id and is not okstra's to close. After collecting results and token usage, apply the selected adapter's `shutdown_workers` operation only to confirmed-complete workers; preserve in-flight workers and the lead. A `cli-wrapper` run holds no pane at all and `team reclaim` refuses it, so record the checkpoint there with `okstra lead-progress append … --phase phase-batch-cleanup --field panes=0`.
|
|
33
33
|
|
|
34
|
-
Before you ask the user for any approval, clarification, or decision after workers have been dispatched, run `okstra team reclaim … --gate` first: it closes the finished panes and prints `PROGRESS: phase-gate-cleanup panes=<n>` for you to emit, without recording a batch cleanup. Then
|
|
34
|
+
Before you ask the user for any approval, clarification, or decision after workers have been dispatched, run `okstra team reclaim … --gate` first: it closes the finished panes and prints `PROGRESS: phase-gate-cleanup panes=<n>` for you to emit, without recording a batch cleanup. Then apply the selected adapter's `shutdown_workers` operation to confirmed-complete workers after collecting their results and token usage; preserve in-flight workers and the lead. This keeps a user gate from being shown while finished worker panes remain; in-progress dispatches keep their panes. Then follow `prompts/lead/okstra-lead-contract.md` "User confirmation before an approval blocker": read cited plan items, worker findings, and files before asking, and ask in the user's language with each option's outcome.
|
|
35
35
|
|
|
36
36
|
Build the `okstra render-bundle` invocation from `outcome.renderArgv`, passing every token verbatim and in order (including empty strings — they are intentional `use phase default` markers).
|
|
37
37
|
|
|
@@ -44,13 +44,13 @@ Step 3's empty-answer and escaping rules apply verbatim: every flag in `renderAr
|
|
|
44
44
|
`renderArgv` already contains exactly one `--lead-runtime <host-runtime>` pair. Do not add or replace it. Do not enumerate a fixed provider list in this skill because the wizard and role model pool own the ordered tokens.
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
okstra render-bundle \
|
|
47
|
+
okstra render-bundle --summary-only \
|
|
48
48
|
<outcome.renderArgv token 1> \
|
|
49
49
|
<outcome.renderArgv token 2> \
|
|
50
50
|
<each remaining outcome.renderArgv token in order>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
`render-bundle` auto-supplies `--workspace-root` and forces `--render-only`. Stdout prints `okstra task root:`, `okstra instruction-set:`, `okstra run manifest:`, and
|
|
53
|
+
`render-bundle` auto-supplies `--workspace-root` and forces `--render-only`. Stdout prints `okstra task root:`, `okstra instruction-set:`, `okstra run manifest:`, and other preparation status. `--summary-only` omits the lead prompt body from stdout; Step 6 reads the verified saved prompt from the manifest path. Parse the labelled lines for `TASK_ROOT`, `INSTRUCTION_SET_PATH`, and `RUN_MANIFEST_PATH`. Also watch for an optional `okstra concurrent-run stages:` label line — present only when a concurrent run is detected (see "Concurrent-run detection branch" below).
|
|
54
54
|
|
|
55
55
|
Before acting as the lead, read `resources.leadPromptMetadataPath` from the run
|
|
56
56
|
manifest and execute the host-native specification-link gate:
|
|
@@ -6,6 +6,10 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# okstra-brief-gen
|
|
8
8
|
|
|
9
|
+
<!-- BEGIN FRAGMENT: host-question-interface -->
|
|
10
|
+
For authored questions, `prompt_user` means the current host's available question interface, not a literal tool name. Use the selected host relay when one is provided. Preserve every question, option, description, and answer; use native controls only when the live session permits them and the complete interaction fits its limits. Otherwise show complete numbered choices and accept the user's reply; collect free text through normal conversation. If a native control is refused, follow the relay's recovery mapping, or use text when no relay is provided. A delivery acknowledgement or preselected option is not an answer; wait for the user's actual response.
|
|
11
|
+
<!-- END FRAGMENT: host-question-interface -->
|
|
12
|
+
|
|
9
13
|
Generate a single `task brief` markdown file under the okstra project domain
|
|
10
14
|
(`.okstra/briefs/<task-group>/<task-id>.md`) so it can be fed to
|
|
11
15
|
[`okstra-run`](../okstra-run/SKILL.md) as `--task-brief`.
|
|
@@ -114,10 +118,10 @@ and never writes them. Decision files (when raised by
|
|
|
114
118
|
|
|
115
119
|
## Step 0: Preflight
|
|
116
120
|
|
|
117
|
-
Every
|
|
121
|
+
Every shell command in this skill is a **separate shell-command tool call**.
|
|
118
122
|
|
|
119
123
|
<!-- BEGIN FRAGMENT: bash-invocation-rule -->
|
|
120
|
-
Run one
|
|
124
|
+
Run one shell-command tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — literal command tokens keep execution permissions reviewable):
|
|
121
125
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
122
126
|
|
|
123
127
|
```bash
|
|
@@ -144,13 +148,7 @@ selection and the material it collects as separate interactions: a native
|
|
|
144
148
|
choice selects the input path, and the next free-text interaction receives a
|
|
145
149
|
path, URL, ticket reference, or body.
|
|
146
150
|
|
|
147
|
-
|
|
148
|
-
their stated order. Do not add an `Other` option: the Codex client adds its
|
|
149
|
-
own free-text `Other` row. When the user supplies a value through that row,
|
|
150
|
-
classify it through the normal reporter-source rules (ticket, URL, or user
|
|
151
|
-
input) and do not ask them to repeat it. If the host does not expose a
|
|
152
|
-
compatible native control, render the same options as a numbered text choice
|
|
153
|
-
and retain the explicit free-text follow-up where this skill specifies one.
|
|
151
|
+
Use the current host's native single-select mapping with every listed option in order. If the host supplies its own free-text row, do not add a duplicate. Classify a custom value through the normal reporter-source rules and do not ask the user to repeat it. If no compatible native control is available, render the complete options as numbered text and retain the specified free-text follow-up.
|
|
154
152
|
|
|
155
153
|
## Step 1: Choose input source
|
|
156
154
|
|
|
@@ -190,7 +188,7 @@ for every variant and every source type below.
|
|
|
190
188
|
|
|
191
189
|
### 1.0. brief variant
|
|
192
190
|
|
|
193
|
-
`
|
|
191
|
+
`prompt_user` (single-select):
|
|
194
192
|
|
|
195
193
|
- **Label**: `"Brief variant?"`
|
|
196
194
|
- **Options**:
|
|
@@ -207,7 +205,7 @@ collected source material, then classify a ticket reference or URL normally.
|
|
|
207
205
|
|
|
208
206
|
If the user picked `Reporter input`, proceed to Step 1.A's sub-flow below — this is the existing 4-source flow. Choose ONE of:
|
|
209
207
|
|
|
210
|
-
`
|
|
208
|
+
`prompt_user` (single-select):
|
|
211
209
|
|
|
212
210
|
- **Label**: "Source of this brief?"
|
|
213
211
|
- **Options** (single-select):
|
|
@@ -252,7 +250,7 @@ Order of operations:
|
|
|
252
250
|
placeholder group.
|
|
253
251
|
|
|
254
252
|
**Sequential, never batched.** Run Step 2a as its **own**
|
|
255
|
-
`
|
|
253
|
+
`prompt_user` call, then ask sub-step 1's ticket question in a
|
|
256
254
|
**separate** call — never combine the task-group and ticket-ref
|
|
257
255
|
questions into one. When you relay this preflight, tell the user in one
|
|
258
256
|
line *why* task group comes first (it scopes where this ticket's brief —
|
|
@@ -262,30 +260,30 @@ Order of operations:
|
|
|
262
260
|
directory segment to equal the slugified frontmatter `task-group`, so a
|
|
263
261
|
brief written before the group is known — or under an invented placeholder
|
|
264
262
|
group — fails validation rather than landing in the wrong tree.
|
|
265
|
-
1. `
|
|
263
|
+
1. `prompt_user` (free text):
|
|
266
264
|
`"Ticket key or URL (e.g. LIN-1234, PROJ-42, https://linear.app/..., https://your.atlassian.net/browse/...)"` →
|
|
267
265
|
`ticket_ref`. Issue this only **after** Step 2a's task-group answer is in
|
|
268
266
|
hand (per sub-step 0's sequential rule).
|
|
269
267
|
2. Auto-detect the tracker by URL host or key prefix (`linear.app` → Linear,
|
|
270
268
|
`atlassian.net` or `JIRA_*` pattern → Jira, `github.com/.../issues/` →
|
|
271
269
|
GitHub, `notion.so` → Notion). If detection fails, ask once more via
|
|
272
|
-
`
|
|
270
|
+
`prompt_user`.
|
|
273
271
|
3. Check whether the tracker's **MCP tools** are loaded in the current
|
|
274
272
|
session and prefer them when available:
|
|
275
273
|
- Linear → `mcp__linear__*` family (e.g. `get_issue` /
|
|
276
|
-
`getIssueByIdentifier`). If absent, try
|
|
277
|
-
`linear
|
|
278
|
-
- Jira → `mcp__jira__*` (or `mcp__atlassian__*`).
|
|
279
|
-
fallback.
|
|
274
|
+
`getIssueByIdentifier`). If absent, try the host's tool-discovery capability (when available) with the keyword
|
|
275
|
+
`linear`; if discovery is unavailable, continue to step 4.
|
|
276
|
+
- Jira → `mcp__jira__*` (or `mcp__atlassian__*`). Use the same capability-discovery
|
|
277
|
+
fallback when available; otherwise continue to step 4.
|
|
280
278
|
- GitHub → `gh issue view <num> --repo <owner>/<repo> --json title,body,comments,labels,state`
|
|
281
279
|
(an authenticated `gh` CLI is the default path — usable even when MCP
|
|
282
|
-
is present). If `gh` is missing or unauthenticated, try
|
|
280
|
+
is present). If `gh` is missing or unauthenticated, try the host's tool-discovery capability (when available)
|
|
283
281
|
for `mcp__github` family; otherwise fall through to step 4 (paste /
|
|
284
282
|
skip).
|
|
285
283
|
- Notion → `mcp__notion__API-retrieve-a-page` /
|
|
286
284
|
`API-get-block-children`.
|
|
287
285
|
4. If **no** MCP or CLI path is available:
|
|
288
|
-
- Ask the user via `
|
|
286
|
+
- Ask the user via `prompt_user`:
|
|
289
287
|
`"<tracker> MCP is not connected. (a) Paste the ticket body here / (b) Skip this source"`.
|
|
290
288
|
- Never invent ticket content.
|
|
291
289
|
5. Preserve the retrieved fields (summary/title, description body, comments,
|
|
@@ -311,11 +309,11 @@ Order of operations:
|
|
|
311
309
|
|
|
312
310
|
Order of operations:
|
|
313
311
|
|
|
314
|
-
1. `
|
|
315
|
-
2. Fetch
|
|
316
|
-
|
|
312
|
+
1. `prompt_user` (free text): `"Link URL"`.
|
|
313
|
+
2. Fetch through an available URL-fetch tool. If tools are deferred, discover
|
|
314
|
+
that capability through the current host when discovery is available.
|
|
317
315
|
3. On fetch failure or auth required (login wall, intranet-only, etc.):
|
|
318
|
-
- Ask the user via `
|
|
316
|
+
- Ask the user via `prompt_user` to paste the body.
|
|
319
317
|
- Never invent URL content.
|
|
320
318
|
4. Preserve the fetched content (title + body + quotes/examples) **verbatim**
|
|
321
319
|
in Source Material. Do not excerpt or summarize long pages to fit a line
|
|
@@ -333,7 +331,7 @@ Two sub-modes combined under one option.
|
|
|
333
331
|
Material as `conversation synthesis` and quote key utterances verbatim
|
|
334
332
|
wherever possible.
|
|
335
333
|
- **Inline input**: if conversation context is empty or thin, take one
|
|
336
|
-
free-text `
|
|
334
|
+
free-text `prompt_user`. The received text is preserved in Source
|
|
337
335
|
Material without changing a character.
|
|
338
336
|
|
|
339
337
|
When both are used, record them as two separate sub-sources under Source
|
|
@@ -343,20 +341,20 @@ Material.
|
|
|
343
341
|
|
|
344
342
|
If the user picked `Codebase scan`, gather the codebase-scan-specific inputs:
|
|
345
343
|
|
|
346
|
-
1. `
|
|
344
|
+
1. `prompt_user` (free text):
|
|
347
345
|
`"Scan scope — comma-separated paths inside the project (e.g. src/foo/, src/bar/baz.py)"` → `scan_scope` (CSV).
|
|
348
|
-
2. `
|
|
346
|
+
2. `prompt_user` (multi-select, options = the lens values from `~/.okstra/lib/python/okstra_ctl/phases/improvement_discovery/lenses.py`'s `LENSES` — code source: `scripts/okstra_ctl/phases/improvement_discovery/lenses.py`):
|
|
349
347
|
`"Priority lenses (pick 1–4)"` → `priority_lenses` (1..4 values from the enum).
|
|
350
348
|
Current `LENSES` values (this list mirrors the module — if they diverge, the module wins; Step 6.6 `validate-brief` enforces the subset): `performance`, `security`, `readability`, `architecture`, `test-coverage`, `dx`, `observability`, `accessibility`.
|
|
351
|
-
3. `
|
|
349
|
+
3. `prompt_user` (free text):
|
|
352
350
|
`"Out-of-scope paths (optional, comma-separated)"` → `out_of_scope` (CSV, empty allowed).
|
|
353
|
-
4. `
|
|
351
|
+
4. `prompt_user` (free text):
|
|
354
352
|
`"Candidate cap (1–12, default 8)"` → `candidate_cap` (integer; empty → 8).
|
|
355
|
-
5. `
|
|
353
|
+
5. `prompt_user` (free text):
|
|
356
354
|
`"Context — why is this scope being scanned now? One short paragraph."` → `context`.
|
|
357
|
-
6. `
|
|
355
|
+
6. `prompt_user` (free text):
|
|
358
356
|
`"Desired outcome — what kinds of improvements do you want surfaced? Anti-goals?"` → `desired_outcome`.
|
|
359
|
-
7. `
|
|
357
|
+
7. `prompt_user` (free text):
|
|
360
358
|
`"Constraints — untouchable areas, deadlines, compatibility (optional)"` → `constraints`.
|
|
361
359
|
|
|
362
360
|
Validation (before Step 4 sharpening):
|
|
@@ -374,7 +372,7 @@ If the user picked `Error feedback`, the input is a `.zip` produced by `okstra e
|
|
|
374
372
|
Input: the `.zip` produced by `okstra error-zip`. Ask the user for the zip path (if a path was received earlier, propose reusing it as `Recommended:`).
|
|
375
373
|
|
|
376
374
|
1. Read the zip's `report.md`, show the frequent-cluster table to the user, and have them pick **one cluster**.
|
|
377
|
-
`
|
|
375
|
+
`prompt_user` (single-select, `Specify manually` always last):
|
|
378
376
|
1. top-1 cluster (highest frequency) — marked `Recommended:`.
|
|
379
377
|
2. top-2 cluster.
|
|
380
378
|
3. `Specify manually` — the user names a cluster directly from the table.
|
|
@@ -413,7 +411,7 @@ shown in slug form.
|
|
|
413
411
|
|
|
414
412
|
If `Status` is `error`, report `Failure stage` and `Failure reason`, then stop.
|
|
415
413
|
|
|
416
|
-
`
|
|
414
|
+
`prompt_user` (single-select):
|
|
417
415
|
|
|
418
416
|
- **Label**: `"Task group?"`
|
|
419
417
|
- **Options** (recommendations first, `Enter directly` always last):
|
|
@@ -465,7 +463,7 @@ relations are also tracked via the brief's `parent-id` frontmatter
|
|
|
465
463
|
- Jira `PROJ-42` → `PROJ-42`
|
|
466
464
|
- GitHub `owner/repo#123` → `gh-<repo>-123`
|
|
467
465
|
- Notion (no canonical id) → `notion-<8-char-page-short-id>`
|
|
468
|
-
- **File / URL / User-input sources**: `
|
|
466
|
+
- **File / URL / User-input sources**: `prompt_user` (free text):
|
|
469
467
|
- `"Ticket / identifier (e.g. dev-9043, INV-1234, login-error)"` →
|
|
470
468
|
`ticket_id`
|
|
471
469
|
|
|
@@ -483,7 +481,7 @@ to Source Material body, not to the filename):
|
|
|
483
481
|
5. Trim leading/trailing `-`
|
|
484
482
|
- Example: Linear `LIN-1234 "Fix flaky login retry on 5xx"` →
|
|
485
483
|
`LIN-1234-fix-flaky-login-retry-on-5xx.md`
|
|
486
|
-
- **Other sources**: `
|
|
484
|
+
- **Other sources**: `prompt_user` (free text):
|
|
487
485
|
- `"File title (short summary, e.g. fix-login-retry, dev-9043-brief)"` →
|
|
488
486
|
`file_title`
|
|
489
487
|
- Apply rules 1–5 above. Re-ask on empty input.
|
|
@@ -495,7 +493,7 @@ alphanumeric character after slugification. Apply Step 2c on collision.
|
|
|
495
493
|
|
|
496
494
|
### 2c. Collision handling
|
|
497
495
|
|
|
498
|
-
If a brief file already exists, `
|
|
496
|
+
If a brief file already exists, `prompt_user` with (`Skip` /
|
|
499
497
|
`Append suffix` / `Overwrite`). Default recommendation: `Skip` —
|
|
500
498
|
protects briefs the user has already edited. `Append suffix` adds a
|
|
501
499
|
timestamp suffix to the filename stem.
|
|
@@ -503,7 +501,7 @@ timestamp suffix to the filename stem.
|
|
|
503
501
|
When multiple collisions occur in tracker multi-generation mode:
|
|
504
502
|
|
|
505
503
|
- First echo the colliding file list to the user.
|
|
506
|
-
- Ask **once** with `
|
|
504
|
+
- Ask **once** with `prompt_user` for a bulk policy.
|
|
507
505
|
- **Even when `Overwrite` is selected, confirm one more time for each
|
|
508
506
|
colliding file**, or warn that downgrading to `Append suffix` is safer. Silent bulk overwrite is forbidden.
|
|
509
507
|
|
|
@@ -585,7 +583,7 @@ project's domain.
|
|
|
585
583
|
|
|
586
584
|
Inspect the synthesized brief draft. For each REQUIRED section below that is
|
|
587
585
|
empty or trivially thin **after** reading Source Material verbatim, ask **at
|
|
588
|
-
most one** `
|
|
586
|
+
most one** `prompt_user` to fill it. Never ask about sections already
|
|
589
587
|
covered by the source material.
|
|
590
588
|
|
|
591
589
|
**Enforced:** `validators/validate-brief.py` fails a brief whose required section is missing, has a blank body (`check_variant_required_sections`), or still carries the template's `<...>` text (`check_template_scaffold`). `## Source Material` is exempt from the template-text check because it holds the reporter's words verbatim.
|
|
@@ -599,12 +597,12 @@ The following rules absorb the useful parts of `grill-me` /
|
|
|
599
597
|
inspection (e.g. "does this symbol exist?", "what does this endpoint
|
|
600
598
|
return today?"), do that **instead of** asking the user. Only ask when
|
|
601
599
|
the codebase cannot answer.
|
|
602
|
-
2. **Question carries a recommended answer** — every `
|
|
600
|
+
2. **Question carries a recommended answer** — every `prompt_user`
|
|
603
601
|
issued in this step must put the recommended option **first** with the
|
|
604
602
|
suffix `(Recommended)`. Free-text fallbacks are still allowed, but the
|
|
605
603
|
recommendation must be visible.
|
|
606
604
|
3. **One at a time** — never batch multiple questions into one
|
|
607
|
-
`
|
|
605
|
+
`prompt_user` call. Ask, wait for the answer, fold it into the
|
|
608
606
|
draft, then ask the next.
|
|
609
607
|
4. **Bounded budget** — at most **1** sharpening question per empty
|
|
610
608
|
required section, plus **at most 2** disambiguation questions arising
|
|
@@ -788,7 +786,7 @@ the skill does not write outside okstra's subtree.
|
|
|
788
786
|
### 4.5b. Approval flow (per entry)
|
|
789
787
|
|
|
790
788
|
For each draft, **first echo the target absolute path on one line** (so
|
|
791
|
-
the user sees the exact file that will be written), then `
|
|
789
|
+
the user sees the exact file that will be written), then `prompt_user`:
|
|
792
790
|
|
|
793
791
|
- **Label**: `"Apply glossary entry?"` (keep the label short — absolute
|
|
794
792
|
paths belong in the echo line above, not in the option chip)
|
|
@@ -936,7 +934,7 @@ one row per requirement unit, its destination section, and for an end-state
|
|
|
936
934
|
unit the `EB-` / `PB-` / `EO-` id it became. That table is what lets the
|
|
937
935
|
reporter check their own list in one pass. Then ask:
|
|
938
936
|
|
|
939
|
-
`
|
|
937
|
+
`prompt_user`: `"Proceed with this brief?"` — options `Save` / `Edit`.
|
|
940
938
|
On `Edit`, return to Step 4 for the section to revise; a unit the user reports
|
|
941
939
|
missing returns to this sweep instead.
|
|
942
940
|
|
|
@@ -991,7 +989,7 @@ in the brief's frontmatter and skip the rest of this step.
|
|
|
991
989
|
|
|
992
990
|
### 6.5b. Ask once: collect now or later
|
|
993
991
|
|
|
994
|
-
If the list is non-empty, run **one** `
|
|
992
|
+
If the list is non-empty, run **one** `prompt_user`:
|
|
995
993
|
|
|
996
994
|
- **Label**: `"This brief has <N> question(s) only the reporter can answer. Collect their answers now?"`
|
|
997
995
|
- **Options**:
|
|
@@ -1094,7 +1092,7 @@ constraints, ticket relations — and no single brief can recover it
|
|
|
1094
1092
|
(observed: a 15-brief group whose reason, "the origin keeps going down under
|
|
1095
1093
|
attack traffic", appeared in none of them, so option selection measured a
|
|
1096
1094
|
per-page ratio instead of origin load). If the file is absent, ask once via
|
|
1097
|
-
`
|
|
1095
|
+
`prompt_user`:
|
|
1098
1096
|
|
|
1099
1097
|
- `Create the group context skeleton now (Recommended for a new task-group)`
|
|
1100
1098
|
→ run `okstra group-context init --project-root <PROJECT_ROOT> --task-group <task-group>`
|
|
@@ -1168,7 +1166,7 @@ group context skeleton: <abs>/<task-group>/group-context.md (fill before /okst
|
|
|
1168
1166
|
- If a URL fetch fails or hits an auth wall, do not guess — ask for a
|
|
1169
1167
|
paste.
|
|
1170
1168
|
- Never fabricate content for empty sections; use `_(none)_`.
|
|
1171
|
-
- Echo each `
|
|
1169
|
+
- Echo each `prompt_user` outcome on one short line.
|
|
1172
1170
|
|
|
1173
1171
|
## Failure Modes
|
|
1174
1172
|
|
|
@@ -1177,7 +1175,7 @@ group context skeleton: <abs>/<task-group>/group-context.md (fill before /okst
|
|
|
1177
1175
|
| `project.json not found` | okstra not set up in this project | Tell user to run `okstra-setup`; stop. |
|
|
1178
1176
|
| `briefs/<group>/<id>.md already exists` | duplicate task-key | Step 2c overwrite prompt. |
|
|
1179
1177
|
| Source file not found | bad path in Step 1 | Re-ask. |
|
|
1180
|
-
| Linear/Jira MCP not connected | tracker MCP missing from the session | Try
|
|
1178
|
+
| Linear/Jira MCP not connected | tracker MCP missing from the session | Try the host's tool-discovery capability (when available) once → if still missing, ask the user to paste the body. Never guess. |
|
|
1181
1179
|
| URL fetch fails or 401 / login wall | intranet, paywall, JS-rendered page | Ask the user to paste the core body. Never guess. |
|
|
1182
1180
|
| Tracker body is in non-MD format (ADF / HTML) | Jira description, Notion blocks | Convert format only, preserve semantics. Annotate the conversion in the `format:` meta. |
|
|
1183
1181
|
| Brief comes out skeletal after synthesis | source too thin AND user picked `User input` with little context | Switch to inline input mode and ask one or two targeted questions. |
|
|
@@ -5,9 +5,9 @@ pending list of `intent-check:` / `conversion-block:` rows.
|
|
|
5
5
|
|
|
6
6
|
## 6.5c. Batch the questions
|
|
7
7
|
|
|
8
|
-
For each pending row, formulate one question.
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
For each pending row, formulate one question. Batch only when the current
|
|
9
|
+
host's question interface can present every question and option within its
|
|
10
|
+
live limits; otherwise ask sequentially without dropping any option.
|
|
11
11
|
|
|
12
12
|
**Cap — 12 questions per Step 6.5 run.** When the pending list exceeds 12
|
|
13
13
|
rows, sort by priority and ask only the top 12 this round:
|
|
@@ -27,7 +27,7 @@ which briefs are emitted, and how re-runs stay idempotent.
|
|
|
27
27
|
|
|
28
28
|
## 2. Ask once at the top parent
|
|
29
29
|
|
|
30
|
-
If there is one or more child, `
|
|
30
|
+
If there is one or more child, `prompt_user` (single-select):
|
|
31
31
|
|
|
32
32
|
- **Label**: `"This ticket has sub-tickets. How should the child tree be handled?"`
|
|
33
33
|
- **Options**:
|
|
@@ -18,7 +18,7 @@ The display name is typed at join. Do not invent a default name.
|
|
|
18
18
|
|
|
19
19
|
## Step 0: CLI
|
|
20
20
|
|
|
21
|
-
Run as a separate
|
|
21
|
+
Run as a separate shell-command tool call with literal leading token:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
okstra chat --help
|
|
@@ -34,17 +34,21 @@ This skill owns review calibration only:
|
|
|
34
34
|
|
|
35
35
|
## Step 0 — Preflight
|
|
36
36
|
|
|
37
|
+
<!-- BEGIN FRAGMENT: host-runtime-selection -->
|
|
38
|
+
Resolve `<host-runtime>` from the launcher's `OKSTRA_RUNTIME_HOST` when present; otherwise use the registered host ID declared by the current harness. Do not infer the host from worker models, installed executables, or `PATH`. If neither source identifies the host, report that it is unknown instead of substituting another host. Keep the same resolved host when retrying against another project directory.
|
|
39
|
+
<!-- END FRAGMENT: host-runtime-selection -->
|
|
40
|
+
|
|
37
41
|
<!-- BEGIN FRAGMENT: bash-invocation-rule -->
|
|
38
|
-
Run one
|
|
42
|
+
Run one shell-command tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — literal command tokens keep execution permissions reviewable):
|
|
39
43
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
40
44
|
|
|
41
45
|
```bash
|
|
42
|
-
okstra preflight --runtime
|
|
46
|
+
okstra preflight --runtime <host-runtime>
|
|
43
47
|
```
|
|
44
48
|
|
|
45
49
|
Branch on the fixed first line:
|
|
46
50
|
- `Okstra preflight: ready` → carry `Project root` as a literal string; every later step is anchored on it.
|
|
47
|
-
- `Okstra preflight: failed` → the check only sees the cwd of the Bash call, so a project that is not the cwd can read as missing setup. Ask whether the user pointed at a specific project directory; if they did, re-run targeting it: `okstra preflight --runtime
|
|
51
|
+
- `Okstra preflight: failed` → the check only sees the cwd of the Bash call, so a project that is not the cwd can read as missing setup. Ask whether the user pointed at a specific project directory; if they did, re-run targeting it: `okstra preflight --runtime <host-runtime> --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this also fails do you show `Reason` and `Recovery`, then stop.
|
|
48
52
|
|
|
49
53
|
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
50
54
|
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
@@ -154,7 +158,7 @@ it. **Every reviewer receives the same brief** — two reviewers are worth their
|
|
|
154
158
|
|
|
155
159
|
- the diff, plus how to read whole files at the reviewed commit: the `worktreePath` when it is non-empty, otherwise `git -C <projectRoot> show <headCommit>:<path>`
|
|
156
160
|
- the project layout in one or two lines (where source, tests, and — if the routing found one — domain / ports / adapters live)
|
|
157
|
-
- **the whole census** — every cell of all four axes, verbatim
|
|
161
|
+
- **the whole census** — the shared rule catalog once and every grouped cell of all four axes, verbatim
|
|
158
162
|
- the absolute paths of every applied pack (from step 2's routing)
|
|
159
163
|
- the calibration path, written out in full as Step 2 fixed it — `~/.agents/skills/okstra-code-review/references/review-calibration.md`. The verdict format, the severity points, and the rules for a legitimate `clean` are defined there, not in the brief; a reviewer that cannot open this file cannot return a usable verdict, so never hand it a relative path or a "next to the skill" hint
|
|
160
164
|
|
|
@@ -169,7 +173,7 @@ Axis scope — each reviewer works all four axes; the `Reads` column names each
|
|
|
169
173
|
| `state-and-tests` | non-test source file × `state-and-tests`, test file × `state-and-tests` | `clean-code.md` "Mutation and state boundaries" and "Testing discipline"; plus the routed language pack's self-mock signals |
|
|
170
174
|
| `general` | non-test source file × `general` | correctness bugs, swallowed errors, `clean-code.md` "Untrusted input and security" (work that grows faster than the input before a size bound rejects it, input building SQL / shell / paths / fetch targets / templates / regexes, a new entry point without auth or ownership checks, secrets or personal data in code, logs or responses, evaluating input), clear performance problems, core principle 7 (fix at the cause — nothing previously green edited to silence a failure); `clean-code.md` "Wrapping a third-party call" — a recovery branch the library already performs, a comment naming a condition the call site never establishes, a rethrow that drops the original error; plus the routed language pack's language-specific traps |
|
|
171
175
|
|
|
172
|
-
|
|
176
|
+
The materialized prompt injects the `code-reviewer` duty contract. Keep task briefs focused on the assigned census, comparison range, rule paths, and result format; do not restate the injected duty.
|
|
173
177
|
|
|
174
178
|
Capture each raw model return under `.okstra/agent-invocations/code-review/.tmp/`. Publish it with
|
|
175
179
|
`okstra agent-prompt materialize-result`, publish the immutable completion marker with
|
|
@@ -179,12 +183,19 @@ review result and cannot contribute a verdict.
|
|
|
179
183
|
|
|
180
184
|
## Step 3.5 — Audit the coverage
|
|
181
185
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
Keep normal output to one compact Coverage Verdicts row per cell, with explicit rule IDs and one source anchor. No target-by-bullet verdict table or repeated per-rule clean prose.
|
|
187
|
+
|
|
188
|
+
For each reviewer separately, audit its grouped rows and explicit rule-ID accounting using its verified completion marker:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
okstra code-review check-coverage --project-root <projectRoot> --census <grouped-census-path> --completion <completion-path> [--completion <gap-fill-completion-path> ...]
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The command reuses the existing completion verification boundary and refuses mixed model assignments. Exit 0 means every cell accounts for all rules in its group with valid source evidence and no unknown cell ID; exit 1 lists missing cells, missing rule IDs or invalid grouped verdicts; exit 2 reports invalid input or completion evidence. It validates the shared catalog and source anchors, but does not establish whether the selected references are exhaustive or a verdict is true.
|
|
195
|
+
|
|
196
|
+
For missing checks, dispatch one gap-fill invocation per reviewer on that reviewer's original slot, carrying only its incomplete grouped cells, their shared catalog entries, the same range and rule paths. Ask for one complete row for each such cell, not separate replies per missing rule. Use a new invocation ID and repeat the full materialize → verify → dispatch → materialize-result → complete → verify-completion boundary. Re-run the audit with that reviewer's initial and gap-fill markers. Earlier usable verdicts remain unchanged. An invocation with unknown IDs is invalid; record its rejection and request a corrected new invocation before auditing the retained valid completions. Do not silently relabel IDs.
|
|
186
197
|
|
|
187
|
-
A
|
|
198
|
+
The Checked/N/A/Findings fields must account for every expected rule ID exactly once; a generic clean or all-checked statement never covers an omitted rule. Do not start Step 3.6 until every reviewer passes the audit. If evidence remains unavailable, report the specific blocker and incomplete coverage instead of writing a completed review.
|
|
188
199
|
|
|
189
200
|
## Step 3.6 — Check every citation
|
|
190
201
|
|
|
@@ -198,19 +209,19 @@ okstra code-review check-lines --project-root <projectRoot> --base <baseCommit>
|
|
|
198
209
|
|
|
199
210
|
## Step 3.7 — Settle the findings
|
|
200
211
|
|
|
201
|
-
Reviewers are wrong in a way a census cannot catch: a claim about code they did not open. What you settle depends on the reviewer count.
|
|
212
|
+
Reviewers are wrong in a way a census cannot catch: a claim about code they did not open. What you settle depends on the reviewer count. Before pairing findings, check every finding, including agreed ones, against its `kind`: an `execution-error` needs an evidenced reachable `failure`; a `design-violation` needs an applicable named rule, code evidence, and concrete `impact`. Both need a fix. Missing or unsupported required evidence goes to `Rejected` with the specific reason; do not demand a runtime failure for a design violation.
|
|
202
213
|
|
|
203
214
|
**Two reviewers.** Pair the findings first: two findings are the same finding when they cite the same `path:line` and describe the same defect. Then:
|
|
204
215
|
|
|
205
|
-
- **Agreed** — both reviewers report it with the same severity and timing. It
|
|
216
|
+
- **Agreed** — both reviewers report it with the same severity and timing. It keeps its severity and timing after the evidence and kind checks above; agreement does not replace those checks.
|
|
206
217
|
- **Graded differently** — both report it, with a different severity or timing. Pick one of the two values after reading the code, and record both values and your reason in the finding. Never pick a third value.
|
|
207
218
|
- **One-sided** — one reviewer reports it and the other returned `clean` for that cell or reported something else. Adjudicate it as below.
|
|
208
219
|
|
|
209
220
|
**One reviewer.** Adjudicate every finding it returns.
|
|
210
221
|
|
|
211
|
-
**Adjudicating** a finding: open each `evidence` location at `headCommit
|
|
222
|
+
**Adjudicating** a finding: open each `evidence` location at `headCommit` and the definitions its claim depends on. For `execution-error`, check reachability and the stated wrong result. For `design-violation`, read the assigned rule and check the cited violation and concrete `impact`. An axis does not determine the kind.
|
|
212
223
|
|
|
213
|
-
- **Confirmed** — the code
|
|
224
|
+
- **Confirmed** — the code supports the execution failure or the applicable design violation and its impact. The finding keeps its severity and timing.
|
|
214
225
|
- **Rejected** — the code contradicts the claim (the called function never reads `this`, the value cannot be null there, the branch is unreachable). Move it to `Rejected` with the contradicting `path:line` and one sentence on what it shows.
|
|
215
226
|
|
|
216
227
|
Rejecting is a statement about the code, so it always carries a `path:line`. Never reject for being unconvinced. Apart from choosing between two reviewers' values, never promote, demote, or re-time a finding. Confirmed and agreed `park` findings go to `Parked`, unscored.
|
|
@@ -257,5 +268,5 @@ generatedAt: <YYYY-MM-DD HH:MM>
|
|
|
257
268
|
- **No finding without a fix.** Readability findings carry a pseudocode sketch; naming findings carry a concrete alternative name.
|
|
258
269
|
- **The census is law.** A reviewer that rebuilds its own worklist reintroduces exactly the run-to-run variance this skill exists to kill.
|
|
259
270
|
- **Every cell gets a verdict.** `clean` is a result, not an omission; the audit treats a gap as unfinished work.
|
|
260
|
-
- **Only a checked claim scores.** A finding reaches the score after its citation is on a changed line and its
|
|
271
|
+
- **Only a checked claim scores.** A finding reaches the score after its citation is on a changed line and its kind-specific evidence holds against the code; everything else is `Parked` or `Rejected`, with its reason.
|
|
261
272
|
- **The report prose follows `Report language`.** Paths, identifiers, rule names, and quoted code stay verbatim.
|
|
@@ -8,13 +8,48 @@ The census is the worklist: an explicit list of cells, each one a `target × axi
|
|
|
8
8
|
|
|
9
9
|
This is what makes the cell count reproducible: the axis list is fixed at four, so the census size depends only on the diff. Splitting an axis per individual rule would make the count depend on how many rules the reader chose to enumerate that day — the exact variance this census exists to remove.
|
|
10
10
|
|
|
11
|
-
The specific rule a finding violates is named **inside the verdict**, in its `rule` field (`review-calibration.md`), not in the cell label. One cell can therefore carry findings from several rules of its group, and it still counts as one cell
|
|
11
|
+
The specific rule a finding violates is named **inside the verdict**, in its `rule` field (`review-calibration.md`), not in the cell label. One cell can therefore carry findings from several rules of its group, and it still counts as one cell. Rule coverage is represented inside each grouped verdict below.
|
|
12
|
+
|
|
13
|
+
## Shared rule catalog and grouped cells
|
|
14
|
+
|
|
15
|
+
Keep one cell per target and axis. Each reviewer returns one compact row per cell, not one prose verdict per pack bullet. Define the shared rule catalog once, then let cells reference its group. Do not materialize a target-by-bullet Cartesian product.
|
|
16
|
+
|
|
17
|
+
Use these named review criteria. Each criterion includes the relevant subconditions and carve-outs in its canonical pack; those bullets do not get separate verdict IDs:
|
|
18
|
+
|
|
19
|
+
| Group | Rule IDs and scope |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `structural` | `S1` reuse/DRY; `S2` simplicity/KISS; `S3` responsibilities/SOLID; `S4` current scope/YAGNI; when an architecture pack is routed: `S5` thin ports, `S6` I/O-only adapters, `S7` domain-object placement, `S8` dependency direction, `S9` boundary ports, `S10` domain-owned business rules |
|
|
22
|
+
| `semantic` | `M1` truthful and specific names; `M2` single-purpose readable flow, including size and nesting; `M3` comments and explanatory values |
|
|
23
|
+
| `state-and-tests` | `T1` state and mutation boundaries; `T2` no self-mocking; `T3` behavioral outcome assertions; `T4` discriminating fixtures, test titles and branch coverage |
|
|
24
|
+
| `general` | `G1` correctness and regressions; `G2` error handling and third-party wrappers; `G3` untrusted-input and resource bounds; `G4` performance; `G5` routed language/framework and project conventions |
|
|
25
|
+
|
|
26
|
+
Write the selected IDs with their absolute pack/section references under `## Rules`. Multiple references for a criterion go in the same Reference field, separated by semicolons. Do not turn every heading, bullet, formatter instruction or example into another rule. Read the original references rather than restating their bodies.
|
|
27
|
+
|
|
28
|
+
Write targets under `## Cells`; each has a stable `C-CR-...` ID, the target and its group. A function target includes its path and position, e.g. `src/orders/pricing.py:42 calculate_price`. Distinguish same-line anonymous functions with their columns. Targets are repository-relative; no absolute or parent-traversal paths.
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
## Rules
|
|
32
|
+
| Rule | Group | Reference |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| S1 | structural | /absolute/pack/clean-code.md#DRY |
|
|
35
|
+
| S2 | structural | /absolute/pack/clean-code.md#KISS |
|
|
36
|
+
|
|
37
|
+
## Cells
|
|
38
|
+
| Cell | Target | Group |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| C-CR-0001 | src/orders/pricing.py | structural |
|
|
41
|
+
| C-CR-0002 | src/orders/totals.py | structural |
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The example is abbreviated; the actual catalog includes the named criteria above for every used group. Add `S5` through `S10` only for a routed architecture pack; otherwise the base catalog has 16 criteria. Freeze the catalog and cell IDs before dispatch and send the same census to each reviewer. The command `code-review check-coverage` enforces catalog membership, rule accounting and source-anchor validity against this saved census; the lead still checks that the catalog names the intended references and that verdicts are true.
|
|
45
|
+
|
|
46
|
+
Do not omit a cell because a rule seems inapplicable. Record that criterion under `N/A` with its reason in the compact row. The normal case lists checked rule IDs once with one inspected source anchor for the cell. This preserves rule-level omission checks without repeating paths and explanations for every rule.
|
|
12
47
|
|
|
13
48
|
## The one principle
|
|
14
49
|
|
|
15
50
|
**Membership is mechanical; judgment only ever decides a cell's verdict.**
|
|
16
51
|
|
|
17
|
-
Never ask "does this rule apply to this file?" while building the census — that question is the reviewer's, and its answer is a verdict (`
|
|
52
|
+
Never ask "does this rule apply to this file?" while building the census — that question is the reviewer's, and its answer is a verdict (`n/a` with a reason when the rule turns out not to apply). Over-inclusion is cheap: a clean verdict costs one line. A judged exclusion is variance — it is the exact failure this census exists to remove, because the next run judges differently and the review changes shape.
|
|
18
53
|
|
|
19
54
|
Two consequences:
|
|
20
55
|
|
|
@@ -94,6 +129,7 @@ In the orchestrator's response, before Step 3:
|
|
|
94
129
|
|
|
95
130
|
- one table per axis, in the order `structural`, `semantic`, `state-and-tests`, `general`, listing every cell
|
|
96
131
|
- the exclusion list, one line per file, each with its reason
|
|
132
|
+
- the shared rule catalog, grouped cell table and total cells per axis
|
|
97
133
|
- the applied pack list (absolute paths)
|
|
98
134
|
- the two completion criteria with their actual numbers
|
|
99
135
|
|