@terreno/agent-plugin-loop 0.0.0-stage → 57.22.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.
@@ -0,0 +1,96 @@
1
+ # Charter template
2
+
3
+ One file per goal. Keep it readable by someone who was not in the grilling conversation.
4
+
5
+ ```markdown
6
+ # Scan charter — <goal statement>
7
+
8
+ - Slug: <goal-slug>
9
+ - Status: draft | approved (<date>)
10
+ - Owner: <human>
11
+
12
+ ## Goal
13
+
14
+ <One paragraph: where the repository is today, where this campaign takes it, and why now.>
15
+
16
+ ## Metric
17
+
18
+ | Field | Value |
19
+ | --- | --- |
20
+ | Name | <what is measured> |
21
+ | Command | `<command that prints the number>` |
22
+ | Unit | s / ms / count / percent / bytes |
23
+ | Direction | down / up |
24
+ | Protocol | <cold vs warm, best of three, machine class> |
25
+ | Baseline | <value> (measured <date>) |
26
+ | Target | <value> |
27
+ | Horizon | <rounds or date> |
28
+
29
+ Baseline evidence:
30
+
31
+ ```text
32
+ <quoted command output>
33
+ ```
34
+
35
+ ## Scope
36
+
37
+ - In scope: <packages, directories, layers>
38
+ - Out of scope: <areas the campaign must not touch>
39
+ - Unacceptable trade-offs: <for example, no public API breaks, no new dependencies>
40
+
41
+ ## Detection rules
42
+
43
+ | Rule | Query | Matches | Why it moves the metric | Hits |
44
+ | --- | --- | --- | --- | --- |
45
+ | <slug> | `<command>` | <one sentence> | <one sentence> | <n> |
46
+
47
+ ## Exclusions
48
+
49
+ <Globs never reported on, beyond the defaults in the map-reduce reference.>
50
+
51
+ ## Validity rule
52
+
53
+ A finding is valid only when <one sentence>.
54
+
55
+ ## Severity rubric
56
+
57
+ | Severity | Threshold |
58
+ | --- | --- |
59
+ | high | <concrete threshold> |
60
+ | medium | <concrete threshold> |
61
+ | low | <concrete threshold> |
62
+
63
+ Effort: S = under an hour, M = under a day, L = more than a day or needs design.
64
+
65
+ ## Slice policy
66
+
67
+ - Maximum <n> files and <n> findings per slice
68
+ - Never mix: <combinations that make review unsafe>
69
+ - Always its own slice: <risky or reviewer-heavy categories>
70
+
71
+ ## Review routing
72
+
73
+ | Field | Value |
74
+ | --- | --- |
75
+ | Mode | fixed / codeowners / blame / round-robin / none |
76
+ | Reviewers | <@handle, @handle> |
77
+ | Assignee | <@handle> |
78
+ | Teams | <org/team> |
79
+ | Draft | yes / no |
80
+ | Labels | <goal-slug, ...> |
81
+ | Merge policy | human / agent-after-approval (<conditions>) |
82
+ | Notify | PR body mention / none / <channel> |
83
+
84
+ ## Budget
85
+
86
+ - Rounds: <n>
87
+ - Slices per round: <n>
88
+ - Open PRs at once (`wipLimit`): <n>
89
+ - Minimum metric step per round before reporting diminishing returns: <value>
90
+
91
+ ## Decisions
92
+
93
+ | Decision | Question that prompted it |
94
+ | --- | --- |
95
+ | <settled decision> | <the exact question asked> |
96
+ ```
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: 2-sweep
3
+ description: Run an approved scan charter across the repository — execute detection rules, shard the hits deterministically, and map fresh parallel workers over the shards into schema-valid candidate findings. Use after a scan charter is approved, or to re-sweep a later campaign round; not for shaping goals, ranking findings, or writing code.
4
+ ---
5
+
6
+ # Sweep — shard and map
7
+
8
+ Execute the approved charter across the repository and return raw candidate findings with
9
+ reproducible evidence. Sweep discovers; it does not judge, rank, or fix.
10
+
11
+ Read the shared [`scan contract`](../../references/scan-contract.md) and
12
+ [`agentic map-reduce`](../../references/mapreduce.md), plus the
13
+ [`worker briefing`](references/worker-briefing.md), before acting.
14
+
15
+ ## Preconditions
16
+
17
+ - An approved charter and campaign state exist for this goal.
18
+ - The working tree is clean enough that `path:line` anchors are stable; record the head
19
+ SHA the sweep ran against.
20
+ - This invocation owns discovery only. It never edits files.
21
+
22
+ ## Inputs
23
+
24
+ - Charter: rules, exclusions, validity rule, severity rubric, effort scale
25
+ - Campaign state: goal, round, prior findings and their status
26
+ - Repository code, tests, build output, and available skills
27
+
28
+ ## Procedure
29
+
30
+ 1. **Reconstruct.** Read the charter and campaign state. Verify the branch and head, and
31
+ increment the round when the previous round is closed.
32
+ 2. **Discover supporting skills.** Load repository skills matching the rules in play.
33
+ 3. **Run the rules.** Execute each rule's query with its exclusions. Record hit counts per
34
+ rule and compare them to the charter's dry-run counts. A rule that now returns zero or
35
+ an order of magnitude more hits is reported in the result — the repository moved, and
36
+ Sift must know.
37
+ 4. **Shard.** Group and pack the hits into deterministic shards per the map-reduce
38
+ reference. Write the shard manifest to the round's artifact directory. When the shard
39
+ cap truncates coverage, name exactly what was dropped.
40
+ 5. **Map.** Spawn one fresh worker per shard with no parent conversation, using the
41
+ worker briefing. Run them concurrently up to the harness's practical limit. Each worker
42
+ returns candidates conforming to
43
+ [`finding.schema.json`](../../references/finding.schema.json) and nothing else.
44
+ 6. **Collect.** Validate every returned candidate against the schema. Drop malformed
45
+ entries and record how many and from which shard. Retry a failed worker once with the
46
+ same briefing; record a second failure as a failed shard without failing the sweep.
47
+ 7. **Persist.** Write the candidate set to the round's artifact directory, update campaign
48
+ state with the round, rules, shard count, and candidate count, and emit the result.
49
+
50
+ ## Constraints
51
+
52
+ - Never edit, stage, or commit files. Never run destructive commands.
53
+ - Never let a worker roam outside its shard beyond following a hit's definition or caller.
54
+ - Never fabricate a candidate to make a shard look productive; empty shards are normal.
55
+ - Never silently truncate. Dropped shards, capped groups, and malformed returns all appear
56
+ in the result.
57
+
58
+ ## Supporting skills
59
+
60
+ Follow the shared discovery procedure. Typical matches are static-analysis, build,
61
+ performance-measurement, or domain skills named by the charter's rules.
62
+
63
+ ## Evidence produced
64
+
65
+ - Head SHA, round number, and per-rule hit counts with drift against the charter
66
+ - Shard manifest path and shard count
67
+ - Candidate findings artifact path and candidate count
68
+ - Failed shards, malformed candidates, and any coverage the caps dropped
69
+
70
+ ## Success conditions
71
+
72
+ - Every approved rule ran, or a `FAIL` names the rule that could not.
73
+ - Every shard was mapped or explicitly recorded as failed.
74
+ - Every candidate validates against the finding schema and carries a `path:line` anchor.
75
+ - Emit `PASS` with `next: sift`.
76
+
77
+ ## Failure conditions
78
+
79
+ A rule that cannot execute, a shard manifest that does not cover the hits, or a candidate
80
+ set that fails schema validation emits `FAIL` with exact evidence, `next: sweep`, and the
81
+ smallest retry — usually re-running the named rule or re-mapping the named shards.
82
+
83
+ ## Blocked conditions
84
+
85
+ Missing tooling, unreadable paths, or a harness that cannot spawn workers emits `BLOCKED`
86
+ with the exact capability required.
87
+
88
+ ## Recommended next stage
89
+
90
+ - `PASS` → Sift
91
+ - `FAIL` → Sweep with the named rule or shard
92
+ - `BLOCKED` → campaign loop routes the named environment/access gate
@@ -0,0 +1,70 @@
1
+ # Worker briefing
2
+
3
+ One briefing per shard. The worker has no parent memory and must not rediscover the
4
+ repository. Send exactly these sections.
5
+
6
+ ```markdown
7
+ ## Goal
8
+
9
+ <goal statement>. Metric: <metric name>, currently <value><unit>, target <value><unit>.
10
+
11
+ ## Rules in play
12
+
13
+ | Rule | Matches | Why it moves the metric |
14
+ | --- | --- | --- |
15
+ | <slug> | <one sentence> | <one sentence> |
16
+
17
+ ## Validity rule
18
+
19
+ A finding is valid only when <charter sentence, quoted verbatim>.
20
+
21
+ ## Severity rubric
22
+
23
+ <charter rubric table, quoted verbatim, plus the effort scale>
24
+
25
+ ## Your shard
26
+
27
+ Files:
28
+ - <path>
29
+ - <path>
30
+
31
+ Hits:
32
+ - <path>:<line> — <rule>
33
+ - <path>:<line> — <rule>
34
+
35
+ ## Commands you may run
36
+
37
+ - `<named command>`
38
+ - `<named command>`
39
+
40
+ ## Rules of engagement
41
+
42
+ 1. Work only inside the shard's files. You may read a definition or caller a hit points
43
+ at; do not search the repository at large.
44
+ 2. Do not edit, stage, or commit anything. Do not run destructive commands.
45
+ 3. Do not spawn other agents.
46
+ 4. Every candidate needs a `path:line` anchor and reproducible evidence: the command you
47
+ ran and its output, or the exact code excerpt that proves the claim.
48
+ 5. If the shard has no valid candidates, return an empty array. That is a correct answer.
49
+
50
+ ## Return this and nothing else
51
+
52
+ A JSON array of objects conforming to the finding schema:
53
+
54
+ [
55
+ {
56
+ "id": "<shard>-<n>",
57
+ "rule": "<rule slug>",
58
+ "title": "<one line>",
59
+ "severity": "high|medium|low",
60
+ "confidence": "high|medium|low",
61
+ "effort": "S|M|L",
62
+ "anchors": [{"path": "<path>", "line": 42, "symbol": "<optional>"}],
63
+ "why": "<how fixing this moves the metric>",
64
+ "fix": "<the smallest change that would resolve it>",
65
+ "ev": "<command + output, or the proving excerpt>"
66
+ }
67
+ ]
68
+ ```
69
+
70
+ No prose, no transcript, no restated instructions.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: 3-sift
3
+ description: Reduce raw scan candidates into a trustworthy findings report — dedupe, adversarially verify, drop what does not reproduce or does not move the goal metric, rank by impact over effort, and write the round's findings report. Use after a sweep returns candidates; not for running detection rules, shaping goals, or writing code.
4
+ ---
5
+
6
+ # Sift — reduce
7
+
8
+ Turn a pile of worker candidates into a short, ranked, defensible findings list. A
9
+ finding that survives Sift is one an engineer can act on without re-investigating.
10
+
11
+ Read the shared [`scan contract`](../../references/scan-contract.md),
12
+ [`agentic map-reduce`](../../references/mapreduce.md), and
13
+ [`goal tracking`](../../references/goal-tracking.md) before acting.
14
+
15
+ ## Preconditions
16
+
17
+ - A sweep for the current round produced a candidate artifact.
18
+ - The charter's validity rule, severity rubric, and effort scale are available.
19
+ - This invocation owns reduction only. It never edits product code.
20
+
21
+ ## Inputs
22
+
23
+ - Candidate findings artifact and shard manifest for this round
24
+ - Charter: validity rule, severity rubric, effort scale, exclusions, metric
25
+ - Campaign state: prior findings and their status, including previously dismissed ones
26
+
27
+ ## Procedure
28
+
29
+ 1. **Reconstruct.** Read campaign state, the charter, and the round's candidates. Verify
30
+ the recorded head still matches the working tree; re-anchor or re-sweep if it moved.
31
+ 2. **Normalize and dedupe.** Give each candidate the dedupe key `rule + path + symbol`.
32
+ Merge candidates describing one defect at several anchors into one finding carrying all
33
+ anchors. Fold candidates matching a previously dismissed finding into that dismissal
34
+ instead of resurrecting them, unless new evidence contradicts the dismissal.
35
+ 3. **Verify.** Re-check each surviving candidate against the validity rule. Re-run the
36
+ candidate's evidence command when it has one. For every `high` severity candidate,
37
+ verify adversarially: state the strongest case that the finding is wrong, and keep it
38
+ only when that refutation fails. Downgrade confidence rather than deleting evidence.
39
+ 4. **Drop.** Remove candidates whose evidence does not reproduce, whose anchor no longer
40
+ exists, that an exclusion covers, or whose link to the metric cannot be stated in one
41
+ sentence. Count the drops and the top drop reasons.
42
+ 5. **Rank.** Score by goal impact × confidence ÷ effort. Apply the charter's severity
43
+ rubric yourself; a worker's severity is an input, not the verdict.
44
+ 6. **Report.** Write the round's findings report to the repository's scan convention
45
+ (default `docs/scans/<goal-slug>/round-<n>-findings.md`): goal and metric header, the
46
+ ranked findings table with severity, effort, anchors, and evidence, one short paragraph
47
+ per high-severity finding, and the dropped-candidate summary with counts and reasons.
48
+ 7. **Persist.** Merge surviving findings into campaign state with status `open`, keep the
49
+ dismissal record for dropped ones, update state, and emit the result.
50
+
51
+ ## Constraints
52
+
53
+ - No finding ships without reproducible evidence and a stated metric link.
54
+ - No silent deletion: every dropped candidate is counted and its reason categorized.
55
+ - Severity comes from the charter's thresholds, never from adjectives.
56
+ - A round that keeps zero findings is a valid dry round, not a failure.
57
+
58
+ ## Supporting skills
59
+
60
+ Follow the shared discovery procedure. Verification of a candidate may require the same
61
+ build, test, performance, or domain skills the rules named.
62
+
63
+ ## Evidence produced
64
+
65
+ - Findings report path, kept count, and dropped count with reasons
66
+ - Per-finding severity, confidence, effort, anchors, and evidence
67
+ - Adversarial verification outcome for every high-severity finding
68
+ - Updated campaign state and structured Sift result
69
+
70
+ ## Success conditions
71
+
72
+ - Every kept finding is deduped, verified, evidenced, ranked, and tied to the metric.
73
+ - Every high-severity finding survived an explicit refutation attempt.
74
+ - A fresh Plot invocation can slice the work from the report alone.
75
+ - Emit `PASS` with `next: plot`, or `PASS` with `next: track` when the round is dry.
76
+
77
+ ## Failure conditions
78
+
79
+ Candidates that cannot be read or validated, a report that contradicts its own evidence,
80
+ or unverifiable high-severity claims emit `FAIL` with exact defects and `next: sift`, or
81
+ `next: sweep` when the candidate set itself is unusable.
82
+
83
+ ## Blocked conditions
84
+
85
+ Missing tooling needed to reproduce evidence, or a metric link that requires a product
86
+ decision, emits `BLOCKED` with the exact decision or capability required.
87
+
88
+ ## Recommended next stage
89
+
90
+ - `PASS` with findings → Plot
91
+ - `PASS` with no findings → Track (dry round)
92
+ - `FAIL` → Sift, or Sweep when candidates are unusable
93
+ - `BLOCKED` → campaign loop routes the named gate
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: 4-plot
3
+ description: Turn ranked scan findings into PR-sized slices and hand the top slice to the Terreno IP and task system, writing a Grow-ready brief with metric-linked acceptance criteria and verification methods for each slice. Use after a sift produces a findings report; not for discovering findings, implementing them, or PR operations.
4
+ ---
5
+
6
+ # Plot — findings to IPs and tasks
7
+
8
+ A findings report is not work. Plot converts ranked findings into ordered, PR-sized
9
+ slices and hands the top one to the lifecycle, which owns the IP, the task list, and the
10
+ implementation.
11
+
12
+ Read the shared [`scan contract`](../../references/scan-contract.md),
13
+ [`goal tracking`](../../references/goal-tracking.md), and
14
+ [`PR routing`](../../references/pr-routing.md) before acting.
15
+
16
+ ## Preconditions
17
+
18
+ - A findings report exists for the current round with at least one kept finding.
19
+ - The charter's slice policy and budget are available.
20
+ - The lifecycle skills (`1-grow`, `2-pick`, `3-roast`,
21
+ `4-brew`, `5-taste`) are installed. If they are not, emit `BLOCKED`
22
+ naming the missing plugin — Plot must not implement findings itself.
23
+
24
+ ## Inputs
25
+
26
+ - Findings report and campaign state for this round
27
+ - Charter: slice policy, budget, unacceptable trade-offs, metric
28
+ - Repository IP/task conventions and available skills
29
+
30
+ ## Procedure
31
+
32
+ 1. **Reconstruct.** Read campaign state and the findings report. Resolve the repository's
33
+ IP and task conventions the same way Grow does; do not invent a second convention.
34
+ Skip findings already `planned`, `fixed`, or `dismissed`.
35
+ 2. **Slice.** Group open findings into units that fit the charter's slice policy: one
36
+ theme per slice, within the file and finding caps, never mixing combinations the
37
+ charter forbids, and giving risky or reviewer-heavy findings their own slice. Order
38
+ slices by rank, then by dependency — a slice that unblocks others goes first.
39
+ 3. **Respect the budget.** Plan at most the charter's slices per round and never exceed
40
+ its open-PR limit (`wipLimit`) counting PRs already open. Findings beyond the budget stay `open` for the next round; say so
41
+ explicitly rather than quietly dropping them.
42
+ 4. **Write a Grow brief per slice.** Each brief is standalone and contains:
43
+ - the goal statement, the metric, and the current value
44
+ - the findings in this slice with their anchors, evidence, and proposed fixes
45
+ - the acceptance criteria, each observable and each paired with a verification method
46
+ (test, build probe, runtime/API/database check, artifact, regression case)
47
+ - at least one criterion that ties back to the metric or names why this slice cannot
48
+ move it alone
49
+ - an `## E2E tests` section listing the slice's planned specs, or `None — <reason>`.
50
+ Use the table format of the testing plan contract in the `terreno-planning` plugin
51
+ (`references/testing-plan.md`, read by `1-grow`). Take each spec's path and
52
+ layer from the e2e guide that the agent instructions' `## Testing conventions` table
53
+ names, or from the contract's default. Pair every UI or cross-process criterion with
54
+ a row or a reason. Leave `Written in` for Grow to fill. When no guide exists at that
55
+ path, use the contract's layer names and say so; Grow adds the guide task, so this
56
+ is not `BLOCKED`
57
+ - a `## Regression cases` section listing the manual cases the slice adds or changes,
58
+ or `None — <reason>`, in the testing plan's table format with provisional
59
+ `<AREA>-new-<n>` IDs. Each case meets the contract's regression-step bar. Leave
60
+ `Added` for Grow to fill
61
+ - a `## User guide` section listing the end-user guide pages the slice adds, updates,
62
+ or retires, or `None — <reason>`, in the user-guide table format of the
63
+ `terreno-planning` plugin (`references/user-guide.md`). Leave `Written in` for Grow
64
+ to fill. A repository whose `## User guide conventions` table sets `none` writes
65
+ `None — user guide off`
66
+ - the unacceptable trade-offs from the charter, quoted
67
+ - the docs the slice must create or update
68
+ - known blockers, dependencies on other slices, and residual risk
69
+ - the reviewer and assignee this slice routes to, resolved from the charter's `review`
70
+ block; a slice whose routing cannot be resolved is `BLOCKED`, not opened unassigned
71
+ 5. **Persist the plan.** Write briefs to the round's artifact directory, record every
72
+ slice in campaign state with status `planned` and its finding ids, and mark those
73
+ findings `planned` with their slice slug.
74
+ 6. **Hand off.** Emit `PASS` with `next: track` and `handoff: grow`, naming the top
75
+ slice's brief path. The campaign loop invokes `1-grow` with that brief, then
76
+ the Pick/Roast inner loop, then Brew and Taste. Plot itself never invokes them, never
77
+ edits product code, and never opens a PR.
78
+
79
+ ## Constraints
80
+
81
+ - Plot writes briefs, not IPs. Grow owns the IP, the task list, and human approval.
82
+ - A slice with no metric-linked criterion needs an explicit sentence saying why.
83
+ - Never merge findings from different rules into one slice purely to hit the budget.
84
+ - Never mark a finding `fixed`; only Track does that, and only with evidence.
85
+
86
+ ## Supporting skills
87
+
88
+ Follow the shared discovery procedure. Slice briefs may name domain skills for the
89
+ lifecycle to load, but Grow and Pick still perform their own discovery.
90
+
91
+ ## Evidence produced
92
+
93
+ - Slice plan with order, rationale, and the findings in each slice
94
+ - Brief path per slice, its resolved reviewer/assignee, the acceptance-criterion →
95
+ verification mapping, and its `## E2E tests` and `## Regression cases` sections
96
+ - Findings deferred to a later round, with the budget reason
97
+ - Updated campaign state and structured Plot result
98
+
99
+ ## Success conditions
100
+
101
+ - Every planned slice fits the slice policy and has a standalone, criterion-complete
102
+ brief with both testing-plan sections, each holding rows or `None — <reason>`.
103
+ - Every open finding is either planned into a slice or explicitly deferred with a reason.
104
+ - A fresh Grow invocation can produce an approved IP and task list from one brief alone.
105
+ - Emit `PASS` with `next: track` and `handoff: grow`.
106
+
107
+ ## Failure conditions
108
+
109
+ Slices that violate the policy, briefs missing verification methods or a testing-plan
110
+ section, or findings silently lost between the report and the plan emit `FAIL` with exact
111
+ defects and `next: plot`.
112
+
113
+ ## Blocked conditions
114
+
115
+ A missing lifecycle plugin, an IP convention that cannot be resolved, or a finding whose
116
+ fix requires a product, security, or compatibility decision emits `BLOCKED` with options,
117
+ tradeoffs, and a recommended default.
118
+
119
+ ## Recommended next stage
120
+
121
+ - `PASS` → Track, after the campaign loop runs the handed-off slice through Grow, the
122
+ Pick/Roast inner loop, Brew, and Taste
123
+ - `FAIL` → Plot with defect evidence
124
+ - `BLOCKED` → campaign loop routes the named human/external gate
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: 5-track
3
+ description: Re-measure a scan campaign's goal metric after slices land, close or reopen findings with evidence, record the round, and choose the next move — more slices, a fresh sweep, or a report with one question. Use after a plotted slice finishes in the lifecycle or a round is dry; not for discovering findings, planning slices, or writing code.
4
+ ---
5
+
6
+ # Track — measure and decide
7
+
8
+ A campaign is only working if the number moved. Track re-measures the goal metric,
9
+ reconciles the findings against reality, records the round, and names the next move.
10
+
11
+ Read the shared [`scan contract`](../../references/scan-contract.md),
12
+ [`goal tracking`](../../references/goal-tracking.md), and
13
+ [`heartbeat`](../../references/heartbeat.md) before acting.
14
+
15
+ ## Preconditions
16
+
17
+ - Campaign state exists with a metric, a baseline, and at least one round in progress.
18
+ - Either a plotted slice has finished in the lifecycle, or the round was dry.
19
+ - This invocation owns measurement and routing only. It never edits product code.
20
+
21
+ ## Inputs
22
+
23
+ - Campaign state: goal, metric, baseline, rounds, findings, slices
24
+ - Findings report and slice briefs for the round
25
+ - Merge state of each slice's PR and the current head
26
+
27
+ ## Procedure
28
+
29
+ 1. **Reconstruct.** Read campaign state. Resolve each running slice's real status — PR
30
+ open, merged, closed, abandoned — from the repository, not from state's memory.
31
+ 2. **Wait when the work is still moving.** If a slice is mid-lifecycle (open PR, CI
32
+ running, review bots pending), emit `PENDING` with a `wait` and let the campaign loop
33
+ return. Prefer the harness's native completion hook or the provider's watch hook; use
34
+ a timer only when no hook applies. Do not close findings against unmerged work.
35
+ 3. **Re-measure.** Run the metric command exactly as the charter's protocol specifies, on
36
+ the branch the charter names (usually the default branch after merge). Quote the output
37
+ as evidence and compute the delta against both the baseline and the round start.
38
+ 4. **Reconcile findings.** For each finding in a landed slice, verify against the current
39
+ code: re-run its evidence command or re-check its anchor.
40
+ - Gone and the fix is present → `fixed`
41
+ - Still reproducible → `reopened`, with the new evidence and a one-line reason
42
+ - Anchor moved but the defect persists → update anchors, keep it open
43
+ Never mark a finding `fixed` because a task was checked off; only evidence closes a
44
+ finding.
45
+ 5. **Catch regressions.** If the metric moved the wrong way, or a previously fixed finding
46
+ is reproducible again, record it with evidence and treat it as the headline of this
47
+ round, not a footnote.
48
+ 6. **Retire closed slices.** A slice whose PR was closed without merging is `abandoned`:
49
+ record the closing reason, return its findings to `open`, and free its slot against the
50
+ open-PR limit.
51
+ 7. **Record the round.** Append the round record per `goal-tracking.md`: metric at start
52
+ and end with command output, found/kept/planned/fixed/dismissed/reopened counts, slices
53
+ landed with their PRs, residual risk, and anything deliberately deferred.
54
+ 8. **Choose the next move.** Apply the decision table in `goal-tracking.md`: `plot` while
55
+ planned findings remain within budget, `sweep` when the backlog is empty and rounds
56
+ remain, `null` when the target is reached and held, when two rounds moved less than the
57
+ charter's minimum step, when the metric regressed, or when the budget or horizon is
58
+ exhausted.
59
+ 9. **Report and persist.** Lead with the trajectory in one line — baseline → previous →
60
+ current against target. Update campaign state and emit the result collapsed. When a
61
+ slice's PR has GitHub Deployments, close the message with those demo URLs as the last
62
+ visible section.
63
+
64
+ ## Constraints
65
+
66
+ - Never re-baseline to flatter the campaign; re-baseline only per the goal-tracking rules
67
+ and record both values and the reason.
68
+ - Never report a metric value without its command output.
69
+ - Never close a round while a slice's PR is unmerged; emit `PENDING` instead.
70
+ - Diminishing returns, regressions, and exhausted budgets are reports with one question,
71
+ not silent stops.
72
+
73
+ ## Supporting skills
74
+
75
+ Follow the shared discovery procedure. Measurement may require the same build, test,
76
+ performance, or analysis skills the charter's metric command depends on.
77
+
78
+ ## Evidence produced
79
+
80
+ - Metric value with quoted command output, and deltas against baseline and round start
81
+ - Per-finding closure evidence: fixed, reopened, or still open with anchors
82
+ - Round record appended to campaign state
83
+ - Regression report when the metric or a fixed finding moved the wrong way
84
+ - The chosen next move with its reason
85
+
86
+ ## Success conditions
87
+
88
+ - The metric was re-measured with the charter's protocol and its output is quoted.
89
+ - Every finding in a landed slice was reconciled against current code with evidence.
90
+ - The round record makes the whole trajectory readable from state alone.
91
+ - Emit `PASS` with `next: plot`, `next: sweep`, or `next: null` per the decision table.
92
+
93
+ ## Failure conditions
94
+
95
+ A metric command that cannot run, a round record that contradicts the repository's real
96
+ merge state, or findings closed without evidence emit `FAIL` with exact defects and
97
+ `next: track`.
98
+
99
+ ## Blocked conditions
100
+
101
+ Missing measurement tooling or access, or a decision about whether to continue the
102
+ campaign that only a human can make, emits `BLOCKED` with the trajectory, options,
103
+ tradeoffs, and a recommended default.
104
+
105
+ ## Recommended next stage
106
+
107
+ - `PASS` with planned findings remaining → Plot
108
+ - `PASS` with an empty backlog and rounds remaining → Sweep
109
+ - `PASS` with the target reached, the budget spent, or a regression → `null`, report and
110
+ ask
111
+ - `PENDING` → campaign loop waits for the running slice and reinvokes Track
112
+ - `BLOCKED` → campaign loop routes the named human/external gate