@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.
- package/.claude-plugin/plugin.json +28 -0
- package/CHANGELOG.md +2155 -0
- package/LICENSE +21 -0
- package/README.md +59 -2
- package/package.json +31 -4
- package/references/finding.schema.json +39 -0
- package/references/goal-tracking.md +71 -0
- package/references/heartbeat.md +91 -0
- package/references/mapreduce.md +90 -0
- package/references/pr-routing.md +77 -0
- package/references/scan-contract.md +195 -0
- package/references/scan-result.schema.json +121 -0
- package/references/scan-state.schema.json +199 -0
- package/skills/1-aim/SKILL.md +114 -0
- package/skills/1-aim/references/charter.md +96 -0
- package/skills/2-sweep/SKILL.md +92 -0
- package/skills/2-sweep/references/worker-briefing.md +70 -0
- package/skills/3-sift/SKILL.md +93 -0
- package/skills/4-plot/SKILL.md +124 -0
- package/skills/5-track/SKILL.md +112 -0
- package/skills/campaign/SKILL.md +185 -0
- package/skills/run/SKILL.md +165 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: campaign
|
|
3
|
+
description: Drive a long-term codebase goal to its target — charter it, sweep and sift the repository into findings, plot PR-sized slices, run each slice through the Terreno lifecycle, then re-measure and repeat until the metric hits target or a genuine human decision is required. Not a scan stage — an outer loop that invokes the scan stages and the lifecycle. Use when asked to run a scan campaign, work toward a long-term engineering goal, or keep scanning and fixing until an outcome is reached.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Scan campaign (outer driver)
|
|
7
|
+
|
|
8
|
+
Not a stage. The five scan stages stay Aim, Sweep, Sift, Plot, Track. This skill walks
|
|
9
|
+
them round after round and hands each plotted slice to the Terreno lifecycle, until the
|
|
10
|
+
goal metric reaches its target or a genuine human decision is required.
|
|
11
|
+
|
|
12
|
+
For a session that stays resident — heartbeating over open PRs, answering review, and
|
|
13
|
+
refilling work as PRs merge — use `run` instead. This skill runs the rounds
|
|
14
|
+
and stops at each gate; the loop wraps it and keeps going.
|
|
15
|
+
|
|
16
|
+
Read the shared [`scan contract`](../../references/scan-contract.md),
|
|
17
|
+
[`agentic map-reduce`](../../references/mapreduce.md),
|
|
18
|
+
[`goal tracking`](../../references/goal-tracking.md), and
|
|
19
|
+
[`PR routing`](../../references/pr-routing.md). The campaign state must conform to
|
|
20
|
+
[`scan-state.schema.json`](../../references/scan-state.schema.json).
|
|
21
|
+
|
|
22
|
+
## Scope
|
|
23
|
+
|
|
24
|
+
- Included: the five scan stages, campaign-state persistence, lifecycle handoff for each
|
|
25
|
+
plotted slice, bounded retries, and one accumulated report.
|
|
26
|
+
- Excluded: implementing findings, editing product code, committing, pushing, opening or
|
|
27
|
+
merging PRs. The lifecycle owns all of that.
|
|
28
|
+
- Requires the Terreno lifecycle plugin (`1-grow` … `5-taste`). If it is
|
|
29
|
+
not installed, stop at Plot and report the missing dependency.
|
|
30
|
+
|
|
31
|
+
## Preconditions
|
|
32
|
+
|
|
33
|
+
- A goal, outcome, or existing charter is available with a repository.
|
|
34
|
+
- The campaign-state location is resolvable and can be preserved between invocations.
|
|
35
|
+
|
|
36
|
+
If a charter exists but is unapproved, stop at a human gate. Do not invent a goal, a
|
|
37
|
+
target, or a metric.
|
|
38
|
+
|
|
39
|
+
## Round shape
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Aim (once per goal)
|
|
43
|
+
→ Sweep → Sift
|
|
44
|
+
→ dry round → Track
|
|
45
|
+
→ findings → Plot → handoff
|
|
46
|
+
→ 1-grow (slice brief → approved IP + tasks)
|
|
47
|
+
→ pick-roast-loop, or 2-pick once
|
|
48
|
+
→ 4-brew → 5-taste
|
|
49
|
+
→ Track
|
|
50
|
+
→ plot (backlog remains)
|
|
51
|
+
→ sweep (backlog empty, rounds remain)
|
|
52
|
+
→ null (target reached, budget spent, regression, or diminishing returns)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Drive
|
|
56
|
+
|
|
57
|
+
1. **Reconstruct once.** Read the charter and campaign state. Verify goal, round, branch,
|
|
58
|
+
findings, and slice PR status against reality. Identify the stage named by
|
|
59
|
+
`next.stage`; default to Aim when no charter exists, otherwise Sweep.
|
|
60
|
+
2. **Invoke the named scan stage** in a fresh context with the charter, campaign state,
|
|
61
|
+
the previous result, and this round's artifacts. Never ask the stage to rediscover the
|
|
62
|
+
campaign from conversation.
|
|
63
|
+
3. **Consume the result.** Update campaign state, then classify:
|
|
64
|
+
- `PASS` with `next` set → invoke that stage next.
|
|
65
|
+
- `PASS` with `handoff: grow` → run the lifecycle for the top slice (below), then
|
|
66
|
+
invoke Track.
|
|
67
|
+
- `PASS` with `next: null` → finish and report.
|
|
68
|
+
- `FAIL` with a concrete action → reinvoke the named stage with the exact evidence and
|
|
69
|
+
a new hypothesis.
|
|
70
|
+
- `BLOCKED` with `kind: human` or `next.human: true` → present the human gate.
|
|
71
|
+
- `BLOCKED` for environment/access/external → attempt safe remediation or one bounded
|
|
72
|
+
retry when a new hypothesis exists. Never relabel it `human` merely to stop.
|
|
73
|
+
- `PENDING` → wait per `wait`, preferring the harness's native completion hook or the
|
|
74
|
+
provider's watch hook; use a timer only when no hook applies. Then reinvoke.
|
|
75
|
+
4. **Run the handed-off slice.** For the slice Plot names:
|
|
76
|
+
- Invoke `1-grow` with the slice brief. Grow owns the IP, the task list, and
|
|
77
|
+
human approval.
|
|
78
|
+
- On Grow `PASS`, invoke `pick-roast-loop` when it is installed, otherwise
|
|
79
|
+
`2-pick` once — Pick owns the pick → roast → next-task inner loop.
|
|
80
|
+
- On completion, invoke `4-brew`, then `5-taste`, honoring their
|
|
81
|
+
`PENDING` waits exactly as the lifecycle's own loops do.
|
|
82
|
+
- As soon as Brew reports the PR, apply the charter's routing per `pr-routing.md` and
|
|
83
|
+
record the reviewer and assignee. An unrouted PR is not a finished handoff.
|
|
84
|
+
- Record the slice's branch, PR, reviewer, and outcome in campaign state. A slice the lifecycle
|
|
85
|
+
blocks is recorded and skipped; the campaign continues with the next slice rather
|
|
86
|
+
than stalling the goal, unless the blocker applies to every slice.
|
|
87
|
+
5. **Bound retries by evidence.** A retry must add a new hypothesis, changed setup, or
|
|
88
|
+
new evidence. Never repeat a failed approach. After two focused failures of the same
|
|
89
|
+
stage with no new hypothesis, classify the underlying decision honestly instead of
|
|
90
|
+
looping.
|
|
91
|
+
6. **Continue quietly.** Repeat steps 2–5 without narrating each cycle. Keep details in
|
|
92
|
+
campaign state and report once at completion or at a human gate.
|
|
93
|
+
|
|
94
|
+
## Budget and safety
|
|
95
|
+
|
|
96
|
+
- Honor the charter's budget: rounds, slices per round, and open PRs at once (`wipLimit`).
|
|
97
|
+
- Never exceed the open-PR limit; wait on Track instead of stacking review load.
|
|
98
|
+
- Stop and report when the horizon passes, even mid-backlog.
|
|
99
|
+
- Never run a campaign that edits code the charter marked out of scope.
|
|
100
|
+
|
|
101
|
+
## Recurring campaigns
|
|
102
|
+
|
|
103
|
+
A campaign is resumable by design: every invocation reconstructs from the charter and
|
|
104
|
+
campaign state. To run it on a cadence, schedule this skill with the goal slug and let it
|
|
105
|
+
pick up the next move — a fresh sweep, the next slice, or a report. Repeated invocations
|
|
106
|
+
must not restart Aim or re-baseline a goal that already has one.
|
|
107
|
+
|
|
108
|
+
## Genuine human gate
|
|
109
|
+
|
|
110
|
+
Ask for input only for:
|
|
111
|
+
|
|
112
|
+
- the goal statement, metric, or target itself
|
|
113
|
+
- destructive or irreversible remediation
|
|
114
|
+
- public API, data-format, or compatibility changes a finding requires
|
|
115
|
+
- scope growth beyond the approved charter
|
|
116
|
+
- a metric regression or two rounds below the charter's minimum step
|
|
117
|
+
- credentials or permissions no authorized alternative can supply
|
|
118
|
+
- a reviewer handle that cannot be verified or requested
|
|
119
|
+
|
|
120
|
+
Before the question, give this overview in plain language:
|
|
121
|
+
|
|
122
|
+
1. **Goal and trajectory:** statement, metric, baseline → previous → current vs target.
|
|
123
|
+
2. **What happened:** rounds run, findings found/fixed/reopened, slices merged, decisive
|
|
124
|
+
evidence.
|
|
125
|
+
3. **Why input is needed:** the exact decision and why evidence cannot choose it.
|
|
126
|
+
4. **Options:** two to four concrete choices with impact and risk.
|
|
127
|
+
5. **Recommendation:** one default and its rationale.
|
|
128
|
+
|
|
129
|
+
End with **one exact question** the human can answer in one message. Then close with PR
|
|
130
|
+
deployment URLs when a slice's PR has them. Do not expose chain-of-thought, worker
|
|
131
|
+
transcripts, or unexplained stage YAML.
|
|
132
|
+
|
|
133
|
+
## Completion report
|
|
134
|
+
|
|
135
|
+
When the target is reached, lead with:
|
|
136
|
+
|
|
137
|
+
`PASS — <metric> <baseline> → <current> <unit> (target <target>) across <n> rounds.`
|
|
138
|
+
|
|
139
|
+
Then report:
|
|
140
|
+
|
|
141
|
+
- `Trajectory`: metric per round with the command output for the final measurement
|
|
142
|
+
- `Fixed`: findings closed with evidence, grouped by slice and PR
|
|
143
|
+
- `Open`: findings still open or deferred, with the reason
|
|
144
|
+
- `Dismissed`: dropped findings and why
|
|
145
|
+
- `Regressions`: anything that moved the wrong way, or `None identified`
|
|
146
|
+
- `Residual risk`: explicit remaining risk, or `None identified`
|
|
147
|
+
- `Next`: the recommended follow-up, such as a cadence for re-sweeping
|
|
148
|
+
|
|
149
|
+
When stopped early, use the same report plus `Blocker`. Include everything from the round
|
|
150
|
+
records once; do not duplicate per-round narration.
|
|
151
|
+
|
|
152
|
+
## Stop conditions
|
|
153
|
+
|
|
154
|
+
- `PASS`: the metric reached target and held after the last slice landed.
|
|
155
|
+
- `PASS` with a question: budget or horizon exhausted, or diminishing returns.
|
|
156
|
+
- `BLOCKED` (human): a genuine human gate above.
|
|
157
|
+
- `BLOCKED` (non-human): retries exhausted and no safe autonomous action exists.
|
|
158
|
+
- `FAIL`: campaign state is inconsistent or corrupt, or the named stage cannot be invoked.
|
|
159
|
+
|
|
160
|
+
Ordinary rule failures, empty shards, dry rounds, and lifecycle test failures are not
|
|
161
|
+
terminal while a concrete action remains.
|
|
162
|
+
|
|
163
|
+
## Emit
|
|
164
|
+
|
|
165
|
+
After the human-facing report, include one collapsed scan-result payload. Since outer
|
|
166
|
+
loops are not stages, set `stage` to the last scan stage invoked.
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
v: 2
|
|
170
|
+
stage: track
|
|
171
|
+
status: PASS
|
|
172
|
+
goal: reduce-cold-build-time
|
|
173
|
+
round: 3
|
|
174
|
+
metric:
|
|
175
|
+
value: 28.4
|
|
176
|
+
unit: s
|
|
177
|
+
delta: -30.2
|
|
178
|
+
ev: "bun run compile (cold, best of 3): 28.4s"
|
|
179
|
+
next: null
|
|
180
|
+
action: Target reached; re-sweep quarterly to hold the gain
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For a human gate, use `status: BLOCKED`, `next: null`, and an `ask` entry with the exact
|
|
184
|
+
question, recommendation, and options. For a non-human terminal blocker, use a `block`
|
|
185
|
+
entry with `kind: environment`, `access`, or `external`, and omit `ask`.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run
|
|
3
|
+
description: Run a scan campaign as a resident session — keep working toward the goal, open PR-sized slices routed to named reviewers, and heartbeat over every open PR to answer review comments, fix failing CI, and land merges, until the metric hits target or a human decision is required. Use when asked to keep a goal running continuously, leave a scan going in the background, watch and respond to campaign PRs, or run the scan loop; not for a single bounded round.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Scan loop (resident driver)
|
|
7
|
+
|
|
8
|
+
One session, running until the goal is met. It alternates between **making progress** —
|
|
9
|
+
sweep, sift, plot, hand a slice to the lifecycle, open a routed PR — and **servicing what
|
|
10
|
+
is already open** — answering human review, fixing red CI, tracking merges. Work happens
|
|
11
|
+
in fresh subagents; this session holds only the goal, the state, and the schedule.
|
|
12
|
+
|
|
13
|
+
Read [`scan contract`](../../references/scan-contract.md),
|
|
14
|
+
[`heartbeat`](../../references/heartbeat.md),
|
|
15
|
+
[`PR routing`](../../references/pr-routing.md),
|
|
16
|
+
[`goal tracking`](../../references/goal-tracking.md), and
|
|
17
|
+
[`agentic map-reduce`](../../references/mapreduce.md). Campaign state conforms to
|
|
18
|
+
[`scan-state.schema.json`](../../references/scan-state.schema.json).
|
|
19
|
+
|
|
20
|
+
## Scope
|
|
21
|
+
|
|
22
|
+
- Included: the five scan stages, PR routing, the heartbeat over open campaign PRs,
|
|
23
|
+
lifecycle invocation per slice, state persistence, scheduling, and one report per
|
|
24
|
+
human gate or completion.
|
|
25
|
+
- Excluded: writing product code, committing, pushing, approving, and merging. Every one
|
|
26
|
+
of those belongs to a lifecycle stage invoked in a fresh subagent — Pick implements,
|
|
27
|
+
Brew submits, Taste reacts.
|
|
28
|
+
- Requires the lifecycle plugin (`1-grow` … `5-taste`) and a host CLI
|
|
29
|
+
with PR access (`gh`). Missing either is `BLOCKED`, not a workaround.
|
|
30
|
+
|
|
31
|
+
## Arguments
|
|
32
|
+
|
|
33
|
+
Parse from the invocation, in this order: an explicit `goal=<slug>`, a quoted goal
|
|
34
|
+
statement, or the remaining text. Also accept:
|
|
35
|
+
|
|
36
|
+
| Argument | Meaning |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `reviewer=<handle[,handle]>` | Override the charter's reviewers for this run |
|
|
39
|
+
| `assignee=<handle>` | Override the charter's assignee |
|
|
40
|
+
| `wip=<n>` | Override the charter's open-PR limit for this run |
|
|
41
|
+
| `rounds=<n>` | Stop after this many sweep rounds |
|
|
42
|
+
| `until=<ISO timestamp>` | Stop at this time regardless of progress |
|
|
43
|
+
| `tick=<seconds>` | Fixed heartbeat interval instead of the adaptive one |
|
|
44
|
+
|
|
45
|
+
An override applies to this run only and is recorded in state as an override, never
|
|
46
|
+
written back into the charter.
|
|
47
|
+
|
|
48
|
+
If no campaign exists for the goal, run Aim first and block for approval — a resident
|
|
49
|
+
loop does not invent a metric, a target, or a reviewer.
|
|
50
|
+
|
|
51
|
+
## Start
|
|
52
|
+
|
|
53
|
+
1. **Resolve the campaign.** Read the charter and campaign state for the goal. Verify the
|
|
54
|
+
branch, round, findings, and every recorded PR against the host. If nothing exists,
|
|
55
|
+
invoke `1-aim` and stop at its approval gate.
|
|
56
|
+
2. **Resolve routing.** Confirm the charter's `review` block names a reachable reviewer or
|
|
57
|
+
an explicit `mode: none`. Verify unfamiliar handles per `pr-routing.md`. An unroutable
|
|
58
|
+
campaign stops here with one question, before any PR exists.
|
|
59
|
+
3. **Announce once.** One short line: goal, metric baseline → current vs target, open PRs
|
|
60
|
+
and who has them, what this run will do first, and the heartbeat interval. This is the
|
|
61
|
+
only unprompted status message until something needs a human.
|
|
62
|
+
|
|
63
|
+
## Run
|
|
64
|
+
|
|
65
|
+
Repeat until a stop condition:
|
|
66
|
+
|
|
67
|
+
1. **Heartbeat tick.** Follow `heartbeat.md`: snapshot the campaign's PRs, classify each,
|
|
68
|
+
and act in priority order — route unrouted PRs, hand answered and broken PRs to Taste
|
|
69
|
+
in fresh subagents, Track merged ones, retire closed ones. Answer any given comment
|
|
70
|
+
exactly once.
|
|
71
|
+
2. **Refill capacity.** When open campaign PRs are below the effective `wipLimit` and the
|
|
72
|
+
backlog has planned findings, advance the campaign one step:
|
|
73
|
+
- planned findings remain → `4-plot` for the next slice
|
|
74
|
+
- backlog empty, rounds remain → `2-sweep`, then `3-sift`
|
|
75
|
+
- a slice is ready to build → `1-grow` with its brief, then
|
|
76
|
+
`pick-roast-loop` (or `2-pick` once), then `4-brew`
|
|
77
|
+
- Brew reported a PR → apply routing immediately, then count the slice in flight
|
|
78
|
+
3. **Persist.** Update campaign state after every stage and every tick: stage, round,
|
|
79
|
+
slices with PR/reviewer/assignee/bucket, answered comment ids, `lastTick`, and the
|
|
80
|
+
chosen next interval.
|
|
81
|
+
4. **Schedule.** Pick the next interval from the heartbeat table — provider watch hook
|
|
82
|
+
while CI runs, minutes while bots report, tens of minutes while a human holds the PR,
|
|
83
|
+
no wait at all while backlog work remains. Prefer the harness's native scheduling or
|
|
84
|
+
completion hooks; use a timer only when no hook applies.
|
|
85
|
+
5. **Stay quiet.** A tick with nothing to report prints nothing. Do not narrate ticks, do
|
|
86
|
+
not repeat the plan, and do not post PR comments to show activity.
|
|
87
|
+
|
|
88
|
+
## Concurrency
|
|
89
|
+
|
|
90
|
+
- Never exceed the effective `wipLimit` of open campaign PRs.
|
|
91
|
+
- Never run two lifecycle stages against the same slice at once.
|
|
92
|
+
- Never start a new slice while a slice for the same files is open — the second PR will
|
|
93
|
+
conflict and waste the reviewer's time.
|
|
94
|
+
- One branch per slice, named from the slice slug. Never reuse a branch a human is
|
|
95
|
+
reviewing.
|
|
96
|
+
|
|
97
|
+
## Speak only when it matters
|
|
98
|
+
|
|
99
|
+
Interrupt the human for:
|
|
100
|
+
|
|
101
|
+
- a genuine gate from `scan-contract.md`: goal or target changes, destructive remediation,
|
|
102
|
+
public API or data-format changes, scope growth, metric regression, exhausted budget
|
|
103
|
+
- an unroutable or unverifiable reviewer handle
|
|
104
|
+
- a PR a human has held with requested changes the campaign cannot satisfy without a
|
|
105
|
+
decision
|
|
106
|
+
- three consecutive host failures, lost credentials, or a lifecycle stage blocked on
|
|
107
|
+
something only a person can supply
|
|
108
|
+
|
|
109
|
+
Every interruption carries goal and trajectory, what happened, why input is needed,
|
|
110
|
+
two to four options with impact, a recommendation, then **one exact question**, then PR
|
|
111
|
+
deployment URLs when a campaign PR has them.
|
|
112
|
+
|
|
113
|
+
## Stop conditions
|
|
114
|
+
|
|
115
|
+
- Metric reached target and held after the last slice merged → complete.
|
|
116
|
+
- `rounds=` or `until=` reached, or the charter's horizon passed → report and ask.
|
|
117
|
+
- Two rounds below the charter's minimum step, or a regression → report and ask.
|
|
118
|
+
- A genuine human gate → `BLOCKED`, with the question above.
|
|
119
|
+
- Three consecutive host failures → `BLOCKED` with `kind: access`.
|
|
120
|
+
- The human says stop → stop immediately, leave every PR routed and state consistent, and
|
|
121
|
+
report what is in flight and who holds it.
|
|
122
|
+
|
|
123
|
+
A resident loop never stops quietly. Every stop names what is open, who has it, and what
|
|
124
|
+
the next action would be.
|
|
125
|
+
|
|
126
|
+
## Report
|
|
127
|
+
|
|
128
|
+
On completion or at a gate, lead with the trajectory:
|
|
129
|
+
|
|
130
|
+
`<metric> <baseline> → <current> <unit> (target <target>), <merged> slices merged, <open> open.`
|
|
131
|
+
|
|
132
|
+
Then: `In flight` (PR, reviewer, bucket, age), `Merged this run`, `Fixed` findings with
|
|
133
|
+
evidence, `Open` and `Dismissed` findings, `Regressions` or `None identified`,
|
|
134
|
+
`Residual risk`, and `Next`.
|
|
135
|
+
|
|
136
|
+
## Emit
|
|
137
|
+
|
|
138
|
+
After the human-facing report, one collapsed scan-result payload. The loop is not a
|
|
139
|
+
stage, so set `stage` to the last scan stage invoked.
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
v: 2
|
|
143
|
+
stage: track
|
|
144
|
+
status: PENDING
|
|
145
|
+
goal: reduce-cold-build-time
|
|
146
|
+
round: 2
|
|
147
|
+
metric:
|
|
148
|
+
value: 41.7
|
|
149
|
+
unit: s
|
|
150
|
+
delta: -16.9
|
|
151
|
+
ev: "bun run compile (cold, best of 3): 41.7s"
|
|
152
|
+
prs:
|
|
153
|
+
- pr: "1421"
|
|
154
|
+
bucket: waiting
|
|
155
|
+
who: octocat
|
|
156
|
+
- pr: "1424"
|
|
157
|
+
bucket: answered
|
|
158
|
+
who: octocat
|
|
159
|
+
wait: 900
|
|
160
|
+
next: track
|
|
161
|
+
action: Taste is addressing review on #1424; recheck both PRs in 15 minutes
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Use `status: PENDING` with a `wait` while PRs are open and progress continues,
|
|
165
|
+
`status: PASS` when the goal is met, and `status: BLOCKED` with one `ask` at a human gate.
|