@shahboura/harness 3.0.4

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.
Files changed (62) hide show
  1. package/.opencode/agents/developer.md +60 -0
  2. package/.opencode/agents/planner.md +51 -0
  3. package/.opencode/agents/reviewer.md +53 -0
  4. package/.opencode/commands/add-repo.md +26 -0
  5. package/.opencode/commands/dev-workflow.md +40 -0
  6. package/.opencode/commands/init-workspace.md +22 -0
  7. package/.opencode/commands/migrate-workspace.md +28 -0
  8. package/.opencode/commands/repo-map-refresh.md +23 -0
  9. package/.opencode/commands/story-workflow.md +24 -0
  10. package/.opencode/commands/workflow-status.md +23 -0
  11. package/.opencode/commands/workspace-config.md +27 -0
  12. package/.opencode/package.json +9 -0
  13. package/.opencode/plugins/harness-guards.ts +290 -0
  14. package/.opencode/skills/add-repo/SKILL.md +96 -0
  15. package/.opencode/skills/dev-workflow/SKILL.md +105 -0
  16. package/.opencode/skills/dev-workflow/shared/diagram-styling.md +65 -0
  17. package/.opencode/skills/dev-workflow/shared/engineering.md +14 -0
  18. package/.opencode/skills/dev-workflow/shared/status-block.md +29 -0
  19. package/.opencode/skills/dev-workflow/steps/analyze-comments.md +32 -0
  20. package/.opencode/skills/dev-workflow/steps/apply-fixes.md +24 -0
  21. package/.opencode/skills/dev-workflow/steps/comment-analysis.md +11 -0
  22. package/.opencode/skills/dev-workflow/steps/create-pr.md +39 -0
  23. package/.opencode/skills/dev-workflow/steps/develop-task.md +54 -0
  24. package/.opencode/skills/dev-workflow/steps/develop.md +60 -0
  25. package/.opencode/skills/dev-workflow/steps/fetch.md +34 -0
  26. package/.opencode/skills/dev-workflow/steps/fixup-task.md +12 -0
  27. package/.opencode/skills/dev-workflow/steps/gate.md +53 -0
  28. package/.opencode/skills/dev-workflow/steps/harden-task.md +12 -0
  29. package/.opencode/skills/dev-workflow/steps/harden.md +30 -0
  30. package/.opencode/skills/dev-workflow/steps/intake.md +52 -0
  31. package/.opencode/skills/dev-workflow/steps/metrics.md +21 -0
  32. package/.opencode/skills/dev-workflow/steps/plan-task.md +108 -0
  33. package/.opencode/skills/dev-workflow/steps/plan.md +80 -0
  34. package/.opencode/skills/dev-workflow/steps/pre-pr-fixes.md +16 -0
  35. package/.opencode/skills/dev-workflow/steps/pre-pr-review.md +14 -0
  36. package/.opencode/skills/dev-workflow/steps/pre-pr.md +14 -0
  37. package/.opencode/skills/dev-workflow/steps/preflight.md +32 -0
  38. package/.opencode/skills/dev-workflow/steps/quick-recheck.md +14 -0
  39. package/.opencode/skills/dev-workflow/steps/reconcile.md +27 -0
  40. package/.opencode/skills/dev-workflow/steps/review-task.md +32 -0
  41. package/.opencode/skills/dev-workflow/steps/security.md +18 -0
  42. package/.opencode/skills/dev-workflow/steps/triage-request.md +15 -0
  43. package/.opencode/skills/init-workspace/SKILL.md +155 -0
  44. package/.opencode/skills/migrate-workspace/SKILL.md +122 -0
  45. package/.opencode/skills/repo-map-refresh/SKILL.md +43 -0
  46. package/.opencode/skills/story-workflow/SKILL.md +78 -0
  47. package/.opencode/skills/story-workflow/commands/analyze.md +40 -0
  48. package/.opencode/skills/story-workflow/commands/groom.md +58 -0
  49. package/.opencode/skills/story-workflow/commands/improve.md +47 -0
  50. package/.opencode/skills/story-workflow/commands/refine.md +44 -0
  51. package/.opencode/skills/story-workflow/shared/context.md +22 -0
  52. package/.opencode/skills/story-workflow/shared/provider-io.md +73 -0
  53. package/.opencode/skills/story-workflow/templates/readiness-report.md +57 -0
  54. package/.opencode/skills/story-workflow/templates/story-template.md +51 -0
  55. package/.opencode/skills/story-workflow/templates/technical-notes.md +48 -0
  56. package/.opencode/skills/workflow-status/SKILL.md +30 -0
  57. package/.opencode/skills/workspace-config/SKILL.md +97 -0
  58. package/.opencode/tsconfig.json +11 -0
  59. package/CHANGELOG.md +396 -0
  60. package/LICENSE +21 -0
  61. package/README.md +351 -0
  62. package/package.json +32 -0
