@seanyao/roll 3.618.3 → 3.619.1
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/CHANGELOG.md +44 -0
- package/README.md +2 -1
- package/dist/roll.mjs +9066 -5629
- package/package.json +1 -1
- package/skills/README.md +2 -2
- package/skills/docs/skill-authoring.md +4 -3
- package/skills/roll-build/references/full-contract.md +12 -28
- package/skills/roll-fix/references/full-contract.md +6 -11
- package/skills/roll-loop/references/full-contract.md +41 -62
- package/skills/roll-peer/references/full-contract.md +1 -7
- package/skills/route-cases/skills.json +0 -20
- package/skills/roll-brief/SKILL.md +0 -207
- package/skills/roll-sentinel/SKILL.md +0 -46
- package/skills/roll-sentinel/references/full-contract.md +0 -363
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -27,8 +27,8 @@ roll 的**技能契约**仓——AI agent 在 roll 项目里工作时加载并
|
|
|
27
27
|
- `roll-.review` / `roll-.qa` — TCR 内嵌自审与测试金字塔基准
|
|
28
28
|
|
|
29
29
|
**Observation · 观察与汇报**
|
|
30
|
-
- `roll-
|
|
31
|
-
- `roll
|
|
30
|
+
- `roll-notes` — 项目日记
|
|
31
|
+
- `roll-.dream` — 夜间架构/文档健康扫描
|
|
32
32
|
- `roll-doctor` — 工具链体检;`roll-doc` — 存量文档自动化
|
|
33
33
|
|
|
34
34
|
**Lifecycle & misc · 生命周期与杂项**
|
|
@@ -42,9 +42,10 @@ Every hub must include `## Gotchas` or `## Known Failure Modes`.
|
|
|
42
42
|
- If a gotcha comes from a missed load, add a positive route case.
|
|
43
43
|
- If a gotcha comes from an off-target load, add a negative route case.
|
|
44
44
|
- Treat the section as append-mostly unless an entry is proven obsolete.
|
|
45
|
-
- Never instruct agents to
|
|
46
|
-
is a bundled CLI, not a bash
|
|
47
|
-
(FIX-274). Skill steps call
|
|
45
|
+
- Never instruct agents to source the `roll` binary as if it were a shell
|
|
46
|
+
library: the TS-native `roll` is a bundled CLI, not a bash script, and
|
|
47
|
+
`source "$(command -v roll)"` executes JS as shell (FIX-274). Skill steps call
|
|
48
|
+
`roll <command>` directly.
|
|
48
49
|
- Skills do NOT self-score (FIX-343). The working agent never scores its own
|
|
49
50
|
story; the Review Score is a runner-side peer-review outcome, produced by a
|
|
50
51
|
Reviewer in a FRESH, separate session (never a sub-agent of the builder's
|
|
@@ -86,30 +86,19 @@ reason: <one short line — which condition triggered, with numbers>
|
|
|
86
86
|
When `verdict: ok` → continue to Step A2 normally.
|
|
87
87
|
When `verdict: too_big` → go to **US-AGENT-008 self-downgrade path**, **but** first run the **US-AGENT-009 chain_depth cap check**:
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
# 0a. Cap check: refuse the third consecutive auto-split.
|
|
91
|
-
# exit 0 → split allowed; exit 1 → cap hit, take cap-hit path instead.
|
|
92
|
-
if ! bash -c 'source "$(command -v roll)"; _loop_chain_depth_cap_check US-XXX-NNN'; then
|
|
93
|
-
# Cap hit (chain_depth ≥ 2): hold + ALERT, exit cleanly.
|
|
94
|
-
bash -c 'source "$(command -v roll)"; _loop_split_cap_hit US-XXX-NNN "depth >= 2, human triage required"'
|
|
95
|
-
exit 0
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
# 1. Invoke roll-design to re-split the story into smaller sub-stories.
|
|
99
|
-
# Each sub-story carries chain_depth = (parent.chain_depth + 1).
|
|
100
|
-
# Sub-stories land as 📋 Todo with depends-on:<parent> chained.
|
|
101
|
-
Skill("roll-design", "--from-story US-XXX-NNN")
|
|
102
|
-
|
|
103
|
-
# 2. After the sub-stories are written to BACKLOG, flip the parent
|
|
104
|
-
# to 🚫 Hold and emit the downgrade event. The helper handles ALERT.
|
|
105
|
-
bash -c 'source "$(command -v roll)"; _loop_self_downgrade US-XXX-NNN "too_big: <reason from verdict>" "US-XXX-NNNa,US-XXX-NNNb"'
|
|
89
|
+
> **v3 note (FIX-364)**: the retired bash helpers `_loop_chain_depth_cap_check`, `_loop_split_cap_hit`, and `_loop_self_downgrade` were removed with the v2 bash engine. v3 `roll` is a TS binary and cannot be sourced. The equivalent self-downgrade surface is being rebuilt in **US-AGENT-042** as `roll loop self-downgrade <story> <reason> <sub-ids>`; until that lands, the skill should **not** invoke the dead bash helpers above. If a story is genuinely too big for a single cycle, raise an ALERT and exit cleanly without TCR commits.
|
|
106
90
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
1. Invoke `roll-design` to re-split the story into smaller sub-stories.
|
|
92
|
+
Each sub-story carries `chain_depth = (parent.chain_depth + 1)`.
|
|
93
|
+
Sub-stories land as 📋 Todo with `depends-on:<parent>` chained.
|
|
94
|
+
2. After the sub-stories are written to BACKLOG, flip the parent to 🚫 Hold
|
|
95
|
+
and emit the downgrade event.
|
|
96
|
+
3. Exit cleanly — no TCR commits this cycle. The next loop cycle picks up
|
|
97
|
+
the first sub-story (which is smaller and should pass pre-flight).
|
|
111
98
|
|
|
112
|
-
If `roll-design` cannot produce ≥2 sub-stories (story is already irreducible),
|
|
99
|
+
If `roll-design` cannot produce ≥2 sub-stories (story is already irreducible),
|
|
100
|
+
treat it as a cap-hit: hold the parent, write an ALERT for human triage, and
|
|
101
|
+
exit cleanly. The cap exists purely to stop infinite split chains.
|
|
113
102
|
|
|
114
103
|
> Pre-flight is honest, not paranoid: a small story (est_min ≤ 8 — the `easy` tier — with chain_depth=0) should almost always go `ok`. The check pays off on the long tail — stories with a large `est_min` that, on inspection, plainly compose far more files and behaviours than one cycle can land green.
|
|
115
104
|
|
|
@@ -389,12 +378,7 @@ When any signal appears, **do not stop — flag it**:
|
|
|
389
378
|
|
|
390
379
|
Then continue implementing the current Story normally.
|
|
391
380
|
|
|
392
|
-
**Event emission** — after all TCR micro-steps for a Story complete, emit a `build` event so the cycle event stream reflects the work done
|
|
393
|
-
|
|
394
|
-
```bash
|
|
395
|
-
# _tcr_count = number of "tcr:" prefix commits made during this Story
|
|
396
|
-
_loop_event build "$US_ID" "${_tcr_count} commits" "" 2>/dev/null || true
|
|
397
|
-
```
|
|
381
|
+
**Event emission** — after all TCR micro-steps for a Story complete, emit a `build` event so the cycle event stream reflects the work done. The v3 runner writes events natively; do not call the retired bash helper `_loop_event`.
|
|
398
382
|
|
|
399
383
|
### Phase 4: E2E Deposit
|
|
400
384
|
|
|
@@ -129,18 +129,13 @@ Emit `verdict: ok` or `verdict: too_big` (with `reason:`) as the first cycle out
|
|
|
129
129
|
- `ok` → continue with step 1 below normally
|
|
130
130
|
- `too_big` → self-downgrade per US-AGENT-008, **gated by US-AGENT-009 cap check**:
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
# Cap check first (chain_depth ≥ 2 → refuse third auto-split).
|
|
134
|
-
if ! bash -c 'source "$(command -v roll)"; _loop_chain_depth_cap_check FIX-XXX-NNN'; then
|
|
135
|
-
bash -c 'source "$(command -v roll)"; _loop_split_cap_hit FIX-XXX-NNN "depth >= 2"'
|
|
136
|
-
exit 0
|
|
137
|
-
fi
|
|
138
|
-
Skill("roll-design", "--from-story FIX-XXX-NNN")
|
|
139
|
-
bash -c 'source "$(command -v roll)"; _loop_self_downgrade FIX-XXX-NNN "too_big: <reason>" "FIX-XXX-NNNa,FIX-XXX-NNNb"'
|
|
140
|
-
exit 0
|
|
141
|
-
```
|
|
132
|
+
> **v3 note (FIX-364)**: the retired bash helpers `_loop_chain_depth_cap_check`, `_loop_split_cap_hit`, and `_loop_self_downgrade` were removed with the v2 bash engine. v3 `roll` is a TS binary and cannot be sourced. The equivalent surface is being rebuilt in **US-AGENT-042** as `roll loop self-downgrade <story> <reason> <sub-ids>`; until that lands, if a fix is genuinely too big for one cycle, raise an ALERT and exit cleanly without TCR commits.
|
|
142
133
|
|
|
143
|
-
|
|
134
|
+
If split is possible, invoke `roll-design --from-story FIX-XXX-NNN` to mint
|
|
135
|
+
sub-stories, then flip the original FIX to 🚫 Hold with a `→ split to ...`
|
|
136
|
+
annotation; sub-stories carry `chain_depth + 1`. If the split cap is hit or
|
|
137
|
+
`roll-design` cannot produce ≥2 sub-stories, write an ALERT for human triage.
|
|
138
|
+
Do NOT TCR a half fix.
|
|
144
139
|
|
|
145
140
|
Bug fixes are usually small (est_min ≤ 5), so pre-flight is mostly a sanity barrier for FIXes whose underlying issue turns out structural — e.g. a "simple null check" that requires touching 12 files. Catching that upfront is cheaper than burning a cycle.
|
|
146
141
|
|
|
@@ -89,7 +89,7 @@ loop:
|
|
|
89
89
|
### Step 1 — Orphan 🔨 Recovery
|
|
90
90
|
|
|
91
91
|
Process-level crash recovery (LOCK, heartbeat, retry budget) is handled by
|
|
92
|
-
the runner
|
|
92
|
+
the v3 runner (`packages/cli/src/runner/run-cycle.ts`) — the per-project LOCK
|
|
93
93
|
guarantees only one cycle for this slug is alive when you start. So at
|
|
94
94
|
this point, any `🔨 In Progress` row in `.roll/backlog.md` belongs to a
|
|
95
95
|
previous cycle that crashed before flipping it back; reclaim it before
|
|
@@ -132,27 +132,27 @@ Before scanning BACKLOG, process open PRs first. PRs are also units of work:
|
|
|
132
132
|
external contributors and human teammates expect their PRs to be reviewed and
|
|
133
133
|
moved forward, not starved while loop opens new fronts.
|
|
134
134
|
|
|
135
|
-
Call `
|
|
135
|
+
Call `roll loop pr-inbox` after the pre-run CI check passes. It walks
|
|
136
136
|
`gh pr list --state open` and routes each PR by classification:
|
|
137
137
|
|
|
138
138
|
| Classification | Action |
|
|
139
139
|
|---|---|
|
|
140
|
-
| `loop_self` (head ref starts with `loop/` **or** `claude/`, CI not red) |
|
|
141
|
-
| `loop_self_ci_red` (loop/* PR whose CI went red) | **US-LOOP-062a**: `
|
|
140
|
+
| `loop_self` (head ref starts with `loop/` **or** `claude/`, CI not red) | squash-merge directly when CI green + clean; if the PR is BEHIND/CONFLICTING with main, rebase it first (circuit-gated) so it merges on a later tick. Never AI-review your own commit. (Agent-authored `claude/*` PRs are loop-owned the same way; a CI-red `claude/*` PR is **not** auto-healed — it falls through for a human to decide.) |
|
|
141
|
+
| `loop_self_ci_red` (loop/* PR whose CI went red) | **US-LOOP-062a**: background-heal via `roll loop pr-heal-run` (per-PR lock + heal budget `ROLL_LOOP_HEAL_MAX`, default 2, via the configured agent); on `ROLL_LOOP_NO_HEAL=1` / budget exhausted → deduped `[TYPE:loop-pr-ci-red]` ALERT (never silently dropped) |
|
|
142
142
|
| `blocked_human_request_changes` | Skip — last human review requested changes; wait for the author to push fixes |
|
|
143
|
-
| `blocked_human_approved` | **US-LOOP-062b**:
|
|
144
|
-
| `stale` (CI failed or branch behind/conflicting) |
|
|
145
|
-
| `eligible` (clean external PR, no blocking review) |
|
|
143
|
+
| `blocked_human_approved` | **US-LOOP-062b**: merge directly (`gh pr merge --squash`) when CI green + mergeable, instead of relying on repo auto-merge (which may be off); merge failure is non-fatal (retried next tick) |
|
|
144
|
+
| `stale` (CI failed or branch behind/conflicting) | Rebase onto `origin/main` after the circuit breaker allows it |
|
|
145
|
+
| `eligible` (clean external PR, no blocking review) | Review via `roll review-pr` (or the equivalent project agent skill) — the actual decision is provided by US-AUTO-035's GitHub Action |
|
|
146
146
|
|
|
147
|
-
**Rebase circuit breaker** —
|
|
148
|
-
|
|
147
|
+
**Rebase circuit breaker** — the runner records each rebase attempt under
|
|
148
|
+
`pr_state.<PR>.attempts_at` in the per-slug state file
|
|
149
149
|
(`~/.shared/roll/loop/state-<slug>.yaml`, FIX-052), pruning entries older
|
|
150
150
|
than 24 h. Once ≥3 attempts land within 24 h, further rebases are blocked and an
|
|
151
151
|
ALERT is written (typical cause: a broken workflow file makes CI never run,
|
|
152
152
|
which would otherwise drive infinite rebase loops).
|
|
153
153
|
|
|
154
154
|
**Lenient on infrastructure** — `gh` missing, repo unparseable, or any
|
|
155
|
-
`gh` API failure → `
|
|
155
|
+
`gh` API failure → `roll loop pr-inbox` returns 0 and the loop falls through to
|
|
156
156
|
Step 2 (BACKLOG scan). Same posture as the pre-run CI check.
|
|
157
157
|
|
|
158
158
|
### Step 2 — Scan BACKLOG
|
|
@@ -172,27 +172,19 @@ claimed by an **open `loop/*` PR**. Each cycle's worktree is branched from
|
|
|
172
172
|
locally until that cycle's PR merges. Without this gate, two cycles started
|
|
173
173
|
back-to-back will both pick the same Todo row and produce duplicate PRs.
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
# loop/* PRs on the remote. SKIP any candidate whose ID appears.
|
|
179
|
-
# exit 0 always (lenient: gh missing / API error → empty output).
|
|
180
|
-
```
|
|
175
|
+
Use `roll loop pr-inbox` to discover story IDs already claimed by open
|
|
176
|
+
`loop/*` PRs on the remote. Skip any candidate whose ID appears. The runner is
|
|
177
|
+
lenient: `gh` missing / API error → empty claim list.
|
|
181
178
|
|
|
182
|
-
**Dependency gate** (FIX-032). For each `📋 Todo` candidate, before picking
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
bash -c 'source "$(command -v roll)"; _loop_check_depends_on "<story-id>" .roll/backlog.md'
|
|
189
|
-
# exit 0 → all `depends-on:US-X,US-Y` are ✅ Done → eligible
|
|
190
|
-
# exit 1 → stdout lists unsatisfied dep IDs; SKIP this story, log to
|
|
191
|
-
# runs.jsonl `skipped` with reason "depends-on: <unsatisfied>"
|
|
192
|
-
```
|
|
179
|
+
**Dependency gate** (FIX-032). For each `📋 Todo` candidate, before picking,
|
|
180
|
+
check that every `depends-on:<ID>` referenced in the story's backlog row is
|
|
181
|
+
already ✅ Done. The v3 runner evaluates dependencies natively; do not call the
|
|
182
|
+
retired bash helper `_loop_check_depends_on`. If a dependency is unsatisfied,
|
|
183
|
+
skip the story and log to `runs.jsonl` `skipped` with reason
|
|
184
|
+
`"depends-on: <unsatisfied>"`.
|
|
193
185
|
|
|
194
186
|
Move to the next candidate when skipping. The gate is a pure function
|
|
195
|
-
over
|
|
187
|
+
over `.roll/backlog.md` text — no side effects, no LOCK interaction.
|
|
196
188
|
|
|
197
189
|
Cap at `max_items_per_run` to limit blast radius per cycle.
|
|
198
190
|
|
|
@@ -200,7 +192,7 @@ Cap at `max_items_per_run` to limit blast radius per cycle.
|
|
|
200
192
|
|
|
201
193
|
Loop has two layers of concurrency protection:
|
|
202
194
|
|
|
203
|
-
1. **Per-project LOCK** (enforced by runner
|
|
195
|
+
1. **Per-project LOCK** (enforced by the v3 runner, see `packages/cli/src/runner/run-cycle.ts`):
|
|
204
196
|
- LOCK file path: `~/.shared/roll/loop/.LOCK-<project-slug>`
|
|
205
197
|
- On launch: if LOCK exists and the PID inside is alive → exit 0 (previous loop still running)
|
|
206
198
|
- On launch: if LOCK exists but PID is dead → clean up stale LOCK and continue
|
|
@@ -219,42 +211,30 @@ Together these mean: only one loop runs at a time per project (LOCK), and within
|
|
|
219
211
|
|
|
220
212
|
> **US-AGENT-006 — Per-story agent routing (pre-cycle)**
|
|
221
213
|
>
|
|
222
|
-
> Before this skill even starts, the runner
|
|
223
|
-
> 1. Picked the next eligible Todo
|
|
224
|
-
> 2. Read its Agent profile (est_min / risk_zone) and routed an agent
|
|
225
|
-
> 3. Exported `ROLL_LOOP_ROUTED_STORY` / `ROLL_LOOP_ROUTED_AGENT` / `ROLL_LOOP_ROUTED_RULE` and printed `[loop] story <id> routed to <agent> via <rule_kind>` to cron.log
|
|
214
|
+
> Before this skill even starts, the v3 runner has already:
|
|
215
|
+
> 1. Picked the next eligible Todo (priority FIX > US > REFACTOR, depends-on gate respected).
|
|
216
|
+
> 2. Read its Agent profile (`est_min` / `risk_zone`) and routed an agent (hard rules from `.roll/agent-routes.yaml` + soft preference from `runs.jsonl`).
|
|
217
|
+
> 3. Exported `ROLL_LOOP_ROUTED_STORY` / `ROLL_LOOP_ROUTED_AGENT` / `ROLL_LOOP_ROUTED_RULE` and printed `[loop] story <id> routed to <agent> via <rule_kind>` to cron.log.
|
|
226
218
|
>
|
|
227
|
-
> When `ROLL_LOOP_ROUTED_STORY` is set, prefer it as `US_ID` for this cycle. The story has already been chosen by hard+soft routing rules — and, per FIX-146, the runner re-validates it against the authoritative backlog right before handing it to you (re-picking the next eligible Todo if it went ✅ Done / In Progress / ineligible between pick and handoff, emitting a `story_stale` event). So treat `ROLL_LOOP_ROUTED_STORY` as already-eligible and just work it. Only if you still find at cycle start that it is no longer 📋 Todo in BACKLOG (a residual concurrent flip),
|
|
219
|
+
> When `ROLL_LOOP_ROUTED_STORY` is set, prefer it as `US_ID` for this cycle. The story has already been chosen by hard+soft routing rules — and, per FIX-146, the runner re-validates it against the authoritative backlog right before handing it to you (re-picking the next eligible Todo if it went ✅ Done / In Progress / ineligible between pick and handoff, emitting a `story_stale` event). So treat `ROLL_LOOP_ROUTED_STORY` as already-eligible and just work it. Only if you still find at cycle start that it is no longer 📋 Todo in BACKLOG (a residual concurrent flip), signal `story_stale` and let the runner pick the next eligible Todo rather than idling the whole cycle.
|
|
228
220
|
>
|
|
229
221
|
> Old single-agent fallback (`primary_agent` from `~/.roll/config.yaml`) still applies when:
|
|
230
222
|
> - no story is pickable (empty Todo / all blocked by depends-on)
|
|
231
223
|
> - the matching agent-routes.yaml has no agent that fits the story profile (then `cold_start_default` is used)
|
|
232
224
|
|
|
233
|
-
For each item, **before invoking the executor skill**, mark the story 🔨 In Progress in the **main repo's**
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
bash -c 'source "$(command -v roll)"; _loop_mark_in_progress US-XXX'
|
|
237
|
-
# Updates ${ROLL_MAIN_PROJECT}/.roll/backlog.md in place: flips the row
|
|
238
|
-
# containing US-XXX from "📋 Todo" to "🔨 In Progress". Idempotent.
|
|
239
|
-
```
|
|
225
|
+
For each item, **before invoking the executor skill**, mark the story 🔨 In Progress in the **main repo's** `.roll/backlog.md` so brief and peer agents can see it being worked on. The cycle worktree is gitignored at `.roll/`, so editing the worktree's own copy + committing carries no change back to main — write directly via the backlog store instead. The v3 runner updates `${ROLL_MAIN_PROJECT}/.roll/backlog.md` in place; do not call the retired bash helpers `_loop_mark_in_progress` / `_loop_mark_todo`.
|
|
240
226
|
|
|
241
|
-
If the executor fails (TCR aborts, CI red, etc.), revert the marker so the next cycle can re-pick the story
|
|
227
|
+
If the executor fails (TCR aborts, CI red, etc.), revert the marker so the next cycle can re-pick the story.
|
|
242
228
|
|
|
243
|
-
|
|
244
|
-
bash -c 'source "$(command -v roll)"; _loop_mark_todo US-XXX'
|
|
245
|
-
```
|
|
229
|
+
Status flips happen in main directly — no per-cycle commit needed. `roll-brief` reads main's backlog, so the 🔨 marker is visible the moment the update returns.
|
|
246
230
|
|
|
247
|
-
|
|
231
|
+
选定故事后,发出 `pick_todo` 事件,让 dashboard / monitor / attach 都能把"这个 cycle 选了哪个 story"正确归类。 The v3 runner emits events natively; do not call the retired bash helper `_loop_event`.
|
|
248
232
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
# 不是 US_ID — dashboard 按 label 聚类,US_ID 当 label 会让事件分到错的桶
|
|
255
|
-
# 里,cycle 看起来"有 token 没 ID"。
|
|
256
|
-
_loop_event pick_todo "$LOOP_CYCLE_ID" "$US_ID" ""
|
|
257
|
-
```
|
|
233
|
+
- Emit immediately after picking and before invoking the executor skill.
|
|
234
|
+
- `label` must be the `cycle_id` (from the `LOOP_CYCLE_ID` environment variable),
|
|
235
|
+
not `US_ID` — the dashboard groups by label, and using `US_ID` as the label
|
|
236
|
+
would put events in the wrong bucket, making the cycle appear to have tokens
|
|
237
|
+
but no ID.
|
|
258
238
|
|
|
259
239
|
Then invoke the executor:
|
|
260
240
|
|
|
@@ -287,8 +267,8 @@ After each item completes:
|
|
|
287
267
|
- Count `tcr:` prefix commits since `started_at` via `git log --oneline --since=<started_at>`
|
|
288
268
|
- Count == 0 → revert story status in .roll/backlog.md from ✅ Done → 📋 Todo; write ALERT to `~/.shared/roll/loop/ALERT-<slug>.md` with story ID, time, reason "zero tcr: commits since story start", and suggested actions (`roll loop now` / `$roll-build <id>` / `roll loop reset`)
|
|
289
269
|
- Count > 0 → continue normally
|
|
290
|
-
2. **CI Gate** — **MUST** invoke `roll ci --wait
|
|
291
|
-
|
|
270
|
+
2. **CI Gate** — **MUST** invoke `roll ci --wait`. **Do NOT call `gh` directly**
|
|
271
|
+
(no `gh run list`, no `gh run watch`,
|
|
292
272
|
no ad-hoc shell checks): `roll ci --wait` is the only sanctioned entry —
|
|
293
273
|
it derives `owner/repo` from the git remote and uses `gh -R <slug>`, which
|
|
294
274
|
is required to work through `~/.ssh/config` host rewrites that break gh's
|
|
@@ -327,7 +307,7 @@ After each item completes:
|
|
|
327
307
|
merges / rebases / closes it asynchronously. There is no false-Done risk:
|
|
328
308
|
with worktree isolation the ✅ Done lives only in the unmerged PR, never on
|
|
329
309
|
the loop's main checkout, and the story is not re-picked meanwhile via the
|
|
330
|
-
open-PR eligibility gate (
|
|
310
|
+
open-PR eligibility gate (FIX-146). The story's
|
|
331
311
|
✅ Done lands on main only when the PR Loop actually merges the PR.
|
|
332
312
|
2. Write ALERT to `~/.shared/roll/loop/ALERT-<slug>.md` with:
|
|
333
313
|
- story ID, time, commit SHA
|
|
@@ -346,10 +326,9 @@ After each item completes:
|
|
|
346
326
|
|
|
347
327
|
### Step 5 — Write Run Summary
|
|
348
328
|
|
|
349
|
-
> **FIX-044**: The
|
|
350
|
-
>
|
|
351
|
-
>
|
|
352
|
-
> final report for `cron.log` visibility.
|
|
329
|
+
> **FIX-044**: The v3 runner (`packages/cli/src/runner/run-cycle.ts`) appends
|
|
330
|
+
> this record deterministically at cycle end. The agent should still emit a run
|
|
331
|
+
> summary in the cycle's final report for `cron.log` visibility.
|
|
353
332
|
|
|
354
333
|
After all items in this cycle:
|
|
355
334
|
|
|
@@ -58,13 +58,7 @@ Allowed states only. No invented words.
|
|
|
58
58
|
- **OBJECT**: The proposal is wrong. Provide an alternative. Proceed to next round.
|
|
59
59
|
- **ESCALATE**: Round 3 reached without AGREE, or a round fails due to API/token error. Hand off to the human user.
|
|
60
60
|
|
|
61
|
-
After each round decision, emit a `peer` event to the cycle event stream
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# $round = current round number, $total = max rounds, $verdict = AGREE/REFINE/OBJECT/ESCALATE
|
|
65
|
-
# $agents = e.g. "claude→deepseek"
|
|
66
|
-
_loop_event peer "${round}/${total}" "$verdict" "$agents" 2>/dev/null || true
|
|
67
|
-
```
|
|
61
|
+
After each round decision, emit a `peer` event to the cycle event stream. The v3 runner writes events natively; do not call the retired bash helper `_loop_event`.
|
|
68
62
|
|
|
69
63
|
If information is insufficient:
|
|
70
64
|
```
|
|
@@ -61,16 +61,6 @@
|
|
|
61
61
|
"ask another agent for peer negotiation"
|
|
62
62
|
]
|
|
63
63
|
},
|
|
64
|
-
"roll-brief": {
|
|
65
|
-
"positive": [
|
|
66
|
-
"prepare an owner-facing digest of completed and in-progress Roll work",
|
|
67
|
-
"summarize backlog queue, escalations, and release readiness"
|
|
68
|
-
],
|
|
69
|
-
"negative": [
|
|
70
|
-
"write public release notes for users",
|
|
71
|
-
"capture a one-line idea into backlog"
|
|
72
|
-
]
|
|
73
|
-
},
|
|
74
64
|
"roll-build": {
|
|
75
65
|
"positive": [
|
|
76
66
|
"execute US-AUTH-001 through TCR and verification",
|
|
@@ -211,16 +201,6 @@
|
|
|
211
201
|
"run attacker and defender agents for high-risk logic"
|
|
212
202
|
]
|
|
213
203
|
},
|
|
214
|
-
"roll-sentinel": {
|
|
215
|
-
"positive": [
|
|
216
|
-
"sample production behavior against backlog requirements",
|
|
217
|
-
"run cost-controlled patrol checks on deployed flows"
|
|
218
|
-
],
|
|
219
|
-
"negative": [
|
|
220
|
-
"scan code architecture for refactor candidates",
|
|
221
|
-
"debug a local browser page with console capture"
|
|
222
|
-
]
|
|
223
|
-
},
|
|
224
204
|
"roll-spar": {
|
|
225
205
|
"positive": [
|
|
226
206
|
"use adversarial TDD for auth or payment logic",
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roll-brief
|
|
3
|
-
license: MIT
|
|
4
|
-
allowed-tools: "Read, Glob, Grep, Write, Bash(git:*)"
|
|
5
|
-
description: "Load when the owner asks for an internal Roll briefing summarizing completed work, in-progress items, backlog queue, escalations, and release readiness."
|
|
6
|
-
---
|
|
7
|
-
# Roll Brief
|
|
8
|
-
|
|
9
|
-
## Gotchas
|
|
10
|
-
|
|
11
|
-
- Brief is owner-facing internal context, not public changelog copy.
|
|
12
|
-
- Call out escalations and release readiness explicitly; do not flatten them into a generic progress summary.
|
|
13
|
-
|
|
14
|
-
> Follows the Architecture Constraints, Development Discipline, and Engineering
|
|
15
|
-
> Common Sense defined in the project AGENTS.md.
|
|
16
|
-
|
|
17
|
-
Owner-facing digest of autonomous agent activity. Gives the human everything
|
|
18
|
-
needed to decide whether to cut a new release — without having to read every
|
|
19
|
-
commit or diff.
|
|
20
|
-
|
|
21
|
-
## Distinct from roll-.changelog
|
|
22
|
-
|
|
23
|
-
| | roll-brief | roll-.changelog |
|
|
24
|
-
|--|-----------|----------------|
|
|
25
|
-
| **Audience** | Product owner (internal) | End users (public) |
|
|
26
|
-
| **Content** | All activity including REFACTOR, escalations, health signals | Only user-visible feature changes |
|
|
27
|
-
| **Trigger** | Feature completion / daily / on-demand | Post-deploy |
|
|
28
|
-
| **Tone** | Operational, candid | Product-facing, polished |
|
|
29
|
-
|
|
30
|
-
## Trigger Modes
|
|
31
|
-
|
|
32
|
-
### 1. Feature Completion (auto)
|
|
33
|
-
|
|
34
|
-
Triggered by `roll-loop` when a set of related Stories under one Feature are
|
|
35
|
-
all marked ✅ Done. The loop passes the Feature name as context.
|
|
36
|
-
|
|
37
|
-
### 2. Daily Morning (scheduled)
|
|
38
|
-
|
|
39
|
-
Runs at a fixed time each morning (configurable in `~/.roll/config.yaml`).
|
|
40
|
-
Covers all activity since the previous brief.
|
|
41
|
-
|
|
42
|
-
```yaml
|
|
43
|
-
# ~/.roll/config.yaml
|
|
44
|
-
brief:
|
|
45
|
-
daily_time: "08:00" # local time
|
|
46
|
-
timezone: "Asia/Shanghai"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 3. On-Demand
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
$roll-brief # since last brief
|
|
53
|
-
$roll-brief --since 2026-05-09 # since specific date
|
|
54
|
-
$roll-brief --feature auth # scoped to one feature
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Workflow
|
|
58
|
-
|
|
59
|
-
### Step 1 — Determine Scope
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
# Find timestamp of last brief
|
|
63
|
-
ls .roll/briefs/ | sort | tail -1
|
|
64
|
-
|
|
65
|
-
# Read .roll/backlog.md — collect all status changes since last brief
|
|
66
|
-
# Read git log — commits since last brief timestamp
|
|
67
|
-
git log --since="{last_brief_timestamp}" --oneline
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Step 2 — Collect Activity
|
|
71
|
-
|
|
72
|
-
From .roll/backlog.md and git log, classify all items since last brief:
|
|
73
|
-
|
|
74
|
-
- **Completed**: US-XXX ✅, FIX-XXX ✅, REFACTOR-XXX ✅
|
|
75
|
-
- **In progress**: items currently 🔨
|
|
76
|
-
- **Queue**: items still 📋 Todo (ordered by priority)
|
|
77
|
-
- **Dream findings**: any REFACTOR entries added by roll-.dream since last brief
|
|
78
|
-
- **Escalations**: any ALERT files in `~/.shared/roll/loop/` or `~/.shared/roll/dream/`
|
|
79
|
-
- **Doc coverage**: compute from `guide/en/` and `guide/zh/`:
|
|
80
|
-
- EN coverage = number of files in `guide/en/`
|
|
81
|
-
- ZH translation rate = files in `guide/zh/` ÷ files in `guide/en/` × 100%
|
|
82
|
-
|
|
83
|
-
### Step 3 — Assess Release Readiness
|
|
84
|
-
|
|
85
|
-
A simple heuristic — not a gate, just a signal for the human:
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
✅ Release candidate if:
|
|
89
|
-
- No 🔨 in-progress US items
|
|
90
|
-
- No open ESCALATE alerts
|
|
91
|
-
- CI is green (check latest workflow run)
|
|
92
|
-
- No critical REFACTOR entries flagged in last 48h
|
|
93
|
-
|
|
94
|
-
⚠️ Hold if any of the above is false
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Step 4 — Write Brief
|
|
98
|
-
|
|
99
|
-
文件命名:`.roll/briefs/YYYY-MM-DD-{NN}.md`,NN 为当日序号(01 起,零填充两位)。
|
|
100
|
-
计算方式:`ls .roll/briefs/YYYY-MM-DD-*.md 2>/dev/null | wc -l`,+1 即为本次序号。
|
|
101
|
-
|
|
102
|
-
全部用中文输出。**省略空 section**(无内容时连标题一起不输出):
|
|
103
|
-
|
|
104
|
-
```markdown
|
|
105
|
-
# 简报 {YYYY-MM-DD HH:mm}
|
|
106
|
-
|
|
107
|
-
> 触发:{触发原因} | 覆盖:{起止时间范围}
|
|
108
|
-
|
|
109
|
-
## 已完成({N} 项)
|
|
110
|
-
| 编号 | 描述 | 类型 |
|
|
111
|
-
|----|-------------|------|
|
|
112
|
-
| US-XXX | {标题} | 用户故事 |
|
|
113
|
-
| FIX-XXX | {标题} | 缺陷修复 |
|
|
114
|
-
| REFACTOR-XXX | {标题} | 重构 |
|
|
115
|
-
|
|
116
|
-
<!-- 仅当有 🔨 条目时输出 -->
|
|
117
|
-
## 进行中
|
|
118
|
-
| 编号 | 描述 |
|
|
119
|
-
|----|-------------|
|
|
120
|
-
| US-XXX | {标题} — 开始于 {date} |
|
|
121
|
-
|
|
122
|
-
<!-- 仅当有 📋 条目时输出 -->
|
|
123
|
-
## 待处理队列({N} 项)
|
|
124
|
-
| 编号 | 描述 | 优先级 |
|
|
125
|
-
|----|-------------|----------|
|
|
126
|
-
| US-XXX | {标题} | 高 |
|
|
127
|
-
|
|
128
|
-
<!-- US-AGENT-010: per-agent hit-rate summary (one line). Read the last
|
|
129
|
-
window_cycles records of runs.jsonl, group by `agent`, format as
|
|
130
|
-
`agents: pi 8/22 (36%) · deepseek 5/8 (63%)`. Sample < 5 → `(n/a)`.
|
|
131
|
-
Omit when no records have an agent field (legacy data). -->
|
|
132
|
-
## Agent 路由命中率
|
|
133
|
-
{agents: <name> built/total (pct%) · …} ← from `runs.jsonl` last 50 cycles
|
|
134
|
-
|
|
135
|
-
<!-- 仅当 roll-.dream 有新发现时输出 -->
|
|
136
|
-
## 悟见
|
|
137
|
-
{来自 .roll/dream/ 的摘要}
|
|
138
|
-
|
|
139
|
-
<!-- 仅当有 ESCALATE 告警时输出 -->
|
|
140
|
-
## 需人工介入
|
|
141
|
-
{告警内容}
|
|
142
|
-
|
|
143
|
-
<!-- 始终输出 doc coverage 数字;若无缺口写"覆盖完整" -->
|
|
144
|
-
## 文档覆盖度
|
|
145
|
-
- guide/en: {N} 个文档
|
|
146
|
-
- ZH 翻译率:{M}/{N}({%})
|
|
147
|
-
- {缺口列表 或 "覆盖完整,无缺口。"}
|
|
148
|
-
|
|
149
|
-
## 发版就绪
|
|
150
|
-
{✅ 可发版 / ⚠️ 暂缓 — 原因}
|
|
151
|
-
|
|
152
|
-
**下一版本:** `v{YYYY}.{MMDD}.{序号}`
|
|
153
|
-
|
|
154
|
-
- {本轮新增 1}
|
|
155
|
-
- {本轮新增 2}
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
*状态:进行中 {N} · 待处理 {N} · 告警 {N} | 下次简报:{datetime}*
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**首份简报或传入 `--full-history`**:在"已完成"表格后追加历史汇总区块:
|
|
162
|
-
|
|
163
|
-
```markdown
|
|
164
|
-
### 历史汇总
|
|
165
|
-
**Epic: {Name}** — {done}/{total} ✅
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Step 4.5 — Commit Brief
|
|
169
|
-
|
|
170
|
-
写完文件后立即提交,让简报进入 git 历史,便于后续追溯与跨会话审计:
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
git add .roll/briefs/YYYY-MM-DD-NN.md
|
|
174
|
-
git commit -m "docs: roll-brief YYYY-MM-DD-NN — {触发原因}"
|
|
175
|
-
git push origin main
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
- 触发原因来自调用上下文(Feature 完成 / 每日 / 手动 / `--feature` / `--since`),用一句话填入
|
|
179
|
-
- 写文件失败时不要执行 commit;保持工作区干净,由调用方处理重试
|
|
180
|
-
- 仅 `.roll/briefs/` 下新文件入 commit,不要顺带带入其他无关变更
|
|
181
|
-
|
|
182
|
-
### Step 5 — Notify
|
|
183
|
-
|
|
184
|
-
写完文件后在终端或 CI 日志中打印简报路径:
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
📋 $(msg brief.generated ".roll/briefs/YYYY-MM-DD-NN.md")
|
|
188
|
-
$(msg brief.release_readiness): ✅ $(msg brief.release_ready_status)
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
有升级事项时须显著打印,不得遗漏。
|
|
192
|
-
|
|
193
|
-
## Scheduler Configuration
|
|
194
|
-
|
|
195
|
-
roll-brief runs **locally**, triggered either by roll-loop (on Feature
|
|
196
|
-
completion) or by local cron (daily morning). The agent reads local
|
|
197
|
-
BACKLOG state and git history directly.
|
|
198
|
-
|
|
199
|
-
### Local cron (daily morning)
|
|
200
|
-
|
|
201
|
-
Installed automatically via `roll loop on` alongside roll-loop and roll-.dream.
|
|
202
|
-
The cron entry is generated using the configured agent — no manual cron editing needed.
|
|
203
|
-
|
|
204
|
-
### Triggered by roll-loop
|
|
205
|
-
|
|
206
|
-
When roll-loop detects a Feature is fully complete, it invokes roll-brief
|
|
207
|
-
automatically — no separate cron entry needed for that trigger.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roll-sentinel
|
|
3
|
-
license: MIT
|
|
4
|
-
allowed-tools: "Read, Edit, Write, Bash, WebFetch"
|
|
5
|
-
description: "Load when production or deployed behavior needs cost-controlled randomized patrol checks based on backlog requirements and runtime sampling."
|
|
6
|
-
---
|
|
7
|
-
# Roll Sentinel
|
|
8
|
-
|
|
9
|
-
This hub keeps the routing boundary, hard gates, and execution skeleton in the initial context. Load the heavier runbook only when the task actually needs the detailed contract.
|
|
10
|
-
|
|
11
|
-
## Load
|
|
12
|
-
|
|
13
|
-
Load when production or deployed behavior needs cost-controlled randomized patrol checks based on backlog requirements and runtime sampling.
|
|
14
|
-
|
|
15
|
-
## When Not to Use
|
|
16
|
-
|
|
17
|
-
- Code health scans; load roll-.dream.
|
|
18
|
-
- Interactive page debugging; load roll-debug.
|
|
19
|
-
|
|
20
|
-
## Read On Demand
|
|
21
|
-
|
|
22
|
-
- Read [the full contract](references/full-contract.md) before executing the workflow end to end, recovering from failures, or checking exact output templates.
|
|
23
|
-
- Keep this hub in context for trigger boundaries and hard gates.
|
|
24
|
-
|
|
25
|
-
## Workflow Skeleton
|
|
26
|
-
|
|
27
|
-
1. Select sampling targets from backlog requirements.
|
|
28
|
-
2. Run randomized cost-controlled checks.
|
|
29
|
-
3. Validate observed production behavior.
|
|
30
|
-
4. Record patrol evidence and escalate anomalies.
|
|
31
|
-
|
|
32
|
-
## Hard Gates
|
|
33
|
-
|
|
34
|
-
- Sampling budget remains explicit.
|
|
35
|
-
- Do not turn sentinel into exhaustive monitoring.
|
|
36
|
-
|
|
37
|
-
## Gotchas
|
|
38
|
-
|
|
39
|
-
- Sentinel samples deployed behavior; it is not a code architecture scanner.
|
|
40
|
-
- Keep cost controls and randomized sampling visible; do not turn patrols into exhaustive monitoring.
|
|
41
|
-
|
|
42
|
-
## Maintenance
|
|
43
|
-
|
|
44
|
-
- Description changes require updates in `route-cases/skills.json`.
|
|
45
|
-
- New observed failures should add a gotcha and the matching positive or negative route case.
|
|
46
|
-
- Heavy examples, templates, recovery paths, and deterministic snippets belong in `references/`, `assets/`, or `scripts/`, not in this hub.
|