@seanyao/roll 2026.529.5 → 2026.601.2
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 +57 -25
- package/README.md +10 -7
- package/bin/roll +3952 -317
- package/conventions/config.yaml +7 -0
- package/lib/__pycache__/github_sync.cpython-314.pyc +0 -0
- package/lib/__pycache__/loop_result_eval.cpython-314.pyc +0 -0
- package/lib/__pycache__/model_prices.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__/slides-render.cpython-314.pyc +0 -0
- package/lib/agent_usage/__init__.py +4 -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__/qwen.cpython-314.pyc +0 -0
- package/lib/agent_usage/gemini.py +127 -0
- package/lib/agent_usage/kimi.py +127 -0
- package/lib/agent_usage/openai.py +126 -0
- package/lib/agent_usage/qwen.py +128 -0
- package/lib/context_feed_budget.sh +194 -0
- package/lib/github_sync.py +876 -0
- package/lib/i18n/agent.sh +54 -0
- package/lib/i18n/init.sh +22 -0
- package/lib/i18n/peer.sh +7 -0
- package/lib/i18n/peer_help.sh +4 -0
- package/lib/i18n/skills_catalog.sh +30 -0
- package/lib/loop-exit-summary.py +393 -0
- package/lib/loop-fmt.py +93 -75
- package/lib/loop_pick_agent.py +241 -170
- package/lib/loop_result_eval.py +469 -0
- package/lib/model_prices.py +0 -10
- package/lib/roll-home.py +1 -28
- package/lib/roll-loop-status.py +330 -40
- package/lib/roll-onboard-render.py +378 -0
- package/lib/roll-peer.py +1 -1
- package/lib/roll-plan-validate.py +165 -0
- package/lib/roll_git.py +41 -0
- package/lib/slides/components/README.md +8 -2
- package/lib/slides/templates/introduction-v3.html +1 -6
- package/lib/slides-render.py +305 -15
- package/lib/slides-validate.py +195 -7
- package/package.json +1 -1
- package/skills/roll-.changelog/SKILL.md +67 -56
- package/skills/roll-brief/SKILL.md +1 -1
- package/skills/roll-build/SKILL.md +14 -12
- package/skills/roll-deck/SKILL.md +152 -0
- package/skills/roll-design/SKILL.md +13 -6
- package/skills/roll-doc/SKILL.md +269 -6
- package/skills/roll-fix/SKILL.md +15 -9
- package/skills/roll-loop/SKILL.md +9 -7
- package/skills/roll-notes/SKILL.md +1 -1
- package/skills/roll-onboard/SKILL.md +85 -0
- package/skills/roll-peer/SKILL.md +6 -5
- package/lib/agent_routes_lint.py +0 -203
- package/skills/roll-research/SKILL.md +0 -316
- package/skills/roll-research/references/schema.json +0 -166
- package/skills/roll-research/scripts/md_to_pdf.py +0 -289
package/skills/roll-doc/SKILL.md
CHANGED
|
@@ -95,12 +95,13 @@ Walk every directory (applying Phase 1 exclusions):
|
|
|
95
95
|
|
|
96
96
|
1. Count non-hidden, non-`.md` source files directly in the directory
|
|
97
97
|
2. If count ≥ 3 AND no `README.md` in that directory AND no `docs/INDEX.md` entry links to it → **module gap**
|
|
98
|
+
3. **High fan-in gap**: a directory imported by **≥ 5 other source files** is a gap targeting `<dir>/README.md`, **even if it has < 3 source files** — critical low-volume modules (shared utils, single-file core) must not be skipped by the file-count threshold. The existing count ≥ 3 rule (rule 2) continues to apply independently; high fan-in only widens what qualifies, it never overrides rule 2.
|
|
98
99
|
|
|
99
100
|
**Special gaps (checked once per project):**
|
|
100
101
|
- No `.roll/domain/` directory or empty → gap: `.roll/domain/context-map.md`
|
|
101
102
|
- No `CONVENTIONS.md` or `docs/CONVENTIONS.md` exists → gap: `docs/CONVENTIONS.md`
|
|
102
103
|
|
|
103
|
-
**Threshold**:
|
|
104
|
+
**Threshold**: a directory qualifies for a module README gap when **file count ≥ 3 OR imported by ≥ 5 other source files** (default). The fan-in count comes from the Phase 3b symbol table `imports` edges; exclude test files (`*.test.*`, `*.spec.*`, `tests/`) when counting referencing files. An existing `<dir>/README.md` is never overwritten unless `--force`. Tune by editing the skill.
|
|
104
105
|
|
|
105
106
|
Record all gaps — they become Phase 3 input.
|
|
106
107
|
|
|
@@ -177,9 +178,12 @@ Pure documentation-only projects (no source code gaps, no code characteristics)
|
|
|
177
178
|
|
|
178
179
|
### Step 1 — Build Symbol Table
|
|
179
180
|
|
|
180
|
-
Read
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
Read each source file through the context-feed budget (US-CTX-001), not by hard-stuffing whole
|
|
182
|
+
files unconditionally. The existing Phase 3 "up to 20 source files" count limit does not apply —
|
|
183
|
+
Phase 3b aims for a complete project symbol table — but per-file material still goes through the
|
|
184
|
+
feed budget: files within budget are read in full, and over-budget files are summarized/chunked
|
|
185
|
+
with an explicit notice (never silently truncated) so the inner agent's context window is not
|
|
186
|
+
blown. This replaces the previous "read every source file in full, no truncation" unbounded path.
|
|
183
187
|
|
|
184
188
|
**Exclusion directories** (same as Phase 1):
|
|
185
189
|
|
|
@@ -272,6 +276,236 @@ If no chain meets the ≥ 3 directory threshold, skip generation entirely (no em
|
|
|
272
276
|
|
|
273
277
|
**Idempotency:** skip (do not overwrite) if `docs/data-flows.md` already exists, unless `--force`.
|
|
274
278
|
|
|
279
|
+
#### State Machine
|
|
280
|
+
|
|
281
|
+
**Detection rule:** enums whose name matches `*State` or `*Status` (case-insensitive)
|
|
282
|
+
AND that are imported/referenced by **≥ 2 distinct source files**. Only count
|
|
283
|
+
imports from source files — exclude test files (`*.test.*`, `*.spec.*`, `tests/`)
|
|
284
|
+
and declaration files (`*.d.ts`).
|
|
285
|
+
|
|
286
|
+
**Threshold:** if no enum meets the ≥ 2 cross-file reference threshold, skip
|
|
287
|
+
generation entirely (no empty `docs/state-machines.md`).
|
|
288
|
+
|
|
289
|
+
**Output document structure** (`docs/state-machines.md`):
|
|
290
|
+
|
|
291
|
+
```markdown
|
|
292
|
+
> **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
|
|
293
|
+
|
|
294
|
+
# State Machines
|
|
295
|
+
|
|
296
|
+
## State: `{EnumName}`
|
|
297
|
+
|
|
298
|
+
**Defined in:** `{file}:{line}`
|
|
299
|
+
|
|
300
|
+
### States
|
|
301
|
+
{list of all enum values}
|
|
302
|
+
|
|
303
|
+
### Referenced By
|
|
304
|
+
|
|
305
|
+
| File:Line | Context |
|
|
306
|
+
|-----------|---------|
|
|
307
|
+
| `path/to/file:12` | `function processOrder(status: OrderState)` |
|
|
308
|
+
| `path/to/file:34` | `if (status === OrderState.Pending)` |
|
|
309
|
+
|
|
310
|
+
### Inferred Transitions
|
|
311
|
+
|
|
312
|
+
| From | To | Evidence |
|
|
313
|
+
|------|----|----------|
|
|
314
|
+
| `Pending` | `Processing` | `order.ts:45` — `if (status === Pending) { status = Processing }` |
|
|
315
|
+
| `Processing` | `Shipped` | `handler.ts:78` — assignment after `ship()` call |
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Transition inference:** scan the referencing files for patterns where an enum
|
|
319
|
+
value is checked (`if (status === X)`, `case X:`) and the status variable is
|
|
320
|
+
reassigned to another enum value in the same block. Record each distinct
|
|
321
|
+
`{from, to, evidence file:line}` pair. Only include transitions backed by
|
|
322
|
+
explicit code — do not fabricate implied transitions.
|
|
323
|
+
|
|
324
|
+
**Output rules:**
|
|
325
|
+
- One top-level `## State:` section per qualifying enum, sorted alphabetically.
|
|
326
|
+
- Each enum section lists all defined values under `### States`.
|
|
327
|
+
- `file:line` annotations must come from actual symbol table records — do not fabricate.
|
|
328
|
+
- Existing `docs/state-machines.md` → skip unless `--force`.
|
|
329
|
+
- No qualifying enum → skip generation entirely (no empty document).
|
|
330
|
+
|
|
331
|
+
#### External Integrations
|
|
332
|
+
|
|
333
|
+
**Detection rule:** scan `external_urls` from the symbol table —
|
|
334
|
+
`fetch(...)` / `axios` / `http.get` (and `http.*`) calls, constants shaped like
|
|
335
|
+
`API_ENDPOINT` / `*_URL` / `*_HOST`, and hardcoded `https?://` strings. Exclude
|
|
336
|
+
matches inside comments and test fixtures (`*.test.*`, `*.spec.*`, `tests/`,
|
|
337
|
+
`fixtures/`).
|
|
338
|
+
|
|
339
|
+
**Threshold:** if no external integration is detected, skip generation entirely
|
|
340
|
+
(no empty `docs/integrations.md`).
|
|
341
|
+
|
|
342
|
+
**Output document structure** (`docs/integrations.md`):
|
|
343
|
+
|
|
344
|
+
```markdown
|
|
345
|
+
> **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
|
|
346
|
+
|
|
347
|
+
# External Integrations
|
|
348
|
+
|
|
349
|
+
## Integration: `{endpoint URL}`
|
|
350
|
+
|
|
351
|
+
### Call Sites
|
|
352
|
+
|
|
353
|
+
| File:Line | Timeout | Error Handling / Fallback |
|
|
354
|
+
|-----------|---------|---------------------------|
|
|
355
|
+
| `path/to/file:12` | `timeout: 5000` | `.catch` retry fallback |
|
|
356
|
+
| `path/to/file:48` | — | try/catch |
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Per-integration fields:**
|
|
360
|
+
- **endpoint URL** — the external URL / endpoint reached.
|
|
361
|
+
- **call file:line** — every source location calling this endpoint.
|
|
362
|
+
- **timeout config** — the value if the calling code carries a `timeout: N` field,
|
|
363
|
+
otherwise `—`.
|
|
364
|
+
- **error handling / fallback** — recorded when the calling code has a `.catch`
|
|
365
|
+
handler or a `try` / `catch` block around the call, otherwise `—`.
|
|
366
|
+
|
|
367
|
+
**Output rules:**
|
|
368
|
+
- The same endpoint reached from multiple sites is merged into **one** integration
|
|
369
|
+
section that lists **all** its call sites — never one section per call.
|
|
370
|
+
- One top-level `## Integration:` section per distinct endpoint, sorted alphabetically.
|
|
371
|
+
- `file:line` annotations must come from actual symbol table records — do not fabricate.
|
|
372
|
+
- Existing `docs/integrations.md` → skip unless `--force`.
|
|
373
|
+
- No external integration detected → skip generation entirely (no empty document).
|
|
374
|
+
|
|
375
|
+
#### Deployment Pipeline
|
|
376
|
+
|
|
377
|
+
**Detection rule:** the project has at least one CI configuration file —
|
|
378
|
+
`.github/workflows/*.yml` (or `*.yaml`) / `.gitlab-ci.yml` / `circle.yml` /
|
|
379
|
+
`.circleci/config.yml` / `Jenkinsfile` — AND a deploy URL pattern appears in the
|
|
380
|
+
code or CI config (vercel / netlify / cloudflare / firebase, or hostnames ending
|
|
381
|
+
in `*.app` / `*.dev`). Pull deploy URLs from the `configs` and `external_urls`
|
|
382
|
+
fields of the symbol table.
|
|
383
|
+
|
|
384
|
+
**Threshold:** if no CI configuration file is detected, skip generation entirely
|
|
385
|
+
(no empty `docs/deployment.md`).
|
|
386
|
+
|
|
387
|
+
**Output document structure** (`docs/deployment.md`):
|
|
388
|
+
|
|
389
|
+
```markdown
|
|
390
|
+
> **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
|
|
391
|
+
|
|
392
|
+
# Deployment
|
|
393
|
+
|
|
394
|
+
## Pipeline: `{ci config file}`
|
|
395
|
+
|
|
396
|
+
**CI Platform:** GitHub Actions
|
|
397
|
+
**Trigger events:** push (main), pull_request, release
|
|
398
|
+
|
|
399
|
+
### Key Jobs
|
|
400
|
+
|
|
401
|
+
| Job | File:Line | Purpose |
|
|
402
|
+
|-----|-----------|---------|
|
|
403
|
+
| `test` | `.github/workflows/deploy.yml:18` | run test suite |
|
|
404
|
+
| `build` | `.github/workflows/deploy.yml:25` | compile artifacts |
|
|
405
|
+
| `deploy` | `.github/workflows/deploy.yml:33` | deploy to Vercel |
|
|
406
|
+
|
|
407
|
+
### Deploy Targets
|
|
408
|
+
|
|
409
|
+
| URL | File:Line |
|
|
410
|
+
|-----|-----------|
|
|
411
|
+
| `https://my-app.vercel.app` | `.github/workflows/deploy.yml:14` |
|
|
412
|
+
|
|
413
|
+
### Environment Variables
|
|
414
|
+
|
|
415
|
+
| Name | File:Line |
|
|
416
|
+
|------|-----------|
|
|
417
|
+
| `NODE_ENV` | `.github/workflows/deploy.yml:11` |
|
|
418
|
+
| `VERCEL_TOKEN` | `.github/workflows/deploy.yml:12` |
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**Per-pipeline fields:**
|
|
422
|
+
- **CI platform** — inferred from which config file is present (GitHub Actions /
|
|
423
|
+
GitLab CI / CircleCI / Jenkins).
|
|
424
|
+
- **trigger events** — the events that start the pipeline (`push` / `pull_request` /
|
|
425
|
+
`tag` / `release`), read from the CI config.
|
|
426
|
+
- **key jobs** — each job / stage name with its `file:line` location.
|
|
427
|
+
- **deploy target URL** — the deploy URL(s) matched by the detection rule.
|
|
428
|
+
- **environment variable names** — every env var name referenced in the CI config,
|
|
429
|
+
listed **without values** (never emit secret values, only names).
|
|
430
|
+
|
|
431
|
+
**Output rules:**
|
|
432
|
+
- One top-level `## Pipeline:` section per CI configuration file, sorted alphabetically.
|
|
433
|
+
- `file:line` annotations must come from actual symbol table / CI config records — do not fabricate.
|
|
434
|
+
- Existing `docs/deployment.md` → skip unless `--force`.
|
|
435
|
+
- No CI configuration detected → skip generation entirely (no empty document).
|
|
436
|
+
|
|
437
|
+
#### Agent Entrypoint (AGENTS.md)
|
|
438
|
+
|
|
439
|
+
This topic handles the **「文件不存在 → 创建」** case: when a project has no agent-facing
|
|
440
|
+
convention file at all, generate a complete baseline `AGENTS.md`. It is complementary to the
|
|
441
|
+
Phase 2 **"AGENTS.md Where to Look bootstrap"** rule, which handles the **「文件存在 → 补章节」**
|
|
442
|
+
case (append a missing `## Where to Look` section to an existing `AGENTS.md`). The two rules
|
|
443
|
+
never overlap — this one only fires when no `AGENTS.md` exists.
|
|
444
|
+
|
|
445
|
+
**Detection rule:** project root has **no** `AGENTS.md` AND the source root (`src/`, or the
|
|
446
|
+
equivalent — `lib/`, `app/`, `pkg/`, etc.) contains **≥ 3 subdirectories**. If `AGENTS.md`
|
|
447
|
+
already exists, skip entirely (do not overwrite unless `--force`). If the source root has
|
|
448
|
+
fewer than 3 subdirectories, skip — the project is too small to warrant a baseline doc.
|
|
449
|
+
|
|
450
|
+
**Output document structure** (`AGENTS.md`) — at minimum three required sections:
|
|
451
|
+
|
|
452
|
+
```markdown
|
|
453
|
+
> **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
|
|
454
|
+
|
|
455
|
+
# {Project Name}
|
|
456
|
+
|
|
457
|
+
{One-sentence positioning: what this project is, inferred from README / package metadata.}
|
|
458
|
+
|
|
459
|
+
## Where to Look
|
|
460
|
+
|
|
461
|
+
- **Domain model**: `.roll/domain/context-map.md` — Contexts: {list, or "see file"}
|
|
462
|
+
- **Story details**: `.roll/features/` — AC, implementation specs, dependencies
|
|
463
|
+
- **Doc index**: `docs/INDEX.md` — generated documentation map
|
|
464
|
+
|
|
465
|
+
## Source Layout
|
|
466
|
+
|
|
467
|
+
| Directory | Purpose |
|
|
468
|
+
|-----------|---------|
|
|
469
|
+
| `src/parser/` | tokenize and parse input (≤ 2 lines each) |
|
|
470
|
+
| `src/codegen/` | emit output artifacts |
|
|
471
|
+
| `src/cli/` | command-line entry and option wiring |
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**Per-section rules:**
|
|
475
|
+
- **Project positioning** — a single sentence describing what the project does, inferred from
|
|
476
|
+
the README / package metadata; never fabricate beyond what the source supports.
|
|
477
|
+
- **`## Where to Look`** — pointer lines **only for directories that actually exist**
|
|
478
|
+
(`.roll/domain/`, `.roll/features/`, `docs/INDEX.md`, etc.); never fabricate pointers to
|
|
479
|
+
missing paths. If `.roll/domain/context-map.md` exists, read it for Bounded Context names.
|
|
480
|
+
- **Source Layout** — one row per key source subdirectory, each description **≤ 2 lines**,
|
|
481
|
+
inferred from the files actually read in the symbol table.
|
|
482
|
+
|
|
483
|
+
**Output rules:**
|
|
484
|
+
- Existing `AGENTS.md` → skip unless `--force` (never overwrite a human-authored file).
|
|
485
|
+
- Source root with < 3 subdirectories → skip generation entirely (no empty `AGENTS.md`).
|
|
486
|
+
- All three sections must be present in the generated file.
|
|
487
|
+
|
|
488
|
+
#### High Fan-in Directory (README)
|
|
489
|
+
|
|
490
|
+
This topic complements the Phase 2 file-count threshold. A directory may hold only one or two
|
|
491
|
+
source files yet be imported across the whole codebase (shared utils, a single-file core
|
|
492
|
+
module). The file-count rule (≥ 3 files) alone skips such hot paths, so high fan-in widens the
|
|
493
|
+
threshold to **「文件数 ≥ 3 OR 被 ≥ 5 个文件引用」**.
|
|
494
|
+
|
|
495
|
+
**Detection rule:** using the symbol table's `imports` edges, count the **distinct source files
|
|
496
|
+
that import any file in the directory**. If that count is **≥ 5**, the directory qualifies for a
|
|
497
|
+
`<dir>/README.md` gap, **even when it contains < 3 source files**. Only count referencing files
|
|
498
|
+
that are source files — exclude test files (`*.test.*`, `*.spec.*`, `tests/`) and files inside
|
|
499
|
+
the directory itself. This rule operates **in addition to** the Phase 2 count ≥ 3 rule, never
|
|
500
|
+
replacing it: directories meeting either condition get a README.
|
|
501
|
+
|
|
502
|
+
**Output rules:**
|
|
503
|
+
- Target file is `<dir>/README.md`, generated with the same Module README content as Phase 3
|
|
504
|
+
(purpose, key files, dependencies).
|
|
505
|
+
- Existing `<dir>/README.md` → skip unless `--force` (never overwrite).
|
|
506
|
+
- Directory imported by < 5 source files **and** holding < 3 source files → skip (no gap).
|
|
507
|
+
- A directory already qualifying under the count ≥ 3 rule is not double-counted — one README.
|
|
508
|
+
|
|
275
509
|
### Step 3 — Source Annotations
|
|
276
510
|
|
|
277
511
|
Every topic document generated in Step 2 must cite `file:line` for each claim (function call,
|
|
@@ -279,6 +513,16 @@ endpoint URL, state transition, CI job, import path). Annotations must come from
|
|
|
279
513
|
symbol table records — do not fabricate line numbers. Follows the same "Do not fabricate"
|
|
280
514
|
rule as Phase 3.
|
|
281
515
|
|
|
516
|
+
**Mandatory `file:line` column** — each topic document's source-reference tables MUST carry a
|
|
517
|
+
dedicated `file:line` column so the reader can jump straight to the code:
|
|
518
|
+
- 「涉及文件」/ Files Involved table → one `file:line` per row.
|
|
519
|
+
- 「引用文件」/ Referenced By table → one `file:line` per referencing site.
|
|
520
|
+
- 「调用链」/ Complete Call Chain table → one `file:line` per hop.
|
|
521
|
+
|
|
522
|
+
Do **not** fabricate a `file:line` value: every annotation MUST come from an actual symbol
|
|
523
|
+
table record (the same "Do not fabricate" rule as above). If the symbol table has no line for
|
|
524
|
+
a claim, omit the row rather than invent a location.
|
|
525
|
+
|
|
282
526
|
---
|
|
283
527
|
|
|
284
528
|
## Phase 4 — Report
|
|
@@ -302,15 +546,34 @@ Phase 3 — Fill
|
|
|
302
546
|
|
|
303
547
|
Phase 3b — Deep Read
|
|
304
548
|
Symbol table: exports(N) imports(N) enums(N) external_urls(N) configs(N)
|
|
305
|
-
N topic documents generated:
|
|
549
|
+
N topic documents generated:
|
|
550
|
+
- docs/dataflow.md (data-flow) source entries: N
|
|
551
|
+
- docs/state-machines.md (state-machine) source entries: N
|
|
552
|
+
- docs/integrations.md (external-integration) source entries: N
|
|
306
553
|
N topics skipped (no matches or already exist; use --force to regenerate)
|
|
307
|
-
(if no topics generated: "no subject-level drafts generated")
|
|
308
554
|
|
|
309
555
|
📋 Review priority (largest / most active modules first):
|
|
310
556
|
1. src/commands/README.md — 8 source files
|
|
311
557
|
2. docs/CONVENTIONS.md — 6 patterns detected
|
|
312
558
|
```
|
|
313
559
|
|
|
560
|
+
Each generated topic document is listed with its **path**, **type**, and **来源条目数 /
|
|
561
|
+
source entries** (how many symbol-table records back the document). When Phase 3b produced no
|
|
562
|
+
subject-level documents, print exactly one line and do **not** error:
|
|
563
|
+
|
|
564
|
+
```
|
|
565
|
+
Phase 3b: no subject-level drafts generated
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
If `--dry-run`, the `Phase 3b — Deep Read` section is shown the same way but every generated
|
|
569
|
+
line is tagged `(plan)` — matching Phase 3's dry-run convention (nothing is written):
|
|
570
|
+
|
|
571
|
+
```
|
|
572
|
+
Phase 3b — Deep Read (plan)
|
|
573
|
+
N topic documents would be generated:
|
|
574
|
+
- docs/dataflow.md (data-flow) source entries: N (plan)
|
|
575
|
+
```
|
|
576
|
+
|
|
314
577
|
If no gaps were found:
|
|
315
578
|
|
|
316
579
|
```
|
package/skills/roll-fix/SKILL.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roll-fix
|
|
3
3
|
license: MIT
|
|
4
|
+
allowed-tools: "Read, Edit, Write, Glob, Grep, Bash, Skill"
|
|
4
5
|
description: Execute bugfix/hotfix from backlog. Reads FIX/BUG from .roll/backlog.md, delivers via TCR workflow. Lighter than roll-build, focused on single-issue fixes.
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -89,24 +90,29 @@ Before creating any file or directory:
|
|
|
89
90
|
|
|
90
91
|
### 0. Pre-flight self-check (US-AGENT-007)
|
|
91
92
|
|
|
92
|
-
Before locking the issue, read the FIX's Agent profile (est_min /
|
|
93
|
+
Before locking the issue, read the FIX's Agent profile (est_min / chain_depth) from the linked feature md and decide whether this cycle should attempt the fix:
|
|
93
94
|
|
|
94
95
|
```
|
|
95
96
|
inputs:
|
|
96
97
|
fix.est_min (from **Agent profile:** block on the FIX row's feature md)
|
|
97
|
-
fix.risk_zone (low / medium / high)
|
|
98
98
|
fix.chain_depth (0 unless already a downgrade product)
|
|
99
|
-
agent.max_est_min (from .roll/agent-routes.yaml for the current agent)
|
|
100
|
-
history.prefer_threshold + history.hit_rate (FIX history for this agent)
|
|
101
99
|
|
|
102
100
|
verdict:
|
|
103
|
-
too_big when
|
|
104
|
-
|
|
105
|
-
2. fix.risk_zone not in agent.risk
|
|
106
|
-
3. history.hit_rate < prefer_threshold AND fix.chain_depth == 0
|
|
101
|
+
too_big when:
|
|
102
|
+
fix.est_min > 20 (lands in the `hard` complexity tier)
|
|
107
103
|
ok otherwise
|
|
108
104
|
```
|
|
109
105
|
|
|
106
|
+
Routing is a single axis now (US-AGENT-022): `est_min` maps to one of three
|
|
107
|
+
complexity tiers — `easy` (≤8), `default` (8<x≤20), `hard` (>20) — and each
|
|
108
|
+
tier binds to a locally-installed agent slot in `.roll/agents.yaml` (model =
|
|
109
|
+
the agent's own default; a `fallback` slot mechanically covers an unavailable
|
|
110
|
+
agent). The retired v1 model (three-dimension type/est/risk_zone matching
|
|
111
|
+
against `agent-routes.yaml`, soft history hit-rate preference, per-agent
|
|
112
|
+
`max_est_min`/`risk`) no longer applies. The pre-flight verdict here is just
|
|
113
|
+
the `hard`-tier boundary: a FIX estimated past it is a sanity signal that the
|
|
114
|
+
"single small fix" assumption may be wrong.
|
|
115
|
+
|
|
110
116
|
Emit `verdict: ok` or `verdict: too_big` (with `reason:`) as the first cycle output line.
|
|
111
117
|
|
|
112
118
|
- `ok` → continue with step 1 below normally
|
|
@@ -369,7 +375,7 @@ Change the Status of the corresponding row from `📋 Todo` or `🔨 In Progress
|
|
|
369
375
|
|
|
370
376
|
### 12. Update Changelog
|
|
371
377
|
|
|
372
|
-
**Mandatory** — release
|
|
378
|
+
**Mandatory** — the release (GitHub Release body = this version's changelog section) depends on this step. Do not skip.
|
|
373
379
|
|
|
374
380
|
```bash
|
|
375
381
|
$roll-.changelog
|
|
@@ -247,7 +247,7 @@ Together these mean: only one loop runs at a time per project (LOCK), and within
|
|
|
247
247
|
> 2. Read its Agent profile (est_min / risk_zone) and routed an agent via `_loop_pick_agent_for_story` (hard rules from `.roll/agent-routes.yaml` + soft preference from `runs.jsonl`)
|
|
248
248
|
> 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
|
|
249
249
|
>
|
|
250
|
-
> 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 —
|
|
250
|
+
> 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), re-pick the next eligible Todo via `_loop_pick_next_story` rather than idling the whole cycle.
|
|
251
251
|
>
|
|
252
252
|
> Old single-agent fallback (`primary_agent` from `~/.roll/config.yaml`) still applies when:
|
|
253
253
|
> - no story is pickable (empty Todo / all manual-only)
|
|
@@ -344,12 +344,14 @@ After each item completes:
|
|
|
344
344
|
|
|
345
345
|
**Path B — heal exhausted (≥`ROLL_LOOP_HEAL_MAX`, default 2) or disabled (`ROLL_LOOP_NO_HEAL=1`) (exit 1):**
|
|
346
346
|
|
|
347
|
-
1. Do NOT force ✅ Done here. CI red means the PR will not merge
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
347
|
+
1. Do NOT force ✅ Done here. CI red means the PR will not merge. Under
|
|
348
|
+
**US-AUTO-044** the main loop no longer waits for merge — it publishes the
|
|
349
|
+
PR and exits; the dedicated PR Loop (`com.roll.pr.<slug>`, every 5 min)
|
|
350
|
+
merges / rebases / closes it asynchronously. There is no false-Done risk:
|
|
351
|
+
with worktree isolation the ✅ Done lives only in the unmerged PR, never on
|
|
352
|
+
the loop's main checkout, and the story is not re-picked meanwhile via the
|
|
353
|
+
open-PR eligibility gate (`_loop_story_is_eligible`, FIX-146). The story's
|
|
354
|
+
✅ Done lands on main only when the PR Loop actually merges the PR.
|
|
353
355
|
2. Write ALERT to `~/.shared/roll/loop/ALERT-<slug>.md` with:
|
|
354
356
|
- story ID, time, commit SHA
|
|
355
357
|
- heal attempts made (read `heal_count:` from `state-<slug>.yaml`)
|
|
@@ -24,7 +24,7 @@ $roll-notes 今天的 code review 给了很好的反馈
|
|
|
24
24
|
## When Not to Use
|
|
25
25
|
|
|
26
26
|
- Capturing a bug or feature idea into BACKLOG (use `$roll-idea`)
|
|
27
|
-
- Generating user-facing
|
|
27
|
+
- Generating the user-facing changelog (use `$roll-.changelog`)
|
|
28
28
|
- Writing design documents or AC (use `$roll-design`)
|
|
29
29
|
|
|
30
30
|
## Behavior
|
|
@@ -55,6 +55,58 @@ Walk the repo. Identify:
|
|
|
55
55
|
- **domains**: top business/technical domains (e.g., "auth", "billing", "search")
|
|
56
56
|
- **key_modules**: top 3-5 modules that hold most of the logic
|
|
57
57
|
|
|
58
|
+
### Step 1b — Phase 2 analysis: business model, tech, tests (US-ONBOARD-016)
|
|
59
|
+
|
|
60
|
+
A single onboard now produces three structured analysis sections in the plan
|
|
61
|
+
(`domain_model`, `tech_analysis`, `test_assessment`). Build them here so Step 4
|
|
62
|
+
can serialise them.
|
|
63
|
+
|
|
64
|
+
**`domain_model`** — from the code you read, identify the bounded contexts. For
|
|
65
|
+
each: a `name`, its `aggregates` (the entities that own consistency), and its
|
|
66
|
+
`ubiquitous_language` (the domain terms the code/docs actually use). If you
|
|
67
|
+
genuinely cannot infer contexts from the code, emit an empty
|
|
68
|
+
`bounded_contexts: []` — do NOT invent contexts that aren't in the code.
|
|
69
|
+
|
|
70
|
+
**`tech_analysis`** — `stack` (languages/frameworks evidenced by manifests),
|
|
71
|
+
`dependencies` (from `package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml`
|
|
72
|
+
etc.), `architecture_notes` (observed structure, not aspirational), and `risks`
|
|
73
|
+
(each a mapping with a `description`; optionally `severity: LOW|MEDIUM|HIGH` and
|
|
74
|
+
an `evidence: detected|inferred` tag).
|
|
75
|
+
|
|
76
|
+
**`test_assessment`** — this section is under a **hard anti-hallucination
|
|
77
|
+
constraint** (next sub-step). Do NOT write it from intuition.
|
|
78
|
+
|
|
79
|
+
#### The verifiable test scan (ANTI-HALLUCINATION HARD CONSTRAINT)
|
|
80
|
+
|
|
81
|
+
Every `test_assessment` claim must be backed by a real filesystem scan you run
|
|
82
|
+
here — never by "what a project like this usually needs". Run these probes and
|
|
83
|
+
record the raw counts/paths:
|
|
84
|
+
|
|
85
|
+
1. **Count test files** by the conventional patterns:
|
|
86
|
+
- `*.test.*` / `*.spec.*` (JS/TS), `*_test.go` (Go), `test_*.py` / `*_test.py` (Python), `*_spec.rb` (Ruby), `*Test.java` (Java)
|
|
87
|
+
- e.g. `git ls-files | grep -cE '\.(test|spec)\.[jt]sx?$'` and similar per pattern
|
|
88
|
+
2. **Probe for runner configs**: `jest.config.*`, `pytest.ini` (or `[tool.pytest]` in `pyproject.toml`), `.mocharc.*`, `vitest.config.*`, `karma.conf.*`, `phpunit.xml`, `go test` (implied by `*_test.go`)
|
|
89
|
+
3. **Probe for a `coverage/` directory** (and `.coverage` / `coverage.xml` artifacts)
|
|
90
|
+
|
|
91
|
+
Then turn the raw findings into claims, each a **mapping** carrying a `claim`
|
|
92
|
+
string plus an `evidence` tag:
|
|
93
|
+
|
|
94
|
+
- `evidence: detected` — the scan directly found it (e.g. "42 `*.test.ts` files detected", "vitest.config.ts present", "coverage/ directory present").
|
|
95
|
+
- `evidence: inferred` — a judgement you derived FROM the detected facts (e.g. "unit layer present but no E2E config — integration coverage likely thin"). The inference must trace back to something the scan detected.
|
|
96
|
+
|
|
97
|
+
**"none detected" rule**: when a probe finds nothing, you MUST say so explicitly
|
|
98
|
+
with a tagged claim — `{claim: "none detected", evidence: detected}` (a scan that
|
|
99
|
+
ran and returned zero is a genuine `detected` finding). You must NOT silently
|
|
100
|
+
omit the dimension, and you must NOT invent generic filler like "needs more E2E
|
|
101
|
+
tests" / "consider adding integration tests" with no detected basis. The plan
|
|
102
|
+
validator (`lib/roll-plan-validate.py`) rejects any untagged free-text claim, so
|
|
103
|
+
filler will fail `roll init --apply`.
|
|
104
|
+
|
|
105
|
+
Map the findings into the three buckets:
|
|
106
|
+
- `current_layers`: what test layers actually exist (each tagged `detected`)
|
|
107
|
+
- `gaps`: dimensions where the scan found nothing (`none detected`, tagged `detected`) or thin coverage you can justify (`inferred`)
|
|
108
|
+
- `recommended_actions`: actions that trace to a detected gap (tag `inferred`); if nothing is missing, this bucket may be `[]`
|
|
109
|
+
|
|
58
110
|
### Step 2 — Get gap report
|
|
59
111
|
|
|
60
112
|
Run `roll-doc --dry-run` (READ-ONLY mode). This reports:
|
|
@@ -121,6 +173,39 @@ agent_routes_template: default # user's Q10 — agent routing pre
|
|
|
121
173
|
# minimal = single agent (pi), no history
|
|
122
174
|
# heavy = pi/deepseek/claude/kimi + larger window
|
|
123
175
|
# skip = don't seed .roll/agent-routes.yaml
|
|
176
|
+
|
|
177
|
+
# ── US-ONBOARD-016: Phase 2 analysis sections (optional, but emit all three) ──
|
|
178
|
+
# All three are validated only when present, so they are backward-compatible,
|
|
179
|
+
# but a normal onboard should produce them from Step 1b.
|
|
180
|
+
|
|
181
|
+
domain_model:
|
|
182
|
+
bounded_contexts: # [] if none can be inferred — never invent
|
|
183
|
+
- name: auth
|
|
184
|
+
aggregates: [User, Session]
|
|
185
|
+
ubiquitous_language: [login, token, refresh]
|
|
186
|
+
|
|
187
|
+
tech_analysis:
|
|
188
|
+
stack: [bash, python3] # evidenced by manifests
|
|
189
|
+
dependencies: [pyyaml] # from package.json / pyproject / go.mod / ...
|
|
190
|
+
architecture_notes: ["single-binary CLI + python helpers in lib/"]
|
|
191
|
+
risks:
|
|
192
|
+
- description: "no automated test run on macOS bash 3.2"
|
|
193
|
+
severity: HIGH # optional: LOW | MEDIUM | HIGH
|
|
194
|
+
evidence: detected # optional: detected | inferred
|
|
195
|
+
|
|
196
|
+
# test_assessment — ANTI-HALLUCINATION: every claim is a mapping with an
|
|
197
|
+
# `evidence` tag (detected | inferred). A zero-result scan is `none detected`
|
|
198
|
+
# tagged `detected`. Untagged free-text is REJECTED by the validator.
|
|
199
|
+
test_assessment:
|
|
200
|
+
current_layers:
|
|
201
|
+
- claim: "112 bats files detected under tests/" # evidence: a real scan count
|
|
202
|
+
evidence: detected
|
|
203
|
+
gaps:
|
|
204
|
+
- claim: "none detected" # e.g. no coverage/ dir found
|
|
205
|
+
evidence: detected
|
|
206
|
+
recommended_actions: # [] if nothing is missing
|
|
207
|
+
- claim: "add a macOS CI runner (inferred from launchd-only test skips)"
|
|
208
|
+
evidence: inferred # an inference traceable to a detected fact
|
|
124
209
|
```
|
|
125
210
|
|
|
126
211
|
Then tell the user:
|
|
@@ -180,7 +180,7 @@ Running
|
|
|
180
180
|
|
|
181
181
|
### Per Peer Pair (e.g., kimi→claude)
|
|
182
182
|
|
|
183
|
-
Stored in `~/.
|
|
183
|
+
Stored in `~/.roll/.peer-state/` (flat key files per pair):
|
|
184
184
|
|
|
185
185
|
```yaml
|
|
186
186
|
kimi→claude:
|
|
@@ -269,7 +269,7 @@ When peer review is manually triggered by a human (via `/peer`, "叫上 peer", e
|
|
|
269
269
|
- Relay the peer's response **verbatim** before adding your own analysis.
|
|
270
270
|
- After the peer's reply, the reviewer's own analysis block must explicitly state whether the peer's root cause and fix direction match the reviewer's own (independent) conclusion — that comparison is what determines the next round's action.
|
|
271
271
|
- If a peer call fails or times out, report it immediately inline and either retry or ESCALATE.
|
|
272
|
-
- Negotiation log is
|
|
272
|
+
- Negotiation log is written to `<project>/.roll/peer/logs/` as usual.
|
|
273
273
|
|
|
274
274
|
**Why inline, not tmux:** When a human manually triggers peer review inside an agent's interactive session, the conversation IS the visible interface. tmux auto-attach is only relevant for CLI-launched background sessions (`bin/roll peer`), not for skill invocations.
|
|
275
275
|
|
|
@@ -300,8 +300,9 @@ When Attacker and Defender reach a stalemate (both tests pass but interpretation
|
|
|
300
300
|
|
|
301
301
|
## Output Artifacts
|
|
302
302
|
|
|
303
|
-
- **Negotiation log**:
|
|
304
|
-
- **
|
|
303
|
+
- **Negotiation log**: `<project>/.roll/peer/logs/<timestamp>_<from>_<to>.md`
|
|
304
|
+
- **Structured record**: `<project>/.roll/peer/runs.jsonl`
|
|
305
|
+
- **State file**: `~/.roll/.peer-state/`
|
|
305
306
|
- **Decision record**: If AGREE, append summary to `docs/decisions/` or `.roll/backlog.md` (optional)
|
|
306
307
|
|
|
307
308
|
## Configuration
|
|
@@ -327,7 +328,7 @@ peer:
|
|
|
327
328
|
|
|
328
329
|
## Limitations
|
|
329
330
|
|
|
330
|
-
1. **Reverse link reliability**: Direct CLI calls are preferred. Reliability varies by tool — see Peer Invocation Reference table. If a peer fails consistently, the adaptive streak tracker marks it `abandoned` and falls back to the next candidate. File mailbox (
|
|
331
|
+
1. **Reverse link reliability**: Direct CLI calls are preferred. Reliability varies by tool — see Peer Invocation Reference table. If a peer fails consistently, the adaptive streak tracker marks it `abandoned` and falls back to the next candidate. File mailbox (`<project>/.roll/peer/mailbox/`) is the last-resort fallback.
|
|
331
332
|
- `deepseek serve --http` is the most reliable option when available — prefer it over direct `deepseek` CLI invocation.
|
|
332
333
|
- `codex exec` has known TTY/Ink issues in non-interactive environments; treat as low-priority fallback.
|
|
333
334
|
2. **Cost**: Every peer review consumes tokens on both sides. Only trigger for tasks where the cost of a wrong decision exceeds the cost of peer review. DeepSeek is the most cost-effective peer for general use.
|