@@ -0,0 +1,12 @@
1
+ # Instruction: hardening tests (developer shape, mode `harden`)
2
+
3
+ You are topping up coverage on code that already exists — tests must be
4
+ meaningful, not gaming:
5
+
6
+ - **Assertion depth (review-policy `assertion-depth`):** assert the full
7
+ observable contract — response body shape, error envelope, side effects.
8
+ Status-code-only or not-throws-only assertions are incomplete.
9
+ - Target the diff-coverage gaps you were given, not incidental old code.
10
+ - Never modify implementation code in this mode — tests only.
11
+ - Commit via `bin/harness commit --commit-class working`; report via the status
12
+ block with the coverage delta you achieved.
@@ -0,0 +1,30 @@
1
+ # Step: harden (developer shape, mode `harden`)
2
+
3
+ Coverage top-up after ⟨approve-impl⟩ — tests here are green-from-birth
4
+ (they cover code that already exists), so NO red-proof machinery applies.
5
+
6
+ 1. Resolve the coverage command: `bin/harness
7
+ resolve-coverage-cmd --repo <repo>` (per repo, `language.repos.<repo-
8
+ name>.coverage_cmd` — `discover` proposes one at `/init-workspace` time
9
+ where repo evidence supports it: python/go conventions, a node
10
+ `coverage` script or jest/vitest+provider, jacoco in a java pom). Null
11
+ means unconfigured — ask the user, never improvise a command. Their
12
+ answer is either a command (write it to
13
+ `language.repos.<name>.coverage_cmd` the `/workspace-config` way, then
14
+ re-resolve) or an explicit skip — record that with
15
+ `bin/harness log-event --json '{"kind":
16
+ "coverage-skipped", "repo": "<name>", "reason": "<their words>"}'` and
17
+ harden that repo from the tasks' own test gaps instead. Run the resolved command to find diff-coverage gaps against
18
+ the tasks' touched files.
19
+ 2. Spawn `developer` with `harness-mode: harden` (+ run/repo/test-cmd
20
+ headers — test-cmd is per repo, same `language.repos.<repo-name>.test_cmd`
21
+ convention as `develop`) and the gap list. It follows `steps/harden-task.md`.
22
+ 3. Spawn `reviewer` (`harness-mode: review`) on the new tests.
23
+ 4. The DEVELOPER already committed its tests (harden-task.md's own
24
+ commit step — do not commit again from here; a second commit in
25
+ the same repo either fails on "nothing to commit" or sweeps unrelated
26
+ files via `git add -A`). Produce `<run>/reports/coverage.md`
27
+ summarizing before/after coverage and record the declared artifact:
28
+ `bin/harness artifact --name coverage-report
29
+ --value reports/coverage.md --run <run>`.
30
+ 5. Advance: `bin/harness cursor --to security --run <run>`.
@@ -0,0 +1,52 @@
1
+ # Step: intake (planner shape)
2
+
3
+ Spawn the planner to turn the normalized work item into a requirements
4
+ summary. It reads `<run>/work-item.json` — it has no provider access.
5
+
6
+ Spawn `planner` with prompt headers:
7
+
8
+ ```
9
+ harness-mode: intake
10
+ harness-run: <run>
11
+ harness-repo: <primary-repo-path>
12
+ ```
13
+
14
+ …plus the ask: read `work-item.json` (+ the repo-map at
15
+ `.claude/context/repo-map/<repo-name>/` if present — index first, then
16
+ only the area files the work item touches), produce
17
+ `<run>/requirements.md` — restated requirements, acceptance criteria,
18
+ ambiguities/clarifying questions for the human.
19
+
20
+ The repo-map is generated at `/init-workspace` and its freshness is
21
+ (re)checked and stamped at **plan step 0** (the single owner). Here, just
22
+ READ what's present — do NOT generate it, run `repo-map-check`, or stamp
23
+ `.meta.json`; a missing or stale map is plan's job to refresh, not
24
+ intake's. (If it's absent, intake still proceeds on `work-item.json`
25
+ alone.) Don't investigate its status — plan handles it.
26
+
27
+ If the status block reports clarifying questions, surface them to the user
28
+ and relay answers (append to `requirements.md` via a re-spawn if substantial).
29
+ When surfacing them, **separate the two kinds** rather than presenting one
30
+ undifferentiated list:
31
+
32
+ - **confirm-a-default** — a question with a safe, stated default (you can
33
+ proceed if the human doesn't object). Batch these together and present the
34
+ default you'll take; a non-answer resolves cleanly.
35
+ - **resolve-a-real-fork** — a genuine either/or with no grounded default
36
+ (both branches are live). Present each on its own and wait for an explicit
37
+ pick; never bundle one of these behind a default, and never imply a fork is
38
+ settled when it isn't.
39
+
40
+ Mixing the two produces partial-answer states (the human ratifies the easy
41
+ defaults and the real fork silently rides along unanswered).
42
+
43
+ Note the run's seeded task list (`T1`) is a **provisional placeholder** —
44
+ fetch's positional default (`repos[0]`), flagged `provisional: true` in
45
+ state, not a scope decision. Do not present it to the human as one; the real
46
+ task list is set at plan-register and replaces it wholesale.
47
+
48
+ Record the declared artifact once requirements.md is final:
49
+ `bin/harness artifact --name requirements-summary
50
+ --value requirements.md --run <run>`.
51
+
52
+ Then advance: `bin/harness cursor --to plan --run <run>`.
@@ -0,0 +1,21 @@
1
+ # Step: metrics (orchestrator-owned, fully mechanical)
2
+
3
+ ```
4
+ bin/harness metrics --run <run>
5
+ ```
6
+
7
+ Deterministic aggregation — timings from state, tokens from the ledger,
8
+ flagged events — into `<run>/reports/metrics.md`. No agent reasoning. Show
9
+ the user the summary. Final mirror **once per preflighted repo** (SKILL.md's
10
+ Publish rule — never the workspace), `--push` required so this closing
11
+ snapshot (metrics report included) actually reaches each PR's remote
12
+ branch instead of stranding locally:
13
+ `bin/harness publish-mirror --repo <preflighted-repo-path> --push --run <run>`.
14
+ Then declare the run finished — the successful sibling of abort, terminal
15
+ by declaration (mutations refuse from here on; the audit trail stays):
16
+
17
+ ```
18
+ bin/harness complete --run <run>
19
+ ```
20
+
21
+ The run is done.
@@ -0,0 +1,108 @@
1
+ # Instruction: produce the plan (planner shape, mode `plan`)
2
+
3
+ Produce `<run>/plan.md`: the human-facing design for this story. Both
4
+ altitudes of approach decision below are approved at the single
5
+ `approve-plan` gate (design.md:495 — one gate, two altitudes).
6
+
7
+ ## 0. Ground in the repo map
8
+
9
+ Before decomposing, read the auto-generated map at
10
+ `.claude/context/repo-map/<repo-name>/` for each repo the story touches —
11
+ the index first, then only the area detail files this story is likely to
12
+ touch (each is loadable standalone; never load the whole map). This is
13
+ where "the team uses <pattern>" comes from — cite it instead of
14
+ re-deriving the codebase. Two boundaries: the map speeds targeting, it
15
+ never replaces reading the real code for areas you plan to change; and its
16
+ freshness was already settled by the orchestrator before your spawn — READ
17
+ what's there, never run `repo-map-check`/`repo-map-stamp` or write
18
+ `.meta.json`. A missing map is not a blocker: proceed on code reading
19
+ alone and note the absence in your self-adversarial pass.
20
+
21
+ ## 1. Decomposition
22
+
23
+ Tasks keyed by id (`T1`, `T2`…), each with: description, repo, edge-case
24
+ enumeration, risk tier, dependencies. One task = one reviewable unit.
25
+
26
+ **`depends_on` is HARD technical blockers ONLY — it is mechanically
27
+ enforced and gates cross-repo parallelism.** A task can't start until every
28
+ task it `depends_on` is done (the `dependencies-done` guard refuses), and
29
+ you can't loosen the graph past the plan gate (registration is plan-step-
30
+ only) — so an over-declared edge permanently *serializes work that could
31
+ run concurrently*. Declare an edge only when B literally cannot begin until
32
+ A completes (B compiles against a symbol A introduces, B's tests need code
33
+ A writes first, B mutates state A sets up). Do NOT encode as `depends_on`:
34
+ a cross-repo consumer whose contract is already ratified in
35
+ `requirements.md` (it doesn't depend on the producer's *implementation* —
36
+ build it in parallel against the fixed contract, stub the response; the
37
+ **ratified contract is the sync point, model it as a Cross-repo contract
38
+ below, not an edge** — e.g. a frontend task consuming a ratified backend
39
+ API is `depends_on: []`, not `[<backend tasks>]`); or mere merge/read order.
40
+ If your self-adversarial pass flags an edge as "soft / for clarity / not a
41
+ hard blocker," **remove it** (note sequencing in prose if useful) — the
42
+ enforced graph doesn't read your annotation. Keep the dependency diagram
43
+ faithful to the hard edges only: the graph the human approves is the one
44
+ that runs.
45
+
46
+ ## 2. Solution Approaches (top-level altitude — only when a fork exists)
47
+
48
+ When a genuine architectural fork exists for the **whole story** (not a
49
+ per-task implementation detail), write a `## Solution Approaches` section:
50
+ 2–3 whole-solution options (name, summary, trade-offs) + a recommendation.
51
+ **Skip this section when no real fork exists** — a single obvious approach
52
+ forces no filler comparison; over-triggering is worse than omitting it. Skip
53
+ silently, though, and the human at the gate can't tell "no fork" from
54
+ "missed one" — so when you skip it, add one line instead: `No architectural
55
+ fork identified: <why>` under the task table, visible either way.
56
+
57
+ ## 3. Per-task detail
58
+
59
+ - **Test-intents**: named tests + one-line intent each, per task, as a
60
+ literal block under that task's section:
61
+ ```
62
+ Test-intents:
63
+ - test_name_one — one-line intent
64
+ - test_name_two — one-line intent
65
+ ```
66
+ Name each test exactly as the developer should write it (function/method
67
+ name) — `verify-red` mechanically checks these literal names appear in
68
+ the actual test files (coverage B1); the orchestrator carries the name
69
+ list, not the intent prose, into `plan-register`'s `test_intents` field.
70
+ - **`[API: <lib> v<X>]`** annotations where a task prescribes a library API
71
+ — the developer verifies the real signature before writing call sites.
72
+ - **≤2 pattern hints** per task: existing test files via bounded globbing
73
+ (≤5 globs), ranked by mtime, filename match only (no reading contents).
74
+ "No match" is a valid answer — don't widen the search.
75
+ - **Per-task approach options** where a single task (not the whole story)
76
+ has more than one reasonable implementation — distinct from the
77
+ story-level altitude in step 2.
78
+ - **Cross-repo contracts**, multi-repo stories only: name the producer repo,
79
+ consumer repo(s), and signature fragment(s) for anything one repo's task
80
+ emits and another's depends on — the enriched shape in `steps/plan.md`'s
81
+ registration example.
82
+
83
+ ## 4. Diagrams
84
+
85
+ Four Mermaid diagrams, styled per `shared/diagram-styling.md`:
86
+
87
+ 1. **Class/type diagram** (`classDiagram`) — new/modified types,
88
+ relationships, key methods. Mark scope with `:::new` / `:::modified` on a
89
+ dedicated `class <Name>:::<style>` statement — NOT on a relationship
90
+ endpoint or bare reference (classDiagram grammar rejects those; see
91
+ `shared/diagram-styling.md`).
92
+ 2. **Runtime flowchart** (`flowchart TD`) — the feature's runtime flow,
93
+ decision points, external interactions, error paths.
94
+ 3. **Sequence diagram** (`sequenceDiagram`, `autonumber`) — actor
95
+ interactions, call order, sync vs async, key payloads.
96
+ 4. **Task dependency graph** (`flowchart LR`) — one node per task id, edges
97
+ from `depends_on`. Required for every story, even single-task ones.
98
+
99
+ ## 5. Self-adversarial pass
100
+
101
+ Before finalizing: list ambiguities, risks, and unchecked assumptions in the
102
+ draft. Revise or flag them — don't ship a plan you haven't tried to break.
103
+
104
+ ## 6. Register + advance
105
+
106
+ Mechanics (the `plan-register` call, gate advance) live in
107
+ `steps/plan.md` — this file is the content contract, that file is the
108
+ registration procedure. Don't duplicate one into the other.
@@ -0,0 +1,80 @@
1
+ # Step: plan (planner shape)
2
+
3
+ 0. **Repo-map freshness — this step is its SINGLE owner.** The repo-map is
4
+ first generated at `/init-workspace`; nothing between there and here
5
+ touches it (intake only reads it), so this is the one place in the
6
+ pipeline that confirms it's current. Its status is filesystem-only
7
+ (`.claude/context/repo-map/<name>/.meta.json`) — not in `state.yaml`, so
8
+ the `show` verb won't surface it; check it explicitly, per registered
9
+ repo:
10
+ `bin/harness repo-map-check --repo-name <name>
11
+ --repo <path>`.
12
+ - `fresh` → nothing to do (init already generated + stamped it; do NOT
13
+ re-stamp).
14
+ - `missing`/`stale` → regenerate (spawn `planner` with
15
+ `harness-mode: repo-map`, a declared out-of-run-legal pair) and stamp
16
+ via `bin/harness repo-map-stamp` after it
17
+ returns — a plan grounded in a stale map cites patterns that no longer
18
+ exist.
19
+ 0b. **Re-entering plan** (gate rejection / approved mid-run amendment)?
20
+ Snapshot the current plan first — copy `<run>/plan.md` to
21
+ `<run>/plan-r<n>.md` — so the previously-approved text stays
22
+ recoverable. Never rewrite it silently.
23
+
24
+ Spawn `planner` with headers (`harness-mode: plan`, `harness-run`,
25
+ `harness-repo`) to produce `<run>/plan.md`. It follows `steps/plan-task.md`
26
+ (the content contract). The plan's REQUIRED content (coverage decisions
27
+ B1/B2/B7/B8 — the gate presents all of it):
28
+
29
+ - Tasks keyed by id (`T1`, `T2`…), each with: description, repo, edge-case
30
+ enumeration, risk tier, dependencies.
31
+ - **Per-task test-intents** (named tests + one-line intent each) — approved
32
+ at the plan gate; carry the NAMES (not the intent prose) into
33
+ `plan-register`'s `test_intents` field per task — `verify-red` mechanically
34
+ checks each declared name is written, no re-declaration needed later.
35
+ - **Approach options, two altitudes**: a top-level `## Solution Approaches`
36
+ section (2–3 whole-solution options + recommendation) only when a genuine
37
+ architectural fork exists, distinct from per-task options — both approved
38
+ at this one gate. Skipped → one line saying why, never silent.
39
+ - `[API: <lib> v<X>]` annotations where a task prescribes a library API.
40
+ - ≤2 existing-test-file **pattern hints** per task (bounded discovery).
41
+ - **Four diagrams** — class/type, runtime flowchart, sequence, task
42
+ dependency graph — per `shared/diagram-styling.md` (full spec in
43
+ `steps/plan-task.md`).
44
+ - A **self-adversarial pass**: ambiguities, risks, unchecked assumptions.
45
+
46
+ When the planner's status block reports the plan ready:
47
+
48
+ 1. Register the tasks it declared (replaces the single fetch-seeded task):
49
+ `bin/harness plan-register --run <run> --tasks-json
50
+ '[{"id":"T1","repo":"<path>","risk":"low","test_intents":["test_name_one",
51
+ "test_name_two"]}, …]'` — `repo` must be the exact path string from this
52
+ workspace's `repos.yaml` (i.e. `config["repos"]`'s VALUE, e.g.
53
+ `/abs/path/to/backend`), never the short registered NAME (`backend`) —
54
+ a name instead of a path resolves to no registered repo and fails
55
+ silently until a later step (`verify-red`/task completion) reports a
56
+ confusing "no test command" error instead of a clear one here.
57
+ `risk` is free-form (defaults to `low` if omitted) — no enum is
58
+ enforced, but use `low`/`medium`/`high` for consistency with what the
59
+ plan itself declares. (`test_intents` is the plan's declared test
60
+ NAMES for that task, empty if none) — declare cross-repo contracts too if
61
+ the plan named any: `--contracts-json '[{"id":"C1","type":"http",
62
+ "producer":"a","consumers":["b"],"signature":["POST /v2/items",
63
+ "field: item_id"]}]'` (`type` is `http | service-bus | dto`, descriptive
64
+ only; `signature` is one string or a list of fragments, and **each must be
65
+ a grep-able code token/signature that appears verbatim in source** —
66
+ `archived`, `filter_notes(notes, tag)`, `POST /v2/items` — NOT an English
67
+ description: reconcile-contracts matches by literal source search, so a
68
+ prose fragment is rejected at plan-register and would false-report drift.
69
+ All fragments must be present; the flat legacy `"repos":["a","b"]` form
70
+ still works in place of `producer`/`consumers`. Legal only at cursor `plan`.
71
+ 2. Check the diagrams: `bin/harness validate-mermaid
72
+ --file <run>/plan.md`. A non-zero exit names structural rule violations
73
+ (`failures` in the JSON) — send the planner back to fix them, never
74
+ advance past a failure. Purely structural (well-formed Mermaid that
75
+ exists); it doesn't check the four diagrams are actually present — that
76
+ stays plan-task.md's content-contract job.
77
+ 3. Record the declared artifact: `bin/harness
78
+ artifact --name plan --value plan.md --run <run>` (the gate presents it
79
+ by this name).
80
+ 4. Advance to the gate: `bin/harness cursor --to approve-plan --run <run>`.
@@ -0,0 +1,16 @@
1
+ # Step: pre-pr-fixes (developer shape, mode `fixup`; reached on gate rejection)
2
+
3
+ Task commits are already squashed — fixes need the fixup path (never new
4
+ loose commits, never history edits by hand):
5
+
6
+ 1. Spawn `developer` with `harness-mode: fixup` + the gate's findings.
7
+ It follows `steps/fixup-task.md`.
8
+ 2. After its fixup commits land:
9
+ `bin/harness merge-task --repo <repo> --autosquash --base <default-branch>
10
+ --run <run>` — folds them into their task commits and re-derives the
11
+ tracker SHAs.
12
+ 3. Record the declared artifact: `bin/harness
13
+ artifact --name fixup-commits --value "<findings addressed> @ <new HEAD
14
+ sha>" --run <run>`.
15
+ 4. Return via the declared edge: `bin/harness cursor --to pre-pr --run <run>`
16
+ (the pre-PR review re-runs on the corrected branch).
@@ -0,0 +1,14 @@
1
+ # Instruction: holistic pre-PR review (reviewer shape, mode `pre-pr`)
2
+
3
+ Review the ENTIRE feature branch (all squashed task commits) as one change:
4
+
5
+ - Re-run build + full test suite yourself — never trust reported results.
6
+ - Check each review-policy rule from config (assertion-depth,
7
+ patch-dto-wrapper, team rules) and cite violations by file:line.
8
+ - Check plan-vs-implementation drift: does what shipped match what was
9
+ approved? Are the declared test-intents all realized?
10
+ - Hunt the TDD residuals: semantically-empty tests (red for the wrong
11
+ reason), impl overfit to the test, weakened shared fixtures.
12
+ - Findings numbered `[R<n>]` with severity CRITICAL | WARNING | SUGGESTION.
13
+ - Deliver the full report text in your status block `details` (the
14
+ orchestrator persists it — you cannot write files).
@@ -0,0 +1,14 @@
1
+ # Step: pre-pr (reviewer shape, mode `pre-pr`)
2
+
3
+ 1. Multi-repo runs first: `bin/harness reconcile-contracts --run <run>` — drift
4
+ goes in front of the human at the gate, never auto-fixed.
5
+ 2. Spawn `reviewer` with `harness-mode: pre-pr` (+ run/repo headers): a
6
+ holistic review of the full feature branch — cohesion across tasks,
7
+ review-policy rules, plan-vs-implementation drift, the residuals the TDD
8
+ lock can't catch (semantically-empty tests, impl-overfit).
9
+ 3. The reviewer is read-only: it reports the review in its status block; YOU
10
+ persist it to `<run>/reports/pre-pr.md` verbatim and record the declared
11
+ artifact: `bin/harness artifact --name pre-pr-report
12
+ --value reports/pre-pr.md --run <run>`.
13
+ 4. Advance to ⟨approve-pre-pr⟩ (`gate.md`); present the report AND the
14
+ contracts verdict. Rejection routes to `pre-pr-fixes` (declared edge).
@@ -0,0 +1,32 @@
1
+ # Step: preflight (orchestrator-owned, fully mechanical)
2
+
3
+ Create the feature branch in each affected repo from the declared naming
4
+ template — one owned command per repo:
5
+
6
+ ```
7
+ bin/harness preflight --repo <repo-path> --run <run>
8
+ ```
9
+
10
+ First ensures the repo is clean and on its default branch (the reusable
11
+ precondition `discover` also uses at `/init-workspace` time, standalone as
12
+ `bin/harness ensure-default-branch --repo <repo-path>
13
+ [--branch <name>]` for any future step that needs it) — a dirty repo, or
14
+ one mid-rebase/merge, refuses
15
+ (surface to the human, never auto-stash/discard/continue); a clean repo on
16
+ a different branch is switched, no confirmation needed. Pass `--branch
17
+ <name>` to override the auto-resolved guess. Idempotent on retry, per
18
+ repo: a `branches` entry already recorded for *this* repo is returned
19
+ directly rather than re-derived — a second repo's preflight is never
20
+ satisfied by the first repo's record (each repo gets its own entry). **Known risk:** two runs started concurrently
21
+ against the *same* repo path can race here (no repo-level lock exists yet)
22
+ — use a separate clone/checkout per concurrent run against the same repo.
23
+ Then it renders `naming.branch` (`{type}/{id}-{slug}`) from state, creates
24
+ the branch, and records the `branches` artifact. It also pins
25
+ `.harness-key` into the repo's `.git/info/exclude` (shared with its task
26
+ worktrees), so a stray integrity key can never be swept into git history
27
+ by the commit verbs' `git add -A`; the commit verbs refuse-and-unstage as
28
+ backstop. Then:
29
+
30
+ ```
31
+ bin/harness cursor --to develop --run <run>
32
+ ```
@@ -0,0 +1,14 @@
1
+ # Step: quick-recheck (orchestrator-owned; quick mode only)
2
+
3
+ The ex-ante classifier saw only work-item text; this step checks the REAL
4
+ diff against the declared disqualify patterns:
5
+
6
+ ```
7
+ bin/harness quick-recheck --repo <repo> --base <default-branch> --run <run>
8
+ ```
9
+
10
+ - `clean` → advance to `pre-pr`.
11
+ - `dirty` → the escalation edge is MANDATORY: `pre-pr` is now illegal;
12
+ advance to `security` (`bin/harness cursor --to security`) — the run switches
13
+ to full mode and continues from there. Tell the user why (the hits are in
14
+ the events ledger).
@@ -0,0 +1,27 @@
1
+ # Step: reconcile (orchestrator-owned, fully mechanical)
2
+
3
+ ## MCP-transport work-item providers (ado-mcp / jira / zoho)
4
+
5
+ A script can't call an MCP tool, so plain `bin/harness reconcile` would try to
6
+ dispatch `work_item.transition` itself and refuse every time write-back is on
7
+ (the default). Run the transition in the orchestrator instead, same pattern
8
+ as `fetch.md`:
9
+
10
+ 1. If `write_back.on_done` (or the milestone in play) is enabled, invoke the
11
+ mapped `work_item.transition` tool (`bin/harness
12
+ provider --op work_item.transition --id <id> --to <status>` prints the
13
+ exact tool + args to call).
14
+ 2. Then run reconcile with the transition skipped (already done above):
15
+ ```
16
+ bin/harness reconcile --skip-transition --run <run>
17
+ ```
18
+
19
+ ## CLI-transport providers (github / gitlab / ado / local-markdown)
20
+
21
+ ```
22
+ bin/harness reconcile --run <run>
23
+ ```
24
+
25
+ Provider status write-back (conservative default: done), archives completed
26
+ tasks (declared FSM edge), sweeps leftover worktrees. Then advance to
27
+ `metrics`.
@@ -0,0 +1,32 @@
1
+ # Instruction: per-task review (reviewer shape, mode `review`)
2
+
3
+ Review ONE task's diff (its worktree branch vs the feature branch), inside
4
+ the develop loop:
5
+
6
+ - Re-run the task's tests yourself (`harness-test-cmd`) — independent
7
+ verification, never trust the developer's claim. Long output? Capture it
8
+ under /tmp (`… 2>&1 | tee /tmp/review.log`) — /tmp and /dev/null are
9
+ your only legal write targets; any other shell write is blocked. Spell
10
+ the path LITERALLY: a variable-held target (`$SCRATCH/x`, `$(mktemp -d)`)
11
+ can't be verified by the guard and blocks even when it points at /tmp.
12
+ - Check the diff against: the task's plan section (scope drift?), the
13
+ config review-policy rules, and the engineering baseline
14
+ (`shared/engineering.md`). For test-intents: run
15
+ `bin/harness show-redproof --task <T> --run <run>`
16
+ (chain-verified; a raw `.redproof/` read skips integrity verification
17
+ and is guard-BLOCKED — and type that full invocation exactly: the bare
18
+ `harness` spelling is neither on PATH nor allow-listed, so it dies as a
19
+ permission denial) and check its `missing_intents` field
20
+ (already mechanically checked, not yours to recompute) — any entry is a
21
+ finding. A present name isn't automatically a pass, though: judge whether
22
+ it genuinely tests its declared intent (design.md:392 — presence is
23
+ mechanical, semantic match stays yours).
24
+ - Findings numbered `[R<n>]` with severity CRITICAL | WARNING | SUGGESTION;
25
+ `verdict: APPROVED` only when nothing CRITICAL/WARNING remains. The
26
+ verdict is its OWN block line, before `outcome`/`details` (the template's
27
+ third line — never inside another field's prose): one run into the end
28
+ of a sentence is deliberately not captured (fail-closed) and costs a
29
+ full re-review by a fresh reviewer.
30
+ - Full findings in the status block `details` — the orchestrator routes
31
+ them; rejection costs a bounded review round (round N+ escalates to the
32
+ human), so make every finding actionable.
@@ -0,0 +1,18 @@
1
+ # Step: security (orchestrator-owned, fully mechanical)
2
+
3
+ ```
4
+ bin/harness security-scan --run <run>
5
+ ```
6
+
7
+ One call scans every registered repo (`security.scan_cmd` is per repo,
8
+ language-config convention — different repos may need different scanners;
9
+ "no scanner" for a repo records informational). Runs concurrently, parses
10
+ each repo's max severity via the declared regex, aggregates to ONE true max
11
+ across all repos (never a per-call overwrite — a clean repo must not mask
12
+ another's critical finding), writes `<run>/reports/security.md`, records
13
+ the `security.max_severity` artifact.
14
+
15
+ Then advance. The manifest's `when` predicate decides the rest mechanically:
16
+ severity ≥ threshold → ⟨approve-security⟩ is REQUIRED next (fix-now / waive /
17
+ defer, see `gate.md`); below threshold → the gate is skipped and `pre-pr` is
18
+ next. `bin/harness show` + a refused advance tell you which.
@@ -0,0 +1,15 @@
1
+ # Instruction: ad-hoc request triage (reviewer shape, mode `request-triage`)
2
+
3
+ A human made a request mid-run. Classify it against the APPROVED plan:
4
+
5
+ - `IN_SCOPE_BUG` — defect in work this run already did → route to the
6
+ develop/fixup loop.
7
+ - `IN_SCOPE_AC_MISS` — an approved acceptance criterion isn't met → same.
8
+ - `OUT_OF_SCOPE` — new scope → propose a follow-up work item; NEVER
9
+ silently merge it into this run.
10
+ - `PLAN_CONFLICT` — contradicts an approved decision → surface both sides
11
+ to the human; never resolve unilaterally.
12
+ - `DUPLICATE` / `INVALID` — with the evidence.
13
+
14
+ Verdict + reasoning in the status block; the orchestrator presents it to the
15
+ human — triage never mutates anything.