@seanyao/roll 2026.512.6 → 2026.512.7
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 +12 -0
- package/README.md +39 -226
- package/bin/roll +205 -29
- package/package.json +2 -2
- package/skills/roll-.changelog/SKILL.md +24 -2
- package/skills/roll-.dream/SKILL.md +41 -1
- package/skills/roll-brief/SKILL.md +9 -0
- package/skills/roll-build/SKILL.md +10 -6
- package/skills/roll-loop/SKILL.md +16 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v2026.512.7
|
|
4
|
+
- **Added**: `roll alert` — 查看、确认、清除 loop 告警,不用再去翻 loop status
|
|
5
|
+
- **Added**: macOS 系统通知 — story 完成或告警写入时自动弹通知,静音模式下不打扰
|
|
6
|
+
- **Added**: `roll ci [--wait]` — 查看当前提交的 CI 状态,或等待 CI 跑完再继续
|
|
7
|
+
- **Fixed**: loop 现在会等 CI 通过后才标记故事完成,CI 失败则保持进行中并发出提醒
|
|
8
|
+
- **Fixed**: changelog 更新不再产生独立 commit,并入故事完成提交,git log 更干净
|
|
9
|
+
- **Added**: `docs/domain/` — Roll 架构的 DDD 领域模型文档(5 个 Bounded Context + 自治操作 Aggregate 设计)
|
|
10
|
+
- **Fixed**: `roll loop runs` 不再报"当前项目尚无运行记录",历史记录正常显示
|
|
11
|
+
- **Added**: 文档目录重组 — methodology、skill 选择指南、loop 验证记录迁移至 `docs/guide/` 和 `docs/practices/`,根目录不再有散落文件
|
|
12
|
+
- **Added**: README 大幅精简并新增文档导航索引 — 首页更清晰,所有指南一表可查
|
|
13
|
+
- **Added**: dream 每晚自动检测文档缺口,brief 新增文档覆盖率数字
|
|
14
|
+
|
|
3
15
|
## v2026.512.6
|
|
4
16
|
- **Added**: peer review 现在也会自动弹出终端窗口,实时观察跨 AI 协商过程(mute 关闭同一开关)
|
|
5
17
|
- **Added**: `docs/guide/en/` — loop/dream/peer 英文用户指南上线,覆盖所有子命令和使用场景
|
package/README.md
CHANGED
|
@@ -19,262 +19,75 @@
|
|
|
19
19
|
|
|
20
20
|
## What is Roll?
|
|
21
21
|
|
|
22
|
-
Roll
|
|
22
|
+
Roll is an instruction and workflow framework for AI agents — it encodes proven engineering practices (TDD, TCR, SRE, INVEST) as skills any agent can follow, distributes unified conventions to every AI client on your machine, and optionally lets the agent work unattended via an autonomous evolution layer.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
3. **Autonomous Evolution** — an optional layer that lets the agent work unattended: `roll-loop` executes BACKLOG items hourly, `roll-.dream` scans code health nightly, and `roll-brief` briefs the human each morning. The human retains sole authority over releases.
|
|
29
|
-
|
|
30
|
-
The result: any agent, any client, same constraints — and optionally, continuous autonomous delivery.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Start Here
|
|
35
|
-
|
|
36
|
-
Before commands and skills, read the Engineering Methodology — it explains the three-loop architecture (Research → Build → Observe), the autonomous evolution layer, why each skill exists, and how they connect into a complete delivery system.
|
|
37
|
-
|
|
38
|
-
**[English](docs/methodology-en.md)** · **[中文](docs/methodology.md)**
|
|
24
|
+
**Three core values:**
|
|
25
|
+
1. **Any agent, same constraints** — Claude, Cursor, Kimi, DeepSeek, Codex all receive identical engineering guardrails
|
|
26
|
+
2. **Skill system** — 20 skills encode research → design → build → check → fix as reliable, repeatable workflows
|
|
27
|
+
3. **Autonomous evolution** — `roll loop on` runs BACKLOG items hourly; humans retain sole release authority
|
|
39
28
|
|
|
40
29
|
---
|
|
41
30
|
|
|
42
|
-
##
|
|
31
|
+
## Quick Start (30 seconds)
|
|
43
32
|
|
|
44
33
|
```bash
|
|
45
34
|
npm install -g @seanyao/roll
|
|
46
|
-
roll setup
|
|
35
|
+
roll setup # distribute conventions to all AI clients
|
|
36
|
+
cd my-project
|
|
37
|
+
roll init # create AGENTS.md + BACKLOG.md + docs/features/
|
|
38
|
+
roll loop on # optional: let the agent work unattended
|
|
47
39
|
```
|
|
48
40
|
|
|
49
41
|
**Requirements:** bash 4+, Node.js 16+
|
|
50
42
|
|
|
51
|
-
To update:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
roll update
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
> **For contributors** (working on roll itself): `git clone https://github.com/seanyao/roll.git && cd roll && ./install.sh`
|
|
58
|
-
|
|
59
43
|
---
|
|
60
44
|
|
|
61
|
-
##
|
|
45
|
+
## Documentation Index
|
|
62
46
|
|
|
63
|
-
|
|
47
|
+
| Topic | English | 中文 |
|
|
48
|
+
|-------|---------|------|
|
|
49
|
+
| Overview & architecture | [guide/en/overview.md](docs/guide/en/overview.md) | [guide/zh/overview.md](docs/guide/zh/overview.md) |
|
|
50
|
+
| Engineering methodology | [guide/en/methodology.md](docs/guide/en/methodology.md) | [guide/zh/methodology.md](docs/guide/zh/methodology.md) |
|
|
51
|
+
| Loop (autonomous executor) | [guide/en/loop.md](docs/guide/en/loop.md) | [guide/zh/loop.md](docs/guide/zh/loop.md) |
|
|
52
|
+
| Dream (nightly health scan) | [guide/en/dream.md](docs/guide/en/dream.md) | [guide/zh/dream.md](docs/guide/zh/dream.md) |
|
|
53
|
+
| Peer (cross-agent review) | [guide/en/peer.md](docs/guide/en/peer.md) | [guide/zh/peer.md](docs/guide/zh/peer.md) |
|
|
54
|
+
| Skill selection guide | [guide/en/skills.md](docs/guide/en/skills.md) | [guide/zh/skills.md](docs/guide/zh/skills.md) |
|
|
55
|
+
| Domain model (DDD) | [domain/context-map.md](docs/domain/context-map.md) | — |
|
|
56
|
+
| Engineering common sense | [practices/engineering-common-sense.md](docs/practices/engineering-common-sense.md) | — |
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
---
|
|
66
59
|
|
|
67
|
-
Commands
|
|
60
|
+
## Commands
|
|
68
61
|
|
|
69
62
|
| Command | Description |
|
|
70
63
|
|---------|-------------|
|
|
71
|
-
| `roll setup [-f]` | First-time install
|
|
72
|
-
| `roll update` |
|
|
73
|
-
| `roll init` |
|
|
74
|
-
| `roll status` | Show sync state, skill links,
|
|
75
|
-
| `roll backlog` | Show
|
|
76
|
-
| `roll
|
|
77
|
-
| `roll
|
|
78
|
-
| `roll
|
|
79
|
-
| `roll
|
|
80
|
-
| `roll release` | 🤖 Sync changelog + version bump + tag + npm publish + GitHub Release |
|
|
81
|
-
| `roll` _(no args, in project dir)_ | Dashboard: loop status, pending count, latest brief summary |
|
|
82
|
-
|
|
83
|
-
### Typical Flow
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
# 1. Install on this machine
|
|
87
|
-
npm install -g @seanyao/roll
|
|
88
|
-
roll setup
|
|
89
|
-
|
|
90
|
-
# 2. Initialize a project (run from project root)
|
|
91
|
-
cd my-app
|
|
92
|
-
roll init
|
|
93
|
-
|
|
94
|
-
# 3. Upgrade to a new release
|
|
95
|
-
roll update
|
|
96
|
-
|
|
97
|
-
# 4. Enable autonomous evolution (optional)
|
|
98
|
-
roll loop on # three services: loop (hourly) + dream (nightly) + brief (daily)
|
|
99
|
-
roll loop monitor # real-time top-like dashboard
|
|
100
|
-
roll brief # read the latest digest
|
|
101
|
-
|
|
102
|
-
# 5. Switch agent per project
|
|
103
|
-
roll agent use kimi # all 🤖 commands now use kimi for this project
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### How Convention Layering Works
|
|
107
|
-
|
|
108
|
-
```
|
|
109
|
-
Global ~/.claude/CLAUDE.md ← user-owned; roll setup appends @roll.md
|
|
110
|
-
~/.claude/roll.md ← Roll conventions (written by roll setup/sync)
|
|
111
|
-
↓ auto-stacked
|
|
112
|
-
Project <project>/AGENTS.md ← generated by roll init
|
|
113
|
-
<project>/.claude/CLAUDE.md
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Global conventions are additive and never overwrite existing files. Project conventions are injected per project via `roll init`.
|
|
117
|
-
|
|
118
|
-
### Directory Layout
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
~/.roll/
|
|
122
|
-
├── config.yaml # sync path configuration
|
|
123
|
-
└── conventions/
|
|
124
|
-
├── global/ # single source of truth
|
|
125
|
-
│ ├── AGENTS.md
|
|
126
|
-
│ ├── CLAUDE.md / GEMINI.md / .cursor-rules
|
|
127
|
-
└── templates/ # project type templates
|
|
128
|
-
├── fullstack/
|
|
129
|
-
├── frontend-only/
|
|
130
|
-
├── backend-service/
|
|
131
|
-
└── cli/
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## Skill System
|
|
137
|
-
|
|
138
|
-
Skills are instructions that encode proven engineering practices into a form AI agents can reliably follow. They live in `~/.roll/skills/` and are symlinked into each AI client's skill directory on `roll setup`.
|
|
139
|
-
|
|
140
|
-
### Workflow
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
Research → Design → Build → Check → Fix → (loop)
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Quick Reference
|
|
147
|
-
|
|
148
|
-
| Scenario | Skill |
|
|
149
|
-
|----------|-------|
|
|
150
|
-
| Uncertain approach, need to think it through | `$roll-design "topic"` |
|
|
151
|
-
| Execute a planned Story | `$roll-build US-001` |
|
|
152
|
-
| Free-form feature request | `$roll-build "add search to admin"` |
|
|
153
|
-
| Bug fix | `$roll-fix FIX-001` |
|
|
154
|
-
| Fast backlog capture (bug / idea) | `$roll-idea "description"` |
|
|
155
|
-
| High-risk logic (payments, auth, state machines) | `$roll-spar "feature"` |
|
|
156
|
-
| Deep research (product / company / tech) | `$roll-research "subject"` |
|
|
157
|
-
| Cross-agent code review | `$roll-peer` |
|
|
158
|
-
| Patrol production for regressions | `$roll-sentinel patrol` |
|
|
159
|
-
| Debug a broken page | `$roll-debug <URL>` |
|
|
160
|
-
| Record a dev moment / diary entry | `$roll-notes "just fixed that nasty bug"` |
|
|
161
|
-
| Let the agent work overnight | `roll loop on` |
|
|
162
|
-
|
|
163
|
-
### Full Skill List
|
|
164
|
-
|
|
165
|
-
**Loop A — Research & Design**
|
|
166
|
-
|
|
167
|
-
| Skill | Description |
|
|
168
|
-
|-------|-------------|
|
|
169
|
-
| `$roll-research` | HV Analysis (Horizontal-Vertical) deep research framework, outputs PDF report |
|
|
170
|
-
| `$roll-design` | Multi-turn discuss → [peer review] → DDD model → solution design → [peer review] → write Stories to BACKLOG |
|
|
171
|
-
|
|
172
|
-
**Loop B — Implementation & Iteration**
|
|
173
|
-
|
|
174
|
-
| Skill | Description |
|
|
175
|
-
|-------|-------------|
|
|
176
|
-
| `$roll-build` | Universal entry: Story ID, fix ID, or free-text fly mode. TCR-driven micro-commits |
|
|
177
|
-
| `$roll-spar` | Adversarial TDD — Attacker writes tests, Defender writes code |
|
|
178
|
-
| `$roll-fix` | Bug fix / hotfix from BACKLOG |
|
|
179
|
-
| `$roll-release` | One-command publish: auto version (YYYY.MMDD.N) → tag → npm publish → GitHub Release |
|
|
180
|
-
| `$roll-peer` | Cross-agent code review — Claude / Kimi / DeepSeek / Codex bilateral negotiation |
|
|
181
|
-
|
|
182
|
-
**Loop C — Observability & Maintenance**
|
|
183
|
-
|
|
184
|
-
| Skill | Description |
|
|
185
|
-
|-------|-------------|
|
|
186
|
-
| `$roll-sentinel` | Randomized production patrol with adaptive hot-spot weighting |
|
|
187
|
-
| `$roll-debug` | Deep page diagnostics + root cause analysis (Black Box probe) |
|
|
188
|
-
|
|
189
|
-
**Autonomous Evolution (optional, via `roll loop on`)**
|
|
190
|
-
|
|
191
|
-
| Skill | Description |
|
|
192
|
-
|-------|-------------|
|
|
193
|
-
| `$roll-loop` | Hourly BACKLOG executor — routes US/FIX/REFACTOR to the right skill, enforces TCR |
|
|
194
|
-
| `$roll-.dream` | Nightly code health scan — dead code, architectural drift → REFACTOR entries |
|
|
195
|
-
| `$roll-brief` | Owner-facing digest — what's done, what's pending, release readiness verdict |
|
|
196
|
-
|
|
197
|
-
**Passive Support**
|
|
198
|
-
|
|
199
|
-
| Skill | Description |
|
|
200
|
-
|-------|-------------|
|
|
201
|
-
| `$roll-.review` | Pre-commit multi-dimensional self code review |
|
|
202
|
-
| `$roll-.qa` | Test pyramid and coverage standards reference |
|
|
203
|
-
| `$roll-.changelog` | Auto-generate CHANGELOG from BACKLOG |
|
|
204
|
-
| `$roll-.echo` | Passive intent clarification |
|
|
205
|
-
| `$roll-.clarify` | Passive scope clarification for vague build requests |
|
|
206
|
-
| `$roll-idea` | Fast capture a bug or idea into BACKLOG.md |
|
|
207
|
-
| `$roll-notes` | Project diary — append dev moments to `notes/YYYY-MM-DD.md` |
|
|
208
|
-
| `$roll-doctor` | One-command dev toolchain health check |
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## Autonomous Evolution
|
|
213
|
-
|
|
214
|
-
Off by default. Enable with `roll loop on` to let the agent work unattended on your project.
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
┌─────────────────────────────────────────────────────────┐
|
|
218
|
-
│ Base layer (always active) │
|
|
219
|
-
│ $roll-design → $roll-build → $roll-fix → $roll-spar │
|
|
220
|
-
│ Human drives every action │
|
|
221
|
-
├─────────────────────────────────────────────────────────┤
|
|
222
|
-
│ Autonomous layer (opt-in: roll loop on) │
|
|
223
|
-
│ roll-loop — hourly BACKLOG executor │
|
|
224
|
-
│ roll-.dream — nightly code health scan │
|
|
225
|
-
│ roll-brief — daily morning digest + release readiness │
|
|
226
|
-
│ Human reviews briefs; retains sole release authority │
|
|
227
|
-
└─────────────────────────────────────────────────────────┘
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
Three services are scheduled via macOS launchd (Linux: crontab) and managed as a unit:
|
|
231
|
-
|
|
232
|
-
- **roll-loop** runs hourly, picks up `📋 Todo` items from BACKLOG, routes them (`US-XXX → $roll-build`, `FIX-XXX → $roll-fix`, `REFACTOR-XXX → $roll-build`), and enforces TCR discipline — if a story completes with zero `tcr:` micro-commits, it reverts to Todo with an ALERT.
|
|
233
|
-
- **roll-.dream** runs nightly, scanning for dead code, architectural drift, and refactoring opportunities. Outputs `REFACTOR-XXX` entries to BACKLOG.
|
|
234
|
-
- **roll-brief** runs each morning (or on-demand via `roll brief`), producing an owner-facing digest with a release-readiness verdict.
|
|
235
|
-
|
|
236
|
-
The autonomous layer **never** invokes `roll-release`. Production deployment is always a human decision.
|
|
237
|
-
|
|
238
|
-
Use `roll loop monitor` for a real-time `top`-like view of all three services: launchd status, current execution state, pending queue, alerts, and live log tail.
|
|
239
|
-
|
|
240
|
-
Per-project agent configuration: `roll agent use <name>` writes `.roll.yaml` so each project can use a different AI client (claude / kimi / deepseek / pi / codex / opencode). Lookup order: `.roll.yaml` → `~/.roll/config.yaml` → `claude` (default).
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## Project Structure (`roll init`)
|
|
245
|
-
|
|
246
|
-
```
|
|
247
|
-
my-project/
|
|
248
|
-
├── AGENTS.md # Project constraints & skill routing
|
|
249
|
-
├── BACKLOG.md # Story and bug index
|
|
250
|
-
├── docs/features/ # Story details and specs
|
|
251
|
-
└── ... your project files
|
|
252
|
-
```
|
|
64
|
+
| `roll setup [-f]` | First-time install or re-sync conventions to all AI clients |
|
|
65
|
+
| `roll update` | Upgrade to latest version |
|
|
66
|
+
| `roll init` | Initialize project: AGENTS.md + BACKLOG.md + docs/features/ |
|
|
67
|
+
| `roll status` | Show sync state, skill links, detected AI tools |
|
|
68
|
+
| `roll backlog` | Show pending tasks from BACKLOG.md |
|
|
69
|
+
| `roll loop <on\|off\|now\|status\|monitor>` | 🤖 Manage autonomous executor |
|
|
70
|
+
| `roll brief` | 🤖 Show latest owner digest |
|
|
71
|
+
| `roll peer` | 🤖 Cross-agent code review |
|
|
72
|
+
| `roll release` | 🤖 Version + tag + npm publish + GitHub Release |
|
|
253
73
|
|
|
254
74
|
---
|
|
255
75
|
|
|
256
76
|
## Contributing
|
|
257
77
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
1. Fork the repo and create a branch from `main`
|
|
261
|
-
2. Make your changes with tests where applicable (`tests/`)
|
|
262
|
-
3. Ensure `./bin/roll --help` output is correct
|
|
263
|
-
4. Open a pull request with a clear description
|
|
78
|
+
PRs welcome. Keep them focused on one thing. For larger changes, open an issue first.
|
|
264
79
|
|
|
265
|
-
|
|
80
|
+
1. `git clone https://github.com/seanyao/roll.git && cd roll && ./install.sh`
|
|
81
|
+
2. Make changes with bats tests (`tests/`)
|
|
82
|
+
3. Run `npm test` before pushing
|
|
266
83
|
|
|
267
84
|
---
|
|
268
85
|
|
|
269
86
|
## Acknowledgments
|
|
270
87
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
- **[khazix-skills](https://github.com/KKKKhazix/khazix-skills)** by Digital Life Khazix — The HV Analysis (Horizontal-Vertical Analysis) deep research framework and schema used by `$roll-research` are derived from this project, used under the MIT License. Copyright (c) 2026 数字生命卡兹克.
|
|
274
|
-
- **[superpowers](https://github.com/obra/superpowers)** by Jesse Vincent — A composable skills library for AI coding agents that informed several workflow patterns in Roll.
|
|
88
|
+
- **[khazix-skills](https://github.com/KKKKhazix/khazix-skills)** by Digital Life Khazix — HV Analysis framework used by `$roll-research`, MIT License.
|
|
89
|
+
- **[superpowers](https://github.com/obra/superpowers)** by Jesse Vincent — composable skills library that inspired several Roll workflow patterns.
|
|
275
90
|
|
|
276
91
|
---
|
|
277
92
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
MIT
|
|
93
|
+
MIT License
|
package/bin/roll
CHANGED
|
@@ -4,7 +4,7 @@ set -euo pipefail
|
|
|
4
4
|
# Roll — AI Agent Convention Manager
|
|
5
5
|
# Single source of truth for how all AI coding agents behave.
|
|
6
6
|
|
|
7
|
-
VERSION="2026.512.
|
|
7
|
+
VERSION="2026.512.7"
|
|
8
8
|
ROLL_HOME="${ROLL_HOME:-${HOME}/.roll}"
|
|
9
9
|
ROLL_CONFIG="${ROLL_HOME}/config.yaml"
|
|
10
10
|
ROLL_GLOBAL="${ROLL_HOME}/conventions/global"
|
|
@@ -117,6 +117,18 @@ _get_ai_tools() {
|
|
|
117
117
|
done
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
# Iterate all configured AI tools, calling: callback entry ai_dir ai_config ai_src [extra_args...]
|
|
121
|
+
_for_each_ai_tool() {
|
|
122
|
+
local _feach_cb="$1"; shift
|
|
123
|
+
while IFS= read -r _feach_entry; do
|
|
124
|
+
"$_feach_cb" "$_feach_entry" \
|
|
125
|
+
"$(_ai_dir "$_feach_entry")" \
|
|
126
|
+
"$(_ai_config "$_feach_entry")" \
|
|
127
|
+
"$(_ai_src "$_feach_entry")" \
|
|
128
|
+
"$@"
|
|
129
|
+
done < <(_get_ai_tools)
|
|
130
|
+
}
|
|
131
|
+
|
|
120
132
|
# Add any ai_* keys from the default set that are missing from the user's config.
|
|
121
133
|
# Non-destructive: never removes or modifies existing entries.
|
|
122
134
|
_ensure_config_entries() {
|
|
@@ -505,16 +517,14 @@ _sync_convention_for_tool() {
|
|
|
505
517
|
fi
|
|
506
518
|
}
|
|
507
519
|
|
|
520
|
+
_sync_one_tool() {
|
|
521
|
+
local _entry="$1" _ai_dir="$2" _cfg="$3" _src="$4" force="$5"
|
|
522
|
+
_sync_convention_for_tool "$ROLL_GLOBAL/$_src" "$_ai_dir/$_cfg" "$force"
|
|
523
|
+
}
|
|
524
|
+
|
|
508
525
|
_sync_conventions() {
|
|
509
526
|
local force="${1:-false}"
|
|
510
|
-
|
|
511
|
-
while IFS= read -r entry; do
|
|
512
|
-
local ai_dir config_file src_file
|
|
513
|
-
ai_dir="$(_ai_dir "$entry")"
|
|
514
|
-
config_file="$(_ai_config "$entry")"
|
|
515
|
-
src_file="$(_ai_src "$entry")"
|
|
516
|
-
_sync_convention_for_tool "$ROLL_GLOBAL/$src_file" "$ai_dir/$config_file" "$force"
|
|
517
|
-
done < <(_get_ai_tools)
|
|
527
|
+
_for_each_ai_tool _sync_one_tool "$force"
|
|
518
528
|
}
|
|
519
529
|
|
|
520
530
|
# ─── Internal: sync skills (pull + link) ──────────────────────────────────────
|
|
@@ -1038,22 +1048,10 @@ scan_project_type_from_files() {
|
|
|
1038
1048
|
fi
|
|
1039
1049
|
}
|
|
1040
1050
|
|
|
1041
|
-
# ─── Helper: true when cwd has no existing source code ───────────────────────
|
|
1042
|
-
is_fresh_project() {
|
|
1043
|
-
local dir="${1:-.}"
|
|
1044
|
-
! ( [[ -f "$dir/package.json" ]] || [[ -f "$dir/go.mod" ]] || \
|
|
1045
|
-
[[ -f "$dir/Cargo.toml" ]] || [[ -f "$dir/requirements.txt" ]] || \
|
|
1046
|
-
[[ -f "$dir/pyproject.toml" ]] || \
|
|
1047
|
-
[[ -d "$dir/src" ]] || [[ -d "$dir/api" ]] || [[ -d "$dir/app" ]] )
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
# ─── Helper: make a scaffold dir + .gitkeep ───────────────────────────────────
|
|
1051
|
-
_mkscaffold() { mkdir -p "$1"; touch "$1/.gitkeep"; }
|
|
1052
|
-
|
|
1053
1051
|
# ─── Helper: write starter BACKLOG.md (no-op if exists) ──────────────────────
|
|
1054
1052
|
_write_backlog() {
|
|
1055
1053
|
if [[ -f "$1" ]]; then
|
|
1056
|
-
|
|
1054
|
+
_ROLL_MERGE_SUMMARY+=("unchanged|BACKLOG.md")
|
|
1057
1055
|
return
|
|
1058
1056
|
fi
|
|
1059
1057
|
cat > "$1" << 'EOF'
|
|
@@ -1068,18 +1066,18 @@ _write_backlog() {
|
|
|
1068
1066
|
|----|---------|--------|
|
|
1069
1067
|
EOF
|
|
1070
1068
|
ok "Created: BACKLOG.md"
|
|
1071
|
-
|
|
1069
|
+
_ROLL_MERGE_SUMMARY+=("created|BACKLOG.md")
|
|
1072
1070
|
}
|
|
1073
1071
|
|
|
1074
1072
|
_ensure_features_dir() {
|
|
1075
1073
|
if [[ -d "$1" ]]; then
|
|
1076
|
-
|
|
1074
|
+
_ROLL_MERGE_SUMMARY+=("unchanged|docs/features/")
|
|
1077
1075
|
return
|
|
1078
1076
|
fi
|
|
1079
1077
|
|
|
1080
1078
|
mkdir -p "$1"
|
|
1081
1079
|
ok "Created: docs/features/"
|
|
1082
|
-
|
|
1080
|
+
_ROLL_MERGE_SUMMARY+=("created|docs/features/")
|
|
1083
1081
|
}
|
|
1084
1082
|
|
|
1085
1083
|
# ─── Helper: write starter .gitignore (no-op if exists) ──────────────────────
|
|
@@ -2266,7 +2264,8 @@ cmd_loop() {
|
|
|
2266
2264
|
pause) _loop_pause ;;
|
|
2267
2265
|
resume) _loop_resume ;;
|
|
2268
2266
|
reset) _loop_reset ;;
|
|
2269
|
-
|
|
2267
|
+
notify) _notify "${1:-roll}" "${2:-}" ;;
|
|
2268
|
+
*) err "Usage: roll loop <on|off|now|test|status|monitor|runs|attach|mute|unmute|pause|resume|reset|notify>"; exit 1 ;;
|
|
2270
2269
|
esac
|
|
2271
2270
|
}
|
|
2272
2271
|
|
|
@@ -2484,7 +2483,7 @@ _loop_status() {
|
|
|
2484
2483
|
else
|
|
2485
2484
|
echo -e " Auto-attach ${GREEN}live${NC} run: roll loop mute"
|
|
2486
2485
|
fi
|
|
2487
|
-
[[ -f "$_LOOP_ALERT" ]] && { echo ""; echo -e " ${RED}⚠ ALERT
|
|
2486
|
+
[[ -f "$_LOOP_ALERT" ]] && { echo ""; echo -e " ${RED}⚠ ALERT${NC} (${CYAN}roll alert${NC} to manage)"; sed 's/^/ /' "$_LOOP_ALERT"; }
|
|
2488
2487
|
[[ -f "$_LOOP_STATE" ]] && { echo ""; echo " State:"; sed 's/^/ /' "$_LOOP_STATE"; }
|
|
2489
2488
|
echo ""
|
|
2490
2489
|
}
|
|
@@ -2683,6 +2682,16 @@ _loop_runs() {
|
|
|
2683
2682
|
done <<<"$recent"
|
|
2684
2683
|
}
|
|
2685
2684
|
|
|
2685
|
+
# Send a macOS system notification. No-op when muted, non-macOS, or osascript unavailable.
|
|
2686
|
+
_notify() {
|
|
2687
|
+
local title="${1:-roll}"
|
|
2688
|
+
local body="${2:-}"
|
|
2689
|
+
[ "$(uname)" = "Darwin" ] || return 0
|
|
2690
|
+
[ -f "$_LOOP_MUTE_FILE" ] && return 0
|
|
2691
|
+
command -v osascript >/dev/null 2>&1 || return 0
|
|
2692
|
+
osascript -e "display notification \"${body}\" with title \"${title}\"" >/dev/null 2>&1 || true
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2686
2695
|
# Count `tcr:` prefixed commits in the current git repo since started_at timestamp.
|
|
2687
2696
|
_loop_tcr_count() {
|
|
2688
2697
|
local started_at="$1"
|
|
@@ -2690,6 +2699,87 @@ _loop_tcr_count() {
|
|
|
2690
2699
|
| awk '/^[a-f0-9]+ tcr:/{n++} END{print n+0}'
|
|
2691
2700
|
}
|
|
2692
2701
|
|
|
2702
|
+
# Poll gh run list until current commit's CI completes.
|
|
2703
|
+
# Returns 0 on success or when gh is unavailable (graceful skip).
|
|
2704
|
+
# Returns 1 on CI failure or timeout.
|
|
2705
|
+
_ci_wait() {
|
|
2706
|
+
local timeout="${1:-300}"
|
|
2707
|
+
local interval=15
|
|
2708
|
+
local elapsed=0
|
|
2709
|
+
|
|
2710
|
+
command -v gh &>/dev/null || { warn "gh not installed — skipping CI gate gh 未安装,跳过 CI 检查"; return 0; }
|
|
2711
|
+
|
|
2712
|
+
local commit; commit=$(git rev-parse HEAD 2>/dev/null) || { err "Not a git repo 非 git 仓库"; return 1; }
|
|
2713
|
+
local short; short=$(git rev-parse --short HEAD 2>/dev/null)
|
|
2714
|
+
|
|
2715
|
+
ok "Waiting for CI on ${short} 等待 CI: ${short}"
|
|
2716
|
+
|
|
2717
|
+
while (( elapsed < timeout )); do
|
|
2718
|
+
local runs
|
|
2719
|
+
runs=$(gh run list --commit "$commit" --json status,conclusion 2>/dev/null) || {
|
|
2720
|
+
warn "gh run list failed — skipping CI gate"
|
|
2721
|
+
return 0
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
if [[ -z "$runs" || "$runs" == "[]" ]]; then
|
|
2725
|
+
(( elapsed == 0 )) && echo " No CI runs found yet, waiting... 尚无 CI 记录,等待触发..."
|
|
2726
|
+
sleep "$interval"
|
|
2727
|
+
elapsed=$(( elapsed + interval ))
|
|
2728
|
+
continue
|
|
2729
|
+
fi
|
|
2730
|
+
|
|
2731
|
+
local pending
|
|
2732
|
+
pending=$(echo "$runs" | jq -r '[.[] | select(.status != "completed")] | length' 2>/dev/null || echo "0")
|
|
2733
|
+
|
|
2734
|
+
if [[ "$pending" -gt 0 ]]; then
|
|
2735
|
+
printf " ⏳ CI running (%ds)... CI 运行中(%ds)...\n" "$elapsed" "$elapsed"
|
|
2736
|
+
sleep "$interval"
|
|
2737
|
+
elapsed=$(( elapsed + interval ))
|
|
2738
|
+
continue
|
|
2739
|
+
fi
|
|
2740
|
+
|
|
2741
|
+
local failed
|
|
2742
|
+
failed=$(echo "$runs" | jq -r '[.[] | select(.conclusion != "success" and .conclusion != "skipped" and .conclusion != null)] | length' 2>/dev/null || echo "0")
|
|
2743
|
+
|
|
2744
|
+
if [[ "$failed" -gt 0 ]]; then
|
|
2745
|
+
err "CI failed for ${short} CI 失败: ${short}"
|
|
2746
|
+
return 1
|
|
2747
|
+
fi
|
|
2748
|
+
|
|
2749
|
+
ok "CI passed CI 通过"
|
|
2750
|
+
return 0
|
|
2751
|
+
done
|
|
2752
|
+
|
|
2753
|
+
warn "CI timed out after ${timeout}s CI 等待超时(${timeout}s)"
|
|
2754
|
+
return 1
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
# CI gate before marking a story Done.
|
|
2758
|
+
# On CI failure: writes ALERT, returns 1 (caller keeps story 🔨 In Progress).
|
|
2759
|
+
# When gh unavailable: returns 0 (graceful skip).
|
|
2760
|
+
_loop_enforce_ci() {
|
|
2761
|
+
local story_id="$1"
|
|
2762
|
+
|
|
2763
|
+
_ci_wait 300 && return 0
|
|
2764
|
+
|
|
2765
|
+
mkdir -p "$(dirname "$_LOOP_ALERT")"
|
|
2766
|
+
cat > "$_LOOP_ALERT" << EOF
|
|
2767
|
+
# ALERT — CI gate failed
|
|
2768
|
+
|
|
2769
|
+
**Time**: $(date '+%Y-%m-%d %H:%M')
|
|
2770
|
+
**Story**: ${story_id}
|
|
2771
|
+
**Commit**: $(git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
|
2772
|
+
**Reason**: CI did not pass — story kept as 🔨 In Progress CI 未通过,故事保持进行中
|
|
2773
|
+
|
|
2774
|
+
**Action required** (choose one):
|
|
2775
|
+
- Fix CI and re-run: \`roll loop now\`
|
|
2776
|
+
- Take over manually: \`\$roll-build ${story_id}\`
|
|
2777
|
+
- Reset and retry: \`roll loop reset\` then \`roll loop now\`
|
|
2778
|
+
EOF
|
|
2779
|
+
_notify "roll ⚠ CI Failed" "${story_id}: CI did not pass"
|
|
2780
|
+
return 1
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2693
2783
|
# Verify TCR rhythm after a story completes. Returns 0 if ok, 1 if no TCR commits.
|
|
2694
2784
|
# On failure: reverts story in BACKLOG.md to 📋 Todo and writes ALERT.
|
|
2695
2785
|
_loop_enforce_tcr() {
|
|
@@ -2722,6 +2812,7 @@ _loop_enforce_tcr() {
|
|
|
2722
2812
|
- Take over manually: \`\$roll-build ${story_id}\`
|
|
2723
2813
|
- Reset and retry: \`roll loop reset\` then \`roll loop now\`
|
|
2724
2814
|
EOF
|
|
2815
|
+
_notify "roll ⚠ TCR Failed" "${story_id}: no tcr: commits found"
|
|
2725
2816
|
return 1
|
|
2726
2817
|
fi
|
|
2727
2818
|
|
|
@@ -2802,7 +2893,7 @@ _loop_monitor() {
|
|
|
2802
2893
|
# Alert
|
|
2803
2894
|
if [[ -f "$_LOOP_ALERT" ]]; then
|
|
2804
2895
|
echo ""
|
|
2805
|
-
echo -e " ${RED}⚠ ALERT
|
|
2896
|
+
echo -e " ${RED}⚠ ALERT${NC} (${CYAN}roll alert${NC} to manage)"
|
|
2806
2897
|
sed 's/^/ /' "$_LOOP_ALERT"
|
|
2807
2898
|
fi
|
|
2808
2899
|
|
|
@@ -2973,6 +3064,88 @@ _backlog_extract_id() {
|
|
|
2973
3064
|
fi
|
|
2974
3065
|
}
|
|
2975
3066
|
|
|
3067
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
3068
|
+
# CI — check or wait for current commit's CI status
|
|
3069
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
3070
|
+
# ALERT — view / ack / resolve loop alert lifecycle
|
|
3071
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
3072
|
+
|
|
3073
|
+
cmd_alert() {
|
|
3074
|
+
local subcmd="${1:-list}"
|
|
3075
|
+
shift || true
|
|
3076
|
+
|
|
3077
|
+
case "$subcmd" in
|
|
3078
|
+
list|"")
|
|
3079
|
+
if [[ ! -f "$_LOOP_ALERT" ]]; then
|
|
3080
|
+
ok "No active alerts 暂无告警"
|
|
3081
|
+
return 0
|
|
3082
|
+
fi
|
|
3083
|
+
echo -e "${BOLD}Active Alert 当前告警${NC}"
|
|
3084
|
+
echo ""
|
|
3085
|
+
cat "$_LOOP_ALERT"
|
|
3086
|
+
echo ""
|
|
3087
|
+
echo -e " Run '${CYAN}roll alert ack${NC}' to acknowledge, '${CYAN}roll alert resolve${NC}' to clear."
|
|
3088
|
+
echo -e " 运行 'roll alert ack' 确认告警,'roll alert resolve' 清除告警。"
|
|
3089
|
+
;;
|
|
3090
|
+
ack)
|
|
3091
|
+
if [[ ! -f "$_LOOP_ALERT" ]]; then
|
|
3092
|
+
warn "No active alerts to acknowledge 暂无待确认告警"
|
|
3093
|
+
return 0
|
|
3094
|
+
fi
|
|
3095
|
+
local ts; ts=$(date '+%Y-%m-%d %H:%M:%S')
|
|
3096
|
+
{
|
|
3097
|
+
echo ""
|
|
3098
|
+
echo "**Acknowledged**: ${ts}"
|
|
3099
|
+
} >> "$_LOOP_ALERT"
|
|
3100
|
+
ok "Alert acknowledged at ${ts} 告警已确认"
|
|
3101
|
+
;;
|
|
3102
|
+
resolve|clear)
|
|
3103
|
+
if [[ ! -f "$_LOOP_ALERT" ]]; then
|
|
3104
|
+
ok "No active alerts 暂无告警"
|
|
3105
|
+
return 0
|
|
3106
|
+
fi
|
|
3107
|
+
rm -f "$_LOOP_ALERT"
|
|
3108
|
+
ok "Alert resolved and cleared 告警已解决并清除"
|
|
3109
|
+
;;
|
|
3110
|
+
*)
|
|
3111
|
+
err "Unknown subcommand: $subcmd 未知子命令: $subcmd"
|
|
3112
|
+
echo " Usage: roll alert [list|ack|resolve]"
|
|
3113
|
+
echo " 用法: roll alert [list|ack|resolve]"
|
|
3114
|
+
return 1
|
|
3115
|
+
;;
|
|
3116
|
+
esac
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
3120
|
+
|
|
3121
|
+
cmd_ci() {
|
|
3122
|
+
local wait_mode=false
|
|
3123
|
+
local timeout=300
|
|
3124
|
+
|
|
3125
|
+
while [[ $# -gt 0 ]]; do
|
|
3126
|
+
case "$1" in
|
|
3127
|
+
--wait) wait_mode=true; shift ;;
|
|
3128
|
+
--timeout=*) timeout="${1#*=}"; shift ;;
|
|
3129
|
+
*) err "Usage: roll ci [--wait] [--timeout=N] 用法: roll ci [--wait] [--timeout=N]"; exit 1 ;;
|
|
3130
|
+
esac
|
|
3131
|
+
done
|
|
3132
|
+
|
|
3133
|
+
if $wait_mode; then
|
|
3134
|
+
_ci_wait "$timeout"
|
|
3135
|
+
return
|
|
3136
|
+
fi
|
|
3137
|
+
|
|
3138
|
+
command -v gh &>/dev/null || { warn "gh not installed gh 未安装"; return 0; }
|
|
3139
|
+
local commit; commit=$(git rev-parse HEAD 2>/dev/null) || { err "Not a git repo 非 git 仓库"; return 1; }
|
|
3140
|
+
local runs
|
|
3141
|
+
runs=$(gh run list --commit "$commit" --json status,conclusion,name 2>/dev/null) || { warn "gh run list failed"; return 0; }
|
|
3142
|
+
if [[ -z "$runs" || "$runs" == "[]" ]]; then
|
|
3143
|
+
echo "No CI runs for $(git rev-parse --short HEAD) 当前提交无 CI 记录"
|
|
3144
|
+
return 0
|
|
3145
|
+
fi
|
|
3146
|
+
echo "$runs" | jq -r '.[] | "\(.name): \(.status)/\(.conclusion)"'
|
|
3147
|
+
}
|
|
3148
|
+
|
|
2976
3149
|
cmd_backlog() {
|
|
2977
3150
|
local backlog="BACKLOG.md"
|
|
2978
3151
|
if [[ ! -f "$backlog" ]]; then
|
|
@@ -3193,7 +3366,7 @@ _dashboard() {
|
|
|
3193
3366
|
else
|
|
3194
3367
|
echo -e " Loop ${YELLOW}○ off${NC} run: roll loop on"
|
|
3195
3368
|
fi
|
|
3196
|
-
[[ -f "$_LOOP_ALERT" ]] && echo -e " ${RED}⚠ ALERT — run: roll
|
|
3369
|
+
[[ -f "$_LOOP_ALERT" ]] && echo -e " ${RED}⚠ ALERT — run: roll alert${NC}"
|
|
3197
3370
|
|
|
3198
3371
|
# Backlog summary
|
|
3199
3372
|
if [[ -f "BACKLOG.md" ]]; then
|
|
@@ -3253,6 +3426,7 @@ usage() {
|
|
|
3253
3426
|
echo " backlog unblock <pat> Restore matching items to 📋 Todo 恢复为待处理"
|
|
3254
3427
|
echo " agent [use <name>|list] [Config] Per-project agent selection 切换项目 agent"
|
|
3255
3428
|
echo " release [Publish] Sync changelog + version bump + npm publish 同步日志并发版"
|
|
3429
|
+
echo " ci [--wait] [CI] Show or wait for current commit's CI status 查看/等待 CI 状态"
|
|
3256
3430
|
echo ""
|
|
3257
3431
|
echo "Examples / 示例:"
|
|
3258
3432
|
echo " roll setup # New machine: first-time install 新机器首次安装"
|
|
@@ -3280,8 +3454,10 @@ main() {
|
|
|
3280
3454
|
loop) cmd_loop "$@" ;;
|
|
3281
3455
|
brief) cmd_brief "$@" ;;
|
|
3282
3456
|
backlog) cmd_backlog "$@" ;;
|
|
3457
|
+
alert) cmd_alert "$@" ;;
|
|
3283
3458
|
agent) cmd_agent "$@" ;;
|
|
3284
3459
|
release) cmd_release "$@" ;;
|
|
3460
|
+
ci) cmd_ci "$@" ;;
|
|
3285
3461
|
version|--version|-v) echo "roll v${VERSION}" ;;
|
|
3286
3462
|
help|--help|-h) usage ;;
|
|
3287
3463
|
"") [[ -f "BACKLOG.md" ]] && _dashboard || { usage; _show_changelog; } ;;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seanyao/roll",
|
|
3
|
-
"version": "2026.512.
|
|
3
|
+
"version": "2026.512.7",
|
|
4
4
|
"description": "Roll — Roll out features with AI agents",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "
|
|
6
|
+
"test": "bash tests/run.sh"
|
|
7
7
|
},
|
|
8
8
|
"keywords": [
|
|
9
9
|
"ai",
|
|
@@ -101,6 +101,19 @@ CHANGELOG 是给**使用者**看的,不是给维护者看的。一句话讲清
|
|
|
101
101
|
- **Fixed**: 多个 loop 实例不会再互相打架(重复触发自动跳过)
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
❌ 说机制不说现象(Fix 类最常犯):
|
|
105
|
+
```
|
|
106
|
+
- **Fixed**: `roll loop runs` 过滤条件从完整路径改为 slug,历史记录不再因路径不匹配而消失
|
|
107
|
+
- **Fixed**: `roll-loop` skill 写入 `runs.jsonl` 时 project slug 计算方式明确,避免写成 bare basename
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
✅ 直接说用户看到了什么:
|
|
111
|
+
```
|
|
112
|
+
- **Fixed**: `roll loop runs` 不再报"当前项目尚无运行记录",历史记录正常显示
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Fix 类句式参考:`<命令/功能> 不再 <之前的坏现象>`,或 `<命令/功能> 现在 <正常表现>`。内部有几个 bug 导致这一个现象,合并成一条。
|
|
116
|
+
|
|
104
117
|
### 4. Section Header — Always `## Unreleased`
|
|
105
118
|
|
|
106
119
|
**⚠️ do NOT guess version numbers.** Only `scripts/release.sh` assigns concrete
|
|
@@ -152,11 +165,20 @@ version numbers like `v2026.511.8`. Just write to `## Unreleased`.
|
|
|
152
165
|
|
|
153
166
|
**Ordering**: Unreleased always at top. Below it, released versions in reverse chronological order.
|
|
154
167
|
|
|
155
|
-
### 6.
|
|
168
|
+
### 6. Stage Update
|
|
169
|
+
|
|
170
|
+
**Normal path (called from `$roll-build` or `$roll-fix`)**: stage only — the
|
|
171
|
+
caller's completion commit will pick up CHANGELOG.md.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
git add CHANGELOG.md
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Standalone / manual path** (called outside a roll-build session): stage and commit.
|
|
156
178
|
|
|
157
179
|
```bash
|
|
158
180
|
git add CHANGELOG.md
|
|
159
|
-
git commit -m "
|
|
181
|
+
git commit -m "chore: sync changelog"
|
|
160
182
|
git push
|
|
161
183
|
```
|
|
162
184
|
|
|
@@ -97,6 +97,46 @@ Find repeated structures that warrant extraction:
|
|
|
97
97
|
Flag: any pattern appearing 3+ times that could be extracted into a shared
|
|
98
98
|
utility or convention.
|
|
99
99
|
|
|
100
|
+
### Scan 5 — Doc Coverage Check
|
|
101
|
+
|
|
102
|
+
Check documentation structure against the conventions in `AGENTS.md § Documentation Conventions`.
|
|
103
|
+
|
|
104
|
+
**Check A — BACKLOG Done stories missing guide/en/ docs:**
|
|
105
|
+
|
|
106
|
+
Scan BACKLOG.md for features with multiple ✅ Done stories. For each feature epic, check whether a corresponding `docs/guide/en/<topic>.md` exists. If a feature has ≥3 Done stories and no guide doc, flag it.
|
|
107
|
+
|
|
108
|
+
**Check B — guide/en/ files missing guide/zh/ translations:**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
for f in docs/guide/en/*.md; do
|
|
112
|
+
base=$(basename "$f")
|
|
113
|
+
[ ! -f "docs/guide/zh/$base" ] && echo "missing ZH: $base"
|
|
114
|
+
done
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Flag any `docs/guide/en/<topic>.md` that has no matching `docs/guide/zh/<topic>.md`, provided the EN file has existed since before the most recent git tag (i.e., at least one release cycle old).
|
|
118
|
+
|
|
119
|
+
**Check C — stray files in docs/ root (根目录散落文件):**
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
find docs/ -maxdepth 1 -name '*.md' 2>/dev/null
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Flag any `.md` file directly in `docs/` root (allowed subdirs: `guide/`, `domain/`, `features/`, `practices/`, `briefs/`, `dream/`).
|
|
126
|
+
|
|
127
|
+
**REFACTOR entry format for doc findings:**
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
| REFACTOR-XXX | docs: {具体缺口描述} — flagged by dream {YYYY-MM-DD} | 📋 Todo |
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Dream log section** — add after existing sections:
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
## 文档覆盖度
|
|
137
|
+
{发现内容 或 "文档结构符合规范,无缺口。"}
|
|
138
|
+
```
|
|
139
|
+
|
|
100
140
|
## Output
|
|
101
141
|
|
|
102
142
|
### REFACTOR Entry (BACKLOG.md)
|
|
@@ -121,7 +161,7 @@ without context switching:
|
|
|
121
161
|
# Dream Log {YYYY-MM-DD}
|
|
122
162
|
|
|
123
163
|
## 概要
|
|
124
|
-
- 扫描项:死代码 / 架构漂移 / 裁剪候选 / 新兴模式
|
|
164
|
+
- 扫描项:死代码 / 架构漂移 / 裁剪候选 / 新兴模式 / 文档覆盖度
|
|
125
165
|
- 发现:{N} 项标记,{M} 个 REFACTOR 条目已创建
|
|
126
166
|
|
|
127
167
|
## 死代码
|
|
@@ -78,6 +78,9 @@ From BACKLOG.md and git log, classify all items since last brief:
|
|
|
78
78
|
- **Queue**: items still 📋 Todo (ordered by priority)
|
|
79
79
|
- **Dream findings**: any REFACTOR entries added by roll-.dream since last brief
|
|
80
80
|
- **Escalations**: any ALERT files in `~/.shared/roll/loop/` or `~/.shared/roll/dream/`
|
|
81
|
+
- **Doc coverage**: compute from `docs/guide/en/` and `docs/guide/zh/`:
|
|
82
|
+
- EN coverage = number of files in `docs/guide/en/`
|
|
83
|
+
- ZH translation rate = files in `docs/guide/zh/` ÷ files in `docs/guide/en/` × 100%
|
|
81
84
|
|
|
82
85
|
### Step 3 — Assess Release Readiness
|
|
83
86
|
|
|
@@ -132,6 +135,12 @@ A simple heuristic — not a gate, just a signal for the human:
|
|
|
132
135
|
## 需人工介入
|
|
133
136
|
{告警内容}
|
|
134
137
|
|
|
138
|
+
<!-- 始终输出 doc coverage 数字;若无缺口写"覆盖完整" -->
|
|
139
|
+
## 文档覆盖度
|
|
140
|
+
- guide/en: {N} 个文档
|
|
141
|
+
- ZH 翻译率:{M}/{N}({%})
|
|
142
|
+
- {缺口列表 或 "覆盖完整,无缺口。"}
|
|
143
|
+
|
|
135
144
|
## 发版就绪
|
|
136
145
|
{✅ 可发版 / ⚠️ 暂缓 — 原因}
|
|
137
146
|
|
|
@@ -509,17 +509,21 @@ For Fly mode: first append an index row under the appropriate Epic > Feature gro
|
|
|
509
509
|
|
|
510
510
|
If the US section does not yet exist, create the full section (AC / Files / Dependencies).
|
|
511
511
|
|
|
512
|
+
**Before committing, run `$roll-.changelog`** to stage CHANGELOG.md — then include
|
|
513
|
+
it in the completion commit so no separate changelog commit is created.
|
|
514
|
+
|
|
512
515
|
```bash
|
|
513
|
-
|
|
516
|
+
# 1. Stage changelog (roll-.changelog stages CHANGELOG.md only, does not commit)
|
|
517
|
+
$roll-.changelog
|
|
518
|
+
|
|
519
|
+
# 2. Commit BACKLOG + feature doc + CHANGELOG.md together
|
|
520
|
+
git add BACKLOG.md docs/features/ CHANGELOG.md
|
|
514
521
|
git commit -m "docs: mark {US-ID} as completed"
|
|
515
522
|
git push
|
|
516
523
|
```
|
|
517
524
|
|
|
518
525
|
### Phase 12: Report & Celebrate
|
|
519
526
|
|
|
520
|
-
**Before reporting, run `$roll-.changelog`** to sync completed Story to CHANGELOG.md.
|
|
521
|
-
This is mandatory — release notes depend on it.
|
|
522
|
-
|
|
523
527
|
```
|
|
524
528
|
✅ Pushed to GitHub: origin/main
|
|
525
529
|
🚀 Deployed: <url>
|
|
@@ -530,7 +534,7 @@ This is mandatory — release notes depend on it.
|
|
|
530
534
|
📊 TCR Stats: <success rate, revert count if any>
|
|
531
535
|
📋 Review Gate: <self-review findings summary>
|
|
532
536
|
📝 BACKLOG: <US-ID> marked ✅ Done
|
|
533
|
-
📄 CHANGELOG:
|
|
537
|
+
📄 CHANGELOG: bundled into completion commit (Phase 11)
|
|
534
538
|
|
|
535
539
|
🎉 Shipped.
|
|
536
540
|
|
|
@@ -604,7 +608,7 @@ Before creating any file or directory:
|
|
|
604
608
|
- [ ] **Verification Gate passed** (fresh evidence for tests, build, deploy, no regression)
|
|
605
609
|
- [ ] **BACKLOG.md index status updated** (📋 → ✅, REQUIRED)
|
|
606
610
|
- [ ] **`docs/features/<feature>.md` US section updated** (Completed date + [x] ACs, REQUIRED)
|
|
607
|
-
- [ ] **CHANGELOG.md
|
|
611
|
+
- [ ] **CHANGELOG.md staged and bundled** into completion commit via `$roll-.changelog` in Phase 11 (REQUIRED)
|
|
608
612
|
- [ ] Summary reported to user
|
|
609
613
|
|
|
610
614
|
---
|
|
@@ -142,9 +142,14 @@ After each item completes:
|
|
|
142
142
|
- Count `tcr:` prefix commits since `started_at` via `git log --oneline --since=<started_at>`
|
|
143
143
|
- Count == 0 → revert story status in BACKLOG.md from ✅ Done → 📋 Todo; write ALERT to `~/.shared/roll/loop/ALERT.md` with story ID, time, reason "zero tcr: commits since story start", and suggested actions (`roll loop now` / `$roll-build <id>` / `roll loop reset`)
|
|
144
144
|
- Count > 0 → continue normally
|
|
145
|
-
2.
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
2. **CI Gate** — call `roll ci --wait` (or `_loop_enforce_ci <story_id>`):
|
|
146
|
+
- Polls `gh run list --commit <HEAD>` until all CI runs complete
|
|
147
|
+
- CI passes → continue normally
|
|
148
|
+
- CI fails or times out → keep story as `🔨 In Progress` (do NOT mark ✅ Done); write ALERT; skip to next story
|
|
149
|
+
- `gh` not installed → skip gracefully (return 0)
|
|
150
|
+
3. Update state file: `status: idle`
|
|
151
|
+
4. Check if a Feature is now fully complete (all its Stories ✅)
|
|
152
|
+
5. If yes and `brief_on_feature_complete: true` → invoke `Skill("roll-brief")`
|
|
148
153
|
|
|
149
154
|
### Step 5 — Write Run Summary
|
|
150
155
|
|
|
@@ -180,7 +185,7 @@ final report in `cron.log` instead.
|
|
|
180
185
|
| Field | Type | Format / Enum |
|
|
181
186
|
|---|---|---|
|
|
182
187
|
| `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. |
|
|
183
|
-
| `project` | string | Project **slug** only (e.g. `roll-d9dfa0`), NOT the absolute path
|
|
188
|
+
| `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}"` |
|
|
184
189
|
| `run_id` | string | Matches `state.yaml` `run_id` exactly. Format: `loop-YYYYMMDD-HHMM`. |
|
|
185
190
|
| `status` | enum | Exactly one of: `built` (≥1 story shipped), `idle` (no Todo items found), `failed` (paused/error). **No synonyms.** |
|
|
186
191
|
| `built` | array<string> | Story ids completed this cycle. `[]` when none. **Always array, never null/number.** |
|
|
@@ -196,7 +201,13 @@ Optional field, only when `status == "failed"`:
|
|
|
196
201
|
|
|
197
202
|
```bash
|
|
198
203
|
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
199
|
-
project
|
|
204
|
+
# Compute project slug — inlined equivalent of bin/roll's _project_slug
|
|
205
|
+
# (Claude sessions can't call roll's internal functions, so we inline).
|
|
206
|
+
# Must produce identical output to _project_slug to match `roll loop runs` filter.
|
|
207
|
+
_p=$(pwd -P)
|
|
208
|
+
_base=$(basename "$_p" | tr -cs '[:alnum:]' '-' | sed 's/-*$//')
|
|
209
|
+
_hash=$(printf '%s' "$_p" | md5 | cut -c1-6 2>/dev/null || printf '%s' "$_p" | md5sum | cut -c1-6)
|
|
210
|
+
project="${_base}-${_hash}" # e.g. roll-d9dfa0 — must match roll loop runs filter
|
|
200
211
|
# duration_sec = cycle_end_epoch - cycle_start_epoch (track at Step 1)
|
|
201
212
|
# tcr_count = git log --oneline --since="<cycle_start>" | grep -c '^[a-f0-9]* tcr:'
|
|
202
213
|
|