@seanyao/roll 3.621.1 → 3.624.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 +28 -0
- package/dist/roll.mjs +2807 -2405
- package/package.json +1 -1
- package/lib/__pycache__/changelog_audit.cpython-314.pyc +0 -0
- package/lib/__pycache__/github_sync.cpython-314.pyc +0 -0
- package/lib/__pycache__/loop-fmt.cpython-314.pyc +0 -0
- package/lib/__pycache__/loop_result_eval.cpython-314.pyc +0 -0
- package/lib/__pycache__/loop_unstick.cpython-314.pyc +0 -0
- package/lib/__pycache__/model_prices.cpython-314.pyc +0 -0
- package/lib/__pycache__/prices_fetcher.cpython-314.pyc +0 -0
- package/lib/__pycache__/roll-home.cpython-314.pyc +0 -0
- package/lib/__pycache__/roll-loop-status.cpython-314.pyc +0 -0
- package/lib/__pycache__/roll_git.cpython-314.pyc +0 -0
- package/lib/__pycache__/roll_render.cpython-314.pyc +0 -0
- package/lib/__pycache__/slides-render.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/__init__.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/gemini.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/kimi.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/openai.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/pi.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/pi_emit.cpython-314.pyc +0 -0
- package/lib/agent_usage/__pycache__/qwen.cpython-314.pyc +0 -0
- package/skills/README.md +0 -64
- package/skills/docs/skill-authoring.md +0 -74
- package/skills/reports/skill-audit-summary.md +0 -53
- package/skills/roll-.changelog/SKILL.md +0 -47
- package/skills/roll-.changelog/references/full-contract.md +0 -462
- package/skills/roll-.clarify/SKILL.md +0 -64
- package/skills/roll-.dream/SKILL.md +0 -47
- package/skills/roll-.dream/references/full-contract.md +0 -365
- package/skills/roll-.echo/SKILL.md +0 -118
- package/skills/roll-.qa/SKILL.md +0 -47
- package/skills/roll-.qa/references/full-contract.md +0 -256
- package/skills/roll-.review/SKILL.md +0 -148
- package/skills/roll-build/SKILL.md +0 -49
- package/skills/roll-build/references/full-contract.md +0 -968
- package/skills/roll-debug/SKILL.md +0 -48
- package/skills/roll-debug/assets/injectable-bb.js +0 -263
- package/skills/roll-debug/references/full-contract.md +0 -607
- package/skills/roll-design/SKILL.md +0 -52
- package/skills/roll-design/references/engineering-checklist.md +0 -298
- package/skills/roll-design/references/full-contract.md +0 -940
- package/skills/roll-doc-audit/SKILL.md +0 -51
- package/skills/roll-doc-audit/references/full-contract.md +0 -796
- package/skills/roll-doctor/SKILL.md +0 -211
- package/skills/roll-fix/SKILL.md +0 -49
- package/skills/roll-fix/references/full-contract.md +0 -672
- package/skills/roll-idea/SKILL.md +0 -62
- package/skills/roll-loop/SKILL.md +0 -50
- package/skills/roll-loop/references/full-contract.md +0 -534
- package/skills/roll-notes/SKILL.md +0 -107
- package/skills/roll-onboard/SKILL.md +0 -238
- package/skills/roll-peer/SKILL.md +0 -47
- package/skills/roll-peer/references/full-contract.md +0 -323
- package/skills/roll-propose/SKILL.md +0 -155
- package/skills/roll-review-pr/SKILL.md +0 -62
- package/skills/roll-spar/SKILL.md +0 -47
- package/skills/roll-spar/references/full-contract.md +0 -288
- package/skills/route-cases/skills.json +0 -216
- package/skills/scripts/audit-skills.mjs +0 -272
- package/skills/scripts/test-audit-skills.mjs +0 -39
- package/skills/tests/fixtures/skill-audit/block-skill/SKILL.md +0 -12
- package/skills/tests/fixtures/skill-audit/minimal-skill/SKILL.md +0 -8
- package/skills/tests/fixtures/skill-audit/quoted-skill/SKILL.md +0 -10
- package/skills/tests/fixtures/skill-audit/route-cases.json +0 -21
- package/skills/tests/fixtures/skill-audit/spoke-skill/SKILL.md +0 -12
- package/skills/tests/fixtures/skill-audit/spoke-skill/references/runbook.md +0 -3
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roll-idea
|
|
3
|
-
license: MIT
|
|
4
|
-
allowed-tools: "Read, Edit"
|
|
5
|
-
description: "Load when the user gives a short idea or bug note that should be quickly classified, assigned an ID, and appended to backlog."
|
|
6
|
-
---
|
|
7
|
-
# roll-idea
|
|
8
|
-
|
|
9
|
-
## Gotchas
|
|
10
|
-
|
|
11
|
-
- Capture is intentionally shallow; do not expand into full DDD stories unless roll-design is invoked.
|
|
12
|
-
- Do not overwrite existing backlog numbering or statuses while appending the quick capture.
|
|
13
|
-
|
|
14
|
-
> One-liner in, backlog entry out. No questions asked.
|
|
15
|
-
|
|
16
|
-
## Trigger
|
|
17
|
-
|
|
18
|
-
User explicitly invokes `roll-idea` with a free-text description.
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
$roll-idea 评价页面的星星也要纳入到 draft 的 scope 里
|
|
22
|
-
$roll-idea 手机端星星指标一行一个从上往下排
|
|
23
|
-
$roll-idea 给 HOD 加一个批量导出 PDF 的功能
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## When Not to Use
|
|
27
|
-
|
|
28
|
-
- Requirement needs discussion or splitting into Stories (use `$roll-design`)
|
|
29
|
-
- A US-XXX / FIX-XXX is ready to execute (use `$roll-build` / `$roll-fix`)
|
|
30
|
-
- Recording a development moment or feeling (use `$roll-notes`)
|
|
31
|
-
|
|
32
|
-
## Behavior
|
|
33
|
-
|
|
34
|
-
1. **Read** `.roll/backlog.md` from the project root.
|
|
35
|
-
2. **Classify** the input:
|
|
36
|
-
- If it describes a defect, regression, broken behavior, or "也要/没/不/bug" → **bug**
|
|
37
|
-
- Otherwise → **idea**
|
|
38
|
-
3. **Assign ID**:
|
|
39
|
-
- Bug → next `FIX-NNN`
|
|
40
|
-
- Idea → next `IDEA-NNN`
|
|
41
|
-
4. **Append** a new row to the appropriate table in `.roll/backlog.md`:
|
|
42
|
-
- Bug → `## 🐛 Bug Fixes` table
|
|
43
|
-
- Idea → `## 💡 Ideas` table (create the section if it doesn't exist)
|
|
44
|
-
5. **Update stats** line if present (e.g. `Bug Fixes: N`, `Ideas: N`).
|
|
45
|
-
6. **Report** the assigned ID and where it was recorded.
|
|
46
|
-
|
|
47
|
-
## Output format
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
📝 Recorded as {ID}
|
|
51
|
-
|
|
52
|
-
Type: {bug|idea}
|
|
53
|
-
Table: {Bug Fixes|Ideas}
|
|
54
|
-
Text: {description}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Rules
|
|
58
|
-
|
|
59
|
-
- Do **not** ask the user for clarification.
|
|
60
|
-
- If the description is vague, record it verbatim and append `(细节待确认)`.
|
|
61
|
-
- Never modify existing entries — only append new rows.
|
|
62
|
-
- If `.roll/backlog.md` does not exist, report an error and stop.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: roll-loop
|
|
3
|
-
license: MIT
|
|
4
|
-
allowed-tools: "Read, Glob, Grep, Write, Edit, Bash(git:*), Bash(cat:*), Skill"
|
|
5
|
-
description: "Load when configuring, explaining, or operating Roll autonomous backlog execution loop that scans Todo work and dispatches US/FIX/REFACTOR items."
|
|
6
|
-
---
|
|
7
|
-
# Roll Loop
|
|
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 configuring, explaining, or operating Roll autonomous backlog execution loop that scans Todo work and dispatches US/FIX/REFACTOR items.
|
|
14
|
-
|
|
15
|
-
## When Not to Use
|
|
16
|
-
|
|
17
|
-
- One-shot story execution by a human agent; load roll-build or roll-fix.
|
|
18
|
-
- Nightly architecture scan; load roll-.dream.
|
|
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. Scan BACKLOG for Todo items.
|
|
28
|
-
2. Route US/FIX/REFACTOR to the right skill.
|
|
29
|
-
3. Run bounded cycles with fresh context.
|
|
30
|
-
4. Persist events, runs, alerts, and status.
|
|
31
|
-
5. Pause on repeated failure.
|
|
32
|
-
|
|
33
|
-
## Hard Gates
|
|
34
|
-
|
|
35
|
-
- Loop never cuts a release autonomously.
|
|
36
|
-
- Fail-loud and PAUSE beat silent fallback.
|
|
37
|
-
|
|
38
|
-
- NEVER run `git push` or `gh pr create` yourself inside a loop cycle: the RUNNER owns publish — it pushes the branch, opens the PR, and runs the attest/peer gates first. A self-published PR bypasses every gate (FIX-245: the runner adopts it and logs a discipline breach, but the gates have already been jumped). Finish your TCR commits and stop; publishing is not your step.
|
|
39
|
-
循环内严禁自己 push/开 PR——发布由 runner 负责(先过闸再出门);自开 PR = 跳闸违纪。
|
|
40
|
-
|
|
41
|
-
## Gotchas
|
|
42
|
-
|
|
43
|
-
- Loop dispatches backlog items; it must not merge releases or bypass human-on-the-loop decisions.
|
|
44
|
-
- Fail-loud pause behavior is preferable to silent fallback when repeated execution breaks.
|
|
45
|
-
|
|
46
|
-
## Maintenance
|
|
47
|
-
|
|
48
|
-
- Description changes require updates in `route-cases/skills.json`.
|
|
49
|
-
- New observed failures should add a gotcha and the matching positive or negative route case.
|
|
50
|
-
- Heavy examples, templates, recovery paths, and deterministic snippets belong in `references/`, `assets/`, or `scripts/`, not in this hub.
|
|
@@ -1,534 +0,0 @@
|
|
|
1
|
-
# Full Contract Reference
|
|
2
|
-
|
|
3
|
-
This file preserves the detailed contract extracted from SKILL.md. Read it when the hub points here for exact workflow steps, templates, rubrics, or recovery branches.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Roll Loop (Autonomous BACKLOG Executor)
|
|
8
|
-
|
|
9
|
-
> Follows the Architecture Constraints, Development Discipline, and Engineering
|
|
10
|
-
> Common Sense defined in the project AGENTS.md.
|
|
11
|
-
|
|
12
|
-
Runs on a schedule. Picks up pending BACKLOG items and executes them without
|
|
13
|
-
human intervention. The human stays informed via `roll-brief` and retains
|
|
14
|
-
sole authority over releases.
|
|
15
|
-
|
|
16
|
-
## Execution Boundary
|
|
17
|
-
|
|
18
|
-
**What roll-loop executes autonomously:**
|
|
19
|
-
- US-XXX (User Stories) → `$roll-build`
|
|
20
|
-
- FIX-XXX (Bug fixes) → `$roll-fix`
|
|
21
|
-
- REFACTOR-XXX (Refactors) → `$roll-build`
|
|
22
|
-
|
|
23
|
-
**What roll-loop never executes:**
|
|
24
|
-
- Releases — production deployment is always a human decision (requires 2FA in real terminal)
|
|
25
|
-
- Any Story marked 🚫 Hold or flagged for human review
|
|
26
|
-
- Destructive operations outside normal skill scope
|
|
27
|
-
|
|
28
|
-
**Human bypass path** — roll-loop 是默认调度器,不垄断执行权。任何时刻人可直接
|
|
29
|
-
`$roll-build US-XXX` 或 `$roll-fix FIX-XXX` 绕过 loop 立即执行(紧急 bug、中断插入、
|
|
30
|
-
故事评审等场景)。loop 通过 LOCK 和 `🔨 In Progress` 状态识别并跳过人正在做的故事,
|
|
31
|
-
人机并行不会撞车(见 Concurrency Safety)。
|
|
32
|
-
|
|
33
|
-
## Environment Constraints (autonomous loop)
|
|
34
|
-
|
|
35
|
-
You are running inside an autonomous cycle. No human is watching this turn.
|
|
36
|
-
Adapt commands to the constraints below — otherwise you will burn turns on
|
|
37
|
-
denied operations and the cycle will idle-exit.
|
|
38
|
-
|
|
39
|
-
- **No `AskUserQuestion`**: no human can answer. If you genuinely cannot
|
|
40
|
-
proceed without a decision, write an entry to `${HOME}/.shared/roll/loop/ALERT-<slug>.md`
|
|
41
|
-
describing what's needed and exit cleanly.
|
|
42
|
-
- **Avoid compound bash**: each `Bash` call must run a single command.
|
|
43
|
-
No `cmd1 && cmd2`, no `cmd1 ; cmd2`, no pipes (`|`), no `$(...)` /
|
|
44
|
-
backtick subshells, no `bash -c '...'` with nested quoting. These are
|
|
45
|
-
rejected by static analysis before they run. Chain operations as
|
|
46
|
-
separate Bash calls and read intermediate output yourself.
|
|
47
|
-
- **Prefer Read/Edit over cat/sed**: use the `Read` tool for any file
|
|
48
|
-
lookup, `Edit` for modifications. They cross sandbox boundaries that
|
|
49
|
-
`cat` / `ls` / `sed` cannot.
|
|
50
|
-
- **CWD-relative paths first**: the cycle's CWD is the per-cycle worktree.
|
|
51
|
-
Files inside it (.roll/backlog.md, bin/roll, tests/, docs/) are always
|
|
52
|
-
accessible. Files at `~/.shared/roll/...` are reachable via the `Read`
|
|
53
|
-
tool but not via shell commands.
|
|
54
|
-
- **Quote every glob**: the `Bash` tool runs commands through the user's
|
|
55
|
-
login shell, which on macOS is typically `zsh`. zsh's default `nomatch`
|
|
56
|
-
aborts unquoted globs that find no match with `(eval):1: no matches
|
|
57
|
-
found: <pattern>` and exit 1, burning a turn on a meaningless error.
|
|
58
|
-
Quote literal globs (`ls 'tests/integration/helpers.*'`) or — better —
|
|
59
|
-
use the `Glob` tool, which is shell-agnostic and never aborts on empty
|
|
60
|
-
matches.
|
|
61
|
-
- **Skill invocation is the work**: route US/REFACTOR via `$roll-build`,
|
|
62
|
-
FIX via `$roll-fix`. Do not try to re-implement those flows inline.
|
|
63
|
-
|
|
64
|
-
## Configuration
|
|
65
|
-
|
|
66
|
-
```yaml
|
|
67
|
-
# ~/.roll/config.yaml
|
|
68
|
-
loop:
|
|
69
|
-
primary_agent: claude # claude | deepseek | kimi | pi | ...
|
|
70
|
-
max_items_per_run: 1 # one story per cycle — atomic delivery, predictable cycle time
|
|
71
|
-
brief_on_feature_complete: true
|
|
72
|
-
retry_backoff: [2, 4, 8, 16] # seconds, exponential
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Workflow
|
|
76
|
-
|
|
77
|
-
> **One story per cycle (强约束)**: 每个 cycle 只 pick 一个 Todo、跑完 Step 4
|
|
78
|
-
> 立刻退出,不再回 Step 2 找下一个。理由:
|
|
79
|
-
> - cycle 时间可预测(不会因贪心一连串 PR 撞 45 分钟 hard timeout)
|
|
80
|
-
> - PR / events / dashboard 每行一个故事,归因清晰
|
|
81
|
-
> - 一个故事一个 PR 一次 review,blast radius 最小
|
|
82
|
-
>
|
|
83
|
-
> 唯一例外是依赖修复(CI self-heal 等)已经内嵌在当前故事的 Step 4 里——
|
|
84
|
-
> 那部分不算"新挑故事"。
|
|
85
|
-
>
|
|
86
|
-
> 实现层:max_items_per_run 默认 1,executor skill 跑完 Step 5 必须 exit。
|
|
87
|
-
> 不要在同一个 cycle 内多次 emit `pick_todo` 事件。
|
|
88
|
-
|
|
89
|
-
### Step 1 — Orphan 🔨 Recovery
|
|
90
|
-
|
|
91
|
-
Process-level crash recovery (LOCK, heartbeat, retry budget) is handled by
|
|
92
|
-
the v3 runner (`packages/cli/src/runner/run-cycle.ts`) — the per-project LOCK
|
|
93
|
-
guarantees only one cycle for this slug is alive when you start. So at
|
|
94
|
-
this point, any `🔨 In Progress` row in `.roll/backlog.md` belongs to a
|
|
95
|
-
previous cycle that crashed before flipping it back; reclaim it before
|
|
96
|
-
scanning.
|
|
97
|
-
|
|
98
|
-
1. Scan .roll/backlog.md for all rows whose Status column contains `🔨 In Progress`.
|
|
99
|
-
2. For each such row: revert the status back to
|
|
100
|
-
`📋 Todo`, commit `chore: revert orphan 🔨 US-XXX to 📋`, and append
|
|
101
|
-
a line to `~/.shared/roll/loop/ALERT-<slug>.md` recording the orphan
|
|
102
|
-
id and time so the next brief surfaces it.
|
|
103
|
-
3. After orphan sweep, proceed to Step 1.5 (Pre-run CI health check) before scanning.
|
|
104
|
-
|
|
105
|
-
### Step 1.5 — Pre-run CI Health Check
|
|
106
|
-
|
|
107
|
-
Call `roll loop precheck-ci` before scanning BACKLOG. This is a **defensive gate**
|
|
108
|
-
against building on a broken base. Check the **exit code** and route accordingly:
|
|
109
|
-
|
|
110
|
-
| Exit code | Meaning | Action |
|
|
111
|
-
|-----------|---------|--------|
|
|
112
|
-
| `0` | CI green / pending / unknown | Proceed to Step 1.6 (PR Inbox) and Step 2 (BACKLOG scan) |
|
|
113
|
-
| `1` | CI red AND heal exhausted or `ROLL_LOOP_NO_HEAL=1` | ALERT already written; exit cleanly this cycle |
|
|
114
|
-
| `2` | CI red AND heal attempt allowed (US-LOOP-046) | **Hot-fix path** — skip BACKLOG, fix CI instead (see below) |
|
|
115
|
-
|
|
116
|
-
`gh` missing or repo unparseable → `precheck-ci` returns `0`; graceful skip.
|
|
117
|
-
|
|
118
|
-
**Hot-fix path (exit code 2) — US-LOOP-046:**
|
|
119
|
-
|
|
120
|
-
Do NOT pick any BACKLOG stories this cycle. Instead:
|
|
121
|
-
|
|
122
|
-
1. Capture context: `roll loop hotfix-head-context` → prints path to context log
|
|
123
|
-
2. Invoke `Skill("roll-fix")` with brief:
|
|
124
|
-
`"CI red on HEAD. Failing run logs at <context-log-path>. Diagnose root cause, fix via TCR, commit, push. Do NOT change BACKLOG status."`
|
|
125
|
-
3. After `roll-fix` completes, re-run `roll ci --wait` to verify the fix
|
|
126
|
-
4. If CI is still red: run `roll loop precheck-ci` again; if it returns `1` (heal exhausted),
|
|
127
|
-
exit cleanly — ALERT was already written by the precheck
|
|
128
|
-
|
|
129
|
-
### Step 1.6 — PR Inbox (US-AUTO-034)
|
|
130
|
-
|
|
131
|
-
Before scanning BACKLOG, process open PRs first. PRs are also units of work:
|
|
132
|
-
external contributors and human teammates expect their PRs to be reviewed and
|
|
133
|
-
moved forward, not starved while loop opens new fronts.
|
|
134
|
-
|
|
135
|
-
Call `roll loop pr-inbox` after the pre-run CI check passes. It walks
|
|
136
|
-
`gh pr list --state open` and routes each PR by classification:
|
|
137
|
-
|
|
138
|
-
| Classification | Action |
|
|
139
|
-
|---|---|
|
|
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
|
-
| `blocked_human_request_changes` | Skip — last human review requested changes; wait for the author to push fixes |
|
|
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
|
-
|
|
147
|
-
**Rebase circuit breaker** — the runner records each rebase attempt under
|
|
148
|
-
`pr_state.<PR>.attempts_at` in the per-slug state file
|
|
149
|
-
(`~/.shared/roll/loop/state-<slug>.yaml`, FIX-052), pruning entries older
|
|
150
|
-
than 24 h. Once ≥3 attempts land within 24 h, further rebases are blocked and an
|
|
151
|
-
ALERT is written (typical cause: a broken workflow file makes CI never run,
|
|
152
|
-
which would otherwise drive infinite rebase loops).
|
|
153
|
-
|
|
154
|
-
**Lenient on infrastructure** — `gh` missing, repo unparseable, or any
|
|
155
|
-
`gh` API failure → `roll loop pr-inbox` returns 0 and the loop falls through to
|
|
156
|
-
Step 2 (BACKLOG scan). Same posture as the pre-run CI check.
|
|
157
|
-
|
|
158
|
-
### Step 2 — Scan BACKLOG
|
|
159
|
-
|
|
160
|
-
Read `.roll/backlog.md`. Collect all rows where Status = `📋 Todo`, in order:
|
|
161
|
-
|
|
162
|
-
Priority: FIX-XXX first (bugs block progress), then US-XXX, then REFACTOR-XXX.
|
|
163
|
-
|
|
164
|
-
**Skip rows with Status = `🔨 In Progress`**. These are currently being executed by:
|
|
165
|
-
- Another concurrent executor (human via `$roll-build`, peer agent)
|
|
166
|
-
- An earlier loop iteration that hasn't finished yet (rare; should be guarded by LOCK)
|
|
167
|
-
- A previous interrupted run (the resume logic in Step 1 will pick these up)
|
|
168
|
-
|
|
169
|
-
**In-flight PR gate** (FIX-048). Before picking, also exclude stories already
|
|
170
|
-
claimed by an **open `loop/*` PR**. Each cycle's worktree is branched from
|
|
171
|
-
`origin/main`, so a story another cycle has marked 🔨 In Progress is invisible
|
|
172
|
-
locally until that cycle's PR merges. Without this gate, two cycles started
|
|
173
|
-
back-to-back will both pick the same Todo row and produce duplicate PRs.
|
|
174
|
-
|
|
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.
|
|
178
|
-
|
|
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>"`.
|
|
185
|
-
|
|
186
|
-
Move to the next candidate when skipping. The gate is a pure function
|
|
187
|
-
over `.roll/backlog.md` text — no side effects, no LOCK interaction.
|
|
188
|
-
|
|
189
|
-
Cap at `max_items_per_run` to limit blast radius per cycle.
|
|
190
|
-
|
|
191
|
-
### Concurrency Safety
|
|
192
|
-
|
|
193
|
-
Loop has two layers of concurrency protection:
|
|
194
|
-
|
|
195
|
-
1. **Per-project LOCK** (enforced by the v3 runner, see `packages/cli/src/runner/run-cycle.ts`):
|
|
196
|
-
- LOCK file path: `~/.shared/roll/loop/.LOCK-<project-slug>`
|
|
197
|
-
- On launch: if LOCK exists and the PID inside is alive → exit 0 (previous loop still running)
|
|
198
|
-
- On launch: if LOCK exists but PID is dead → clean up stale LOCK and continue
|
|
199
|
-
- On exit (normal or via trap): LOCK is removed
|
|
200
|
-
- One LOCK per project — different projects' loops run independently
|
|
201
|
-
|
|
202
|
-
2. **🔨 In Progress story status** (enforced here):
|
|
203
|
-
- Before picking a story, check its status is `📋 Todo`
|
|
204
|
-
- Skip any `🔨 In Progress` row (someone else is on it)
|
|
205
|
-
- Mark each story `🔨 In Progress` BEFORE invoking the executor skill (see Step 3)
|
|
206
|
-
- On completion: update to `✅ Done`; on TCR failure: revert to `📋 Todo`
|
|
207
|
-
|
|
208
|
-
Together these mean: only one loop runs at a time per project (LOCK), and within a loop, stories already claimed by humans or peer agents are skipped (status check).
|
|
209
|
-
|
|
210
|
-
### Step 3 — Route and Execute
|
|
211
|
-
|
|
212
|
-
> **US-AGENT-006 — Per-story agent routing (pre-cycle)**
|
|
213
|
-
>
|
|
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.
|
|
218
|
-
>
|
|
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.
|
|
220
|
-
>
|
|
221
|
-
> Old single-agent fallback (`primary_agent` from `~/.roll/config.yaml`) still applies when:
|
|
222
|
-
> - no story is pickable (empty Todo / all blocked by depends-on)
|
|
223
|
-
> - the matching agent-routes.yaml has no agent that fits the story profile (then `cold_start_default` is used)
|
|
224
|
-
|
|
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`.
|
|
226
|
-
|
|
227
|
-
If the executor fails (TCR aborts, CI red, etc.), revert the marker so the next cycle can re-pick the story.
|
|
228
|
-
|
|
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.
|
|
230
|
-
|
|
231
|
-
选定故事后,发出 `pick_todo` 事件,让 dashboard / monitor / attach 都能把"这个 cycle 选了哪个 story"正确归类。 The v3 runner emits events natively; do not call the retired bash helper `_loop_event`.
|
|
232
|
-
|
|
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.
|
|
238
|
-
|
|
239
|
-
Then invoke the executor:
|
|
240
|
-
|
|
241
|
-
```
|
|
242
|
-
Item type → Skill invoked
|
|
243
|
-
─────────────────────────────────
|
|
244
|
-
US-XXX → Skill("roll-build", "US-XXX")
|
|
245
|
-
FIX-XXX → Skill("roll-fix", "FIX-XXX")
|
|
246
|
-
REFACTOR-XXX → Skill("roll-build", "REFACTOR-XXX")
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
The executor will update the row to `✅ Done` on success (it transitions from `🔨 In Progress` → `✅ Done`, same Edit logic as from `📋 Todo`).
|
|
250
|
-
|
|
251
|
-
Before invoking, also write current item to the per-slug state file
|
|
252
|
-
(`~/.shared/roll/loop/state-<slug>.yaml`, FIX-052):
|
|
253
|
-
|
|
254
|
-
```yaml
|
|
255
|
-
status: running
|
|
256
|
-
current_item: US-AUTO-004
|
|
257
|
-
started_at: "2026-05-10T02:00:00+08:00"
|
|
258
|
-
agent: claude
|
|
259
|
-
run_id: loop-20260510-0200
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Step 4 — Post-Item Cleanup
|
|
263
|
-
|
|
264
|
-
After each item completes:
|
|
265
|
-
|
|
266
|
-
1. **TCR 硬校验** — call `roll loop enforce-tcr <story_id> <started_at>`:
|
|
267
|
-
- Count `tcr:` prefix commits since `started_at` via `git log --oneline --since=<started_at>`
|
|
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`)
|
|
269
|
-
- Count > 0 → continue normally
|
|
270
|
-
2. **CI Gate** — **MUST** invoke `roll ci --wait`. **Do NOT call `gh` directly**
|
|
271
|
-
(no `gh run list`, no `gh run watch`,
|
|
272
|
-
no ad-hoc shell checks): `roll ci --wait` is the only sanctioned entry —
|
|
273
|
-
it derives `owner/repo` from the git remote and uses `gh -R <slug>`, which
|
|
274
|
-
is required to work through `~/.ssh/config` host rewrites that break gh's
|
|
275
|
-
auto-detection.
|
|
276
|
-
- CI passes → clear any `heal_count:` entry in `~/.shared/roll/loop/state-<slug>.yaml` (idempotent — drop the line if present, no-op otherwise) and continue normally
|
|
277
|
-
- CI fails / times out / `gh` call fails → enter **CI self-heal** (US-AUTO-041)
|
|
278
|
-
- `gh` binary not installed (`command -v gh` fails) → skip gracefully
|
|
279
|
-
(return 0). Any other `gh` error is **not** "gh unavailable" — it is a
|
|
280
|
-
hard failure and must block the gate.
|
|
281
|
-
|
|
282
|
-
**CI self-heal (US-AUTO-041)** — bounded auto-fix before ALERT.
|
|
283
|
-
|
|
284
|
-
Read `heal_count:` from `~/.shared/roll/loop/state-<slug>.yaml`; treat a missing line as `0`. If the count is below `ROLL_LOOP_HEAL_MAX` (default 2) and `ROLL_LOOP_NO_HEAL` is not set, increment it and take Path A. Otherwise take Path B.
|
|
285
|
-
|
|
286
|
-
**Path A — attempt allowed (counter incremented in `state-<slug>.yaml`):**
|
|
287
|
-
|
|
288
|
-
1. Capture failure summary:
|
|
289
|
-
```
|
|
290
|
-
gh run view --log-failed --repo <slug> \
|
|
291
|
-
$(gh run list --commit HEAD --json databaseId,conclusion -L 5 \
|
|
292
|
-
| jq -r '.[] | select(.conclusion=="failure") | .databaseId' | head -1) \
|
|
293
|
-
2>/dev/null | head -200 > /tmp/roll-heal-<story_id>.log
|
|
294
|
-
```
|
|
295
|
-
2. Invoke `Skill("roll-fix")` with brief:
|
|
296
|
-
`"CI red after <story_id>. Failing run logs at /tmp/roll-heal-<story_id>.log.
|
|
297
|
-
Diagnose root cause, fix via TCR, commit, push. Do NOT change <story_id>'s
|
|
298
|
-
BACKLOG status — it stays ✅ Done. The fix is a follow-up."`
|
|
299
|
-
3. After `roll-fix` completes, return to step 2 (CI Gate) — re-run `roll ci --wait`.
|
|
300
|
-
The counter in `state-<slug>.yaml` prevents infinite loops.
|
|
301
|
-
|
|
302
|
-
**Path B — heal exhausted (≥`ROLL_LOOP_HEAL_MAX`, default 2) or disabled (`ROLL_LOOP_NO_HEAL=1`) (exit 1):**
|
|
303
|
-
|
|
304
|
-
1. Do NOT force ✅ Done here. CI red means the PR will not merge. Under
|
|
305
|
-
**US-AUTO-044** the main loop no longer waits for merge — it publishes the
|
|
306
|
-
PR and exits; the dedicated PR Loop (`com.roll.pr.<slug>`, every 5 min)
|
|
307
|
-
merges / rebases / closes it asynchronously. There is no false-Done risk:
|
|
308
|
-
with worktree isolation the ✅ Done lives only in the unmerged PR, never on
|
|
309
|
-
the loop's main checkout, and the story is not re-picked meanwhile via the
|
|
310
|
-
open-PR eligibility gate (FIX-146). The story's
|
|
311
|
-
✅ Done lands on main only when the PR Loop actually merges the PR.
|
|
312
|
-
2. Write ALERT to `~/.shared/roll/loop/ALERT-<slug>.md` with:
|
|
313
|
-
- story ID, time, commit SHA
|
|
314
|
-
- heal attempts made (read `heal_count:` from `state-<slug>.yaml`)
|
|
315
|
-
- last failure summary (head of `/tmp/roll-heal-<story_id>.log`)
|
|
316
|
-
- suggested actions: `$roll-fix` manually / inspect CI / `roll loop reset`
|
|
317
|
-
3. Skip to next story.
|
|
318
|
-
|
|
319
|
-
**Bypass for debugging / cost control:** set `ROLL_LOOP_NO_HEAL=1` to restore
|
|
320
|
-
pre-US-AUTO-041 fail-fast behaviour.
|
|
321
|
-
3. Update state file: `status: idle`
|
|
322
|
-
4. Check if a Feature is now fully complete (all its Stories ✅)
|
|
323
|
-
5. If yes and `brief_on_feature_complete: true` → invoke `Skill("roll-brief")`
|
|
324
|
-
6. **EXIT the cycle.** 不要回 Step 2 找下一个故事,不要再 emit `pick_todo`。
|
|
325
|
-
一个 cycle 只交付一个故事;剩下的 Todo 等下一个 launchd tick 起新 cycle 处理。
|
|
326
|
-
|
|
327
|
-
### Step 5 — Write Run Summary
|
|
328
|
-
|
|
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.
|
|
332
|
-
|
|
333
|
-
After all items in this cycle:
|
|
334
|
-
|
|
335
|
-
```yaml
|
|
336
|
-
# ~/.shared/roll/loop/state-<slug>.yaml (FIX-052)
|
|
337
|
-
status: idle
|
|
338
|
-
last_run: "2026-05-10T02:15:00+08:00"
|
|
339
|
-
last_run_items: [US-AUTH-003, FIX-007]
|
|
340
|
-
last_run_outcome: success
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
Then append a JSONL record to `~/.shared/roll/loop/runs.jsonl` for per-iteration
|
|
344
|
-
visibility (one line per cycle, append-only — never delete or rewrite earlier lines).
|
|
345
|
-
|
|
346
|
-
**⚠️ Strict schema contract — do NOT deviate.** Every field has exactly one
|
|
347
|
-
canonical form. Synonyms like `"success"`, `"noop"`, `"completed"` are forbidden
|
|
348
|
-
for `status`. Numbers and arrays cannot be interchanged. UTC `Z` suffix only,
|
|
349
|
-
no timezone offsets. **No extra fields** — emit only the keys listed below (plus
|
|
350
|
-
optional `reason` when `status="failed"`); do not add `note`, `comment`,
|
|
351
|
-
`details`, `info`, etc. If you feel the urge to annotate, put it in the cycle's
|
|
352
|
-
final report in `cron.log` instead.
|
|
353
|
-
|
|
354
|
-
**Canonical record (copy this exact shape, fill in real values):**
|
|
355
|
-
|
|
356
|
-
```json
|
|
357
|
-
{"ts":"2026-05-11T11:46:43Z","project":"roll-d9dfa0","run_id":"loop-20260511-1911","status":"built","built":["US-AUTO-024","US-AUTO-025"],"skipped":[],"alerts":[],"tcr_count":5,"duration_sec":2080}
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
**Field contract — types are enforced**:
|
|
361
|
-
|
|
362
|
-
| Field | Type | Format / Enum |
|
|
363
|
-
|---|---|---|
|
|
364
|
-
| `ts` | string | ISO 8601 **UTC** with `Z` suffix. Get via `date -u +%Y-%m-%dT%H:%M:%SZ`. Never use `+08:00` or other offsets. |
|
|
365
|
-
| `project` | string | Project **slug** only (e.g. `roll-d9dfa0`), NOT the absolute path and NOT plain `basename`. Compute via: `p=$(pwd -P); base=$(basename "$p" | tr -cs '[:alnum:]' '-' | sed 's/-*$//'); hash=$(printf '%s' "$p" | md5 | cut -c1-6 2>/dev/null || printf '%s' "$p" | md5sum | cut -c1-6); echo "${base}-${hash}"` |
|
|
366
|
-
| `run_id` | string | Matches `state-<slug>.yaml` `run_id` exactly. Format: `loop-YYYYMMDD-HHMM`. |
|
|
367
|
-
| `status` | enum | Exactly one of: `built` (≥1 story shipped), `idle` (no Todo items found), `failed` (paused/error). **No synonyms.** |
|
|
368
|
-
| `built` | array<string> | Story ids completed this cycle. `[]` when none. **Always array, never null/number.** |
|
|
369
|
-
| `skipped` | array<string> | Story ids skipped because they were `🔨 In Progress`. `[]` when none. **Always array.** |
|
|
370
|
-
| `alerts` | array<string> | Newly raised ALERT identifiers/tags this cycle. `[]` when none. **Always array, never number.** |
|
|
371
|
-
| `tcr_count` | integer | Total `tcr:` prefix commits made this cycle. `0` when none. |
|
|
372
|
-
| `duration_sec` | integer | Seconds from cycle start to completion. Integer only, no decimals. |
|
|
373
|
-
|
|
374
|
-
Optional field, only when `status == "failed"`:
|
|
375
|
-
- `reason` (string): short human-readable explanation.
|
|
376
|
-
|
|
377
|
-
**Write recipe:**
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
381
|
-
# Compute project slug — inlined equivalent of bin/roll's _project_slug
|
|
382
|
-
# (Claude sessions can't call roll's internal functions, so we inline).
|
|
383
|
-
# Must produce identical output to _project_slug to match `roll loop runs` filter.
|
|
384
|
-
_p=$(pwd -P)
|
|
385
|
-
_base=$(basename "$_p" | tr -cs '[:alnum:]' '-' | sed 's/-*$//')
|
|
386
|
-
_hash=$(printf '%s' "$_p" | md5 | cut -c1-6 2>/dev/null || printf '%s' "$_p" | md5sum | cut -c1-6)
|
|
387
|
-
project="${_base}-${_hash}" # e.g. roll-d9dfa0 — must match roll loop runs filter
|
|
388
|
-
# duration_sec = cycle_end_epoch - cycle_start_epoch (track at Step 1)
|
|
389
|
-
# tcr_count = git log --oneline --since="<cycle_start>" | grep -c '^[a-f0-9]* tcr:'
|
|
390
|
-
|
|
391
|
-
jq -nc \
|
|
392
|
-
--arg ts "$ts" \
|
|
393
|
-
--arg project "$project" \
|
|
394
|
-
--arg run_id "$run_id" \
|
|
395
|
-
--arg status "built" \
|
|
396
|
-
--argjson built '["US-AUTO-024"]' \
|
|
397
|
-
--argjson skipped '[]' \
|
|
398
|
-
--argjson alerts '[]' \
|
|
399
|
-
--argjson tcr_count 14 \
|
|
400
|
-
--argjson duration_sec 1680 \
|
|
401
|
-
'{ts:$ts, project:$project, run_id:$run_id, status:$status,
|
|
402
|
-
built:$built, skipped:$skipped, alerts:$alerts,
|
|
403
|
-
tcr_count:$tcr_count, duration_sec:$duration_sec}' \
|
|
404
|
-
>> ~/.shared/roll/loop/runs.jsonl
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
The companion read-side is `roll loop runs [N] [--all]` — shows the most recent
|
|
408
|
-
N records (default 10) for the current project, or across all projects with `--all`.
|
|
409
|
-
|
|
410
|
-
## Failure Handling
|
|
411
|
-
|
|
412
|
-
### Network Error (transient)
|
|
413
|
-
|
|
414
|
-
```
|
|
415
|
-
Attempt 1 fails
|
|
416
|
-
→ wait 2s → Attempt 2
|
|
417
|
-
→ wait 4s → Attempt 3
|
|
418
|
-
→ wait 8s → Attempt 4
|
|
419
|
-
→ wait 16s → Attempt 5
|
|
420
|
-
→ still failing → escalate to token/agent failure path
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
### Token Exhausted / Agent Unavailable
|
|
424
|
-
|
|
425
|
-
```
|
|
426
|
-
Primary agent fails (non-network error)
|
|
427
|
-
→ 3 attempts at the agent_invoke phase (with 30s back-off between)
|
|
428
|
-
→ still failing → PAUSE
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
### Pause + Alert
|
|
432
|
-
|
|
433
|
-
When the primary agent exhausts its retry budget:
|
|
434
|
-
|
|
435
|
-
1. Write state:
|
|
436
|
-
```yaml
|
|
437
|
-
status: paused
|
|
438
|
-
paused_at: "2026-05-10T02:07:00+08:00"
|
|
439
|
-
paused_on: US-AUTH-003
|
|
440
|
-
reason: "primary agent (claude) unavailable after 3 attempts"
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
2. Write alert:
|
|
444
|
-
```markdown
|
|
445
|
-
# ALERT — roll-loop paused
|
|
446
|
-
|
|
447
|
-
**Time**: 2026-05-10 02:07
|
|
448
|
-
**Paused on**: US-AUTH-003
|
|
449
|
-
**Reason**: claude exited non-zero on 3 consecutive attempts
|
|
450
|
-
|
|
451
|
-
**Action required** (choose one):
|
|
452
|
-
- Top up credits and run: `roll loop resume`
|
|
453
|
-
- Switch agent: edit `~/.roll/config.yaml` → `primary_agent`
|
|
454
|
-
- Take over manually: `$roll-build US-AUTH-003`
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
3. Write alert file to `~/.shared/roll/loop/ALERT-<slug>.md`
|
|
458
|
-
|
|
459
|
-
## Resuming After Pause
|
|
460
|
-
|
|
461
|
-
```bash
|
|
462
|
-
roll loop resume # picks up from state-<slug>.yaml current_item
|
|
463
|
-
roll loop status # show current state without running
|
|
464
|
-
roll loop reset # clear state and start fresh next scheduled run
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
## Scheduler Configuration
|
|
468
|
-
|
|
469
|
-
roll-loop runs **locally** — it needs access to the local codebase, local
|
|
470
|
-
test runner, and local agent CLI. GitHub Actions runs on remote servers and
|
|
471
|
-
cannot fulfill these requirements.
|
|
472
|
-
|
|
473
|
-
### Local cron (default)
|
|
474
|
-
|
|
475
|
-
Install once with `roll loop on` — agent selection happens per cycle from the
|
|
476
|
-
`.roll/agents.yaml` complexity slots (easy/default/hard/fallback), so the cron
|
|
477
|
-
entry is agent-agnostic. No agent-specific command needed.
|
|
478
|
-
|
|
479
|
-
```bash
|
|
480
|
-
roll loop on # install cron for loop + dream + brief
|
|
481
|
-
roll loop off # remove cron entries
|
|
482
|
-
roll loop status # show current state
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
### Manual run (for testing)
|
|
486
|
-
|
|
487
|
-
```bash
|
|
488
|
-
roll loop now # execute one cycle immediately
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### Live attach (transparency)
|
|
492
|
-
|
|
493
|
-
Each loop iteration runs inside a detached tmux session named
|
|
494
|
-
`roll-loop-<slug>` (tmux is a required dependency — `roll setup` auto-installs
|
|
495
|
-
it via Homebrew on macOS, or prints the install command elsewhere).
|
|
496
|
-
|
|
497
|
-
**Default — auto-attach popup**: when the loop fires, a background Terminal
|
|
498
|
-
window pops up running `tmux attach -t roll-loop-<slug>`. You can watch the
|
|
499
|
-
agent work in real time without typing anything. The popup is best-effort
|
|
500
|
-
focus-retaining (it captures the previously-active app and restores focus
|
|
501
|
-
after the window appears) and the tmux session keeps running even if you
|
|
502
|
-
close the window.
|
|
503
|
-
|
|
504
|
-
**Manual attach** (any time):
|
|
505
|
-
|
|
506
|
-
```bash
|
|
507
|
-
roll loop attach # exec tmux attach -t roll-loop-<slug>
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
Press `Ctrl-B D` to detach — the loop continues running uninterrupted.
|
|
511
|
-
|
|
512
|
-
**Mute / unmute the popup**:
|
|
513
|
-
|
|
514
|
-
```bash
|
|
515
|
-
roll loop mute # 🔇 — suppress auto-attach popup (loop still runs in tmux)
|
|
516
|
-
roll loop unmute # 🔔 — re-enable the popup
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
Mute state is a single marker file at `~/.shared/roll/mute` and is shared
|
|
520
|
-
across all projects on this machine. Check the current state with
|
|
521
|
-
`roll loop status` — it shows an `Auto-attach: live | muted` line.
|
|
522
|
-
|
|
523
|
-
## Integration Map
|
|
524
|
-
|
|
525
|
-
```
|
|
526
|
-
roll-loop
|
|
527
|
-
├── reads .roll/backlog.md
|
|
528
|
-
├── invokes $roll-build (US-XXX, REFACTOR-XXX)
|
|
529
|
-
├── invokes $roll-fix (FIX-XXX)
|
|
530
|
-
├── invokes $roll-brief (on Feature completion)
|
|
531
|
-
├── reads ~/.roll/config.yaml (agent routing)
|
|
532
|
-
├── writes ~/.shared/roll/loop/state-<slug>.yaml
|
|
533
|
-
└── writes ~/.shared/roll/loop/ALERT-<slug>.md (on failure)
|
|
534
|
-
```
|