@seanyao/roll 2026.529.2 → 2026.529.3

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v2026.529.3
4
+
5
+ ### Fixed
6
+
7
+ - loop 用 kimi 跑不再必崩 `[loop]`
8
+ - 切 agent 后 loop 不再用旧的 `[loop]`
9
+ - loop 不再因提交卡住整轮白做 `[loop]`
10
+
3
11
  ## v2026.529.2
4
12
 
5
13
  ### Added
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.529.2"
7
+ VERSION="2026.529.3"
8
8
  ROLL_HOME="${ROLL_HOME:-${HOME}/.roll}"
9
9
  ROLL_CONFIG="${ROLL_HOME}/config.yaml"
10
10
  ROLL_GLOBAL="${ROLL_HOME}/conventions/global"
@@ -3389,7 +3389,7 @@ _agent_argv() {
3389
3389
  fi
3390
3390
  case "$mode" in
3391
3391
  interactive) _AGENT_ARGV=("$_kimi_bin" "$prompt") ;;
3392
- *) _AGENT_ARGV=("$_kimi_bin" --quiet -p "$prompt") ;;
3392
+ *) _AGENT_ARGV=("$_kimi_bin" -p "$prompt") ;; # FIX-133: kimi-code 无 --quiet,-p 自带 auto 审批
3393
3393
  esac ;;
3394
3394
  deepseek)
3395
3395
  # deepseek has the same argv shape in both modes (positional prompt).
@@ -5954,6 +5954,10 @@ _write_runner_script() {
5954
5954
  _write_loop_runner_script() {
5955
5955
  local script_path="$1" project_path="$2" cmd="$3" log_path="$4"
5956
5956
  local active_start="${5:-10}" active_end="${6:-18}"
5957
+ # FIX-134: skill md path. When set, the inner script rebuilds the agent
5958
+ # command at runtime from the routed cycle agent; when empty it falls back to
5959
+ # the baked command (backwards compatible with callers that omit it).
5960
+ local skill_path="${7:-}"
5957
5961
  # FIX-054: terminal preference detection removed. Popup is hard-coded to
5958
5962
  # macOS Terminal.app; the 7th positional arg, if any, is ignored for
5959
5963
  # backwards compatibility with existing callers.
@@ -5985,6 +5989,15 @@ _write_loop_runner_script() {
5985
5989
  agent_cmd="${agent_cmd/--output-format stream-json/--output-format stream-json --add-dir \"\$WT\"}"
5986
5990
  fi
5987
5991
  local slug; slug=$(_project_slug "$project_path")
5992
+ # FIX-134: emit a runtime command-builder line when skill_path is known, so
5993
+ # the cycle agent is resolved live (routing-aware). Otherwise leave _CYCLE_CMD
5994
+ # empty and the inner script uses the baked fallback command below.
5995
+ local cycle_cmd_line
5996
+ if [[ -n "$skill_path" ]]; then
5997
+ cycle_cmd_line="_CYCLE_CMD=\$(_loop_cycle_agent_cmd \"${skill_path}\" \"\$CYCLE_AGENT\" \"\$WT\" 2>/dev/null || true)"
5998
+ else
5999
+ cycle_cmd_line="_CYCLE_CMD="
6000
+ fi
5988
6001
  cat > "$inner_path" << INNER
5989
6002
  #!/bin/bash -l
5990
6003
  set -o pipefail
@@ -6476,10 +6489,15 @@ for _attempt in 1 2 3; do
6476
6489
  pkill -KILL -f "\$WT" 2>/dev/null
6477
6490
  } ) &
6478
6491
  _WATCHDOG_PID=\$!
6492
+ ${cycle_cmd_line}
6493
+ # FIX-134: prefer the runtime-rebuilt command (routing-aware); fall back to
6494
+ # the baked command (project agent at \`roll loop on\` time) when empty.
6479
6495
  if [ -f "\$FMT" ]; then
6480
- ( cd "\$WT" && ${agent_cmd} ) | python3 "\$FMT"
6496
+ if [ -n "\$_CYCLE_CMD" ]; then ( cd "\$WT" && eval "\$_CYCLE_CMD" ) | python3 "\$FMT"
6497
+ else ( cd "\$WT" && ${agent_cmd} ) | python3 "\$FMT"; fi
6481
6498
  else
6482
- ( cd "\$WT" && ${agent_cmd} )
6499
+ if [ -n "\$_CYCLE_CMD" ]; then ( cd "\$WT" && eval "\$_CYCLE_CMD" )
6500
+ else ( cd "\$WT" && ${agent_cmd} ); fi
6483
6501
  fi
6484
6502
  _exit=\$?
6485
6503
  kill "\$_WATCHDOG_PID" 2>/dev/null
@@ -6939,7 +6957,7 @@ _install_launchd_plists() {
6939
6957
  local cmd; cmd=$(_agent_skill_cmd "${sd}/${skill}/SKILL.md" 2>/dev/null || echo "roll loop now")
6940
6958
 
6941
6959
  if [[ "$svc" == "loop" ]]; then
6942
- _write_loop_runner_script "$runner" "$project_path" "cd \"${project_path}\" && ${cmd}" "$log" "$active_start" "$active_end"
6960
+ _write_loop_runner_script "$runner" "$project_path" "cd \"${project_path}\" && ${cmd}" "$log" "$active_start" "$active_end" "${sd}/${skill}/SKILL.md"
6943
6961
  else
6944
6962
  _write_runner_script "$runner" "$project_path" "cd \"${project_path}\" && ${cmd}" "$log"
6945
6963
  fi
@@ -6984,7 +7002,9 @@ _install_launchd_plists() {
6984
7002
 
6985
7003
  _agent_skill_cmd() {
6986
7004
  local skill_path="$1"
6987
- local agent; agent=$(_project_agent)
7005
+ # FIX-134: accept an explicit agent (loop routing passes the resolved cycle
7006
+ # agent); default to the project agent for non-routed callers.
7007
+ local agent="${2:-$(_project_agent)}"
6988
7008
  local strip="awk 'NR==1 && /^---$/{skip=1;next} skip && /^---$/{skip=0;next} !skip{print}' '${skill_path}'"
6989
7009
  _agent_argv "$agent" plain "__PROMPT__" || {
6990
7010
  err "Unknown agent '${agent}'. Run: roll agent use <claude|kimi|deepseek|pi|openai|codex|opencode|qwen|gemini>"
@@ -7005,6 +7025,23 @@ _agent_skill_cmd() {
7005
7025
  echo "${out} \"\$(${strip})\""
7006
7026
  }
7007
7027
 
7028
+ # FIX-134: build the full per-cycle agent command at RUNTIME, routing-aware.
7029
+ # The loop inner script calls this with the resolved cycle agent (CYCLE_AGENT =
7030
+ # ROLL_LOOP_ROUTED_AGENT or project agent) so routing actually switches the
7031
+ # executed binary — instead of running a constant baked at `roll loop on` time.
7032
+ # Reproduces the claude-only verbose / stream-json / add-dir enhancements that
7033
+ # _write_loop_runner_script previously baked into the runner.
7034
+ _loop_cycle_agent_cmd() {
7035
+ local skill_path="$1" agent="${2:-$(_project_agent)}" wt="${3:-$WT}"
7036
+ [ -n "$skill_path" ] || return 1
7037
+ local cmd; cmd=$(_agent_skill_cmd "$skill_path" "$agent") || return 1
7038
+ cmd="${cmd/claude -p/claude -p --verbose --dangerously-skip-permissions --output-format stream-json}"
7039
+ if [[ "$cmd" == *"--output-format stream-json"* ]]; then
7040
+ cmd="${cmd/--output-format stream-json/--output-format stream-json --add-dir \"$wt\"}"
7041
+ fi
7042
+ printf '%s' "$cmd"
7043
+ }
7044
+
7008
7045
  cmd_loop() {
7009
7046
  local subcmd="${1:-status}"; shift || true
7010
7047
  case "$subcmd" in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seanyao/roll",
3
- "version": "2026.529.2",
3
+ "version": "2026.529.3",
4
4
  "description": "Roll — Roll out features with AI agents",
5
5
  "scripts": {
6
6
  "test": "bash tests/run.sh"
@@ -7,7 +7,7 @@ description: "Legacy project documentation automation. Scans all docs, builds/up
7
7
 
8
8
  # roll-doc
9
9
 
10
- Four-phase legacy documentation automation: scan → index → gap analysis → fill.
10
+ Four-phase legacy documentation automation (plus deep-read Phase 3b): scan → index → gap analysis → fill (directory-level) → deep read (cross-directory topics).
11
11
 
12
12
  Works on any project root. No manual mode switching — reads the project state and decides what to do.
13
13
 
@@ -162,6 +162,70 @@ Only include lines for directories that already exist in the project.
162
162
 
163
163
  Do not fabricate details — infer only from source files actually read.
164
164
 
165
+ ## Phase 3b — Deep Read
166
+
167
+ Deep-read phase that builds a full project symbol table (without truncation) and auto-detects
168
+ cross-directory topics that directory-level Phase 3 alone cannot discover.
169
+
170
+ **Trigger conditions** — Phase 3b runs when either is true:
171
+ - Phase 2 found any gap (module or special gap)
172
+ - The project exhibits code characteristics that Phase 3a cannot capture:
173
+ cross-directory import chains spanning ≥ 3 directories, state enums referenced by
174
+ multiple files, external URL/endpoint calls, or CI pipeline configuration files
175
+
176
+ Pure documentation-only projects (no source code gaps, no code characteristics) skip Phase 3b.
177
+
178
+ ### Step 1 — Build Symbol Table
179
+
180
+ Read every source file **in full** (no truncation). The existing Phase 3 "up to 20 source files"
181
+ limit does not apply — Phase 3b builds a complete project symbol table for downstream topic
182
+ detection to reason across files without missing logic.
183
+
184
+ **Exclusion directories** (same as Phase 1):
185
+
186
+ ```
187
+ node_modules/ .git/ dist/ build/ .shared/ .roll/dream/ .roll/briefs/
188
+ ```
189
+
190
+ **Symbol table fields:**
191
+
192
+ | Field | Content |
193
+ |-------|---------|
194
+ | `exports` | class / interface / type / function / const declarations, per file |
195
+ | `imports` | source file → target file mapping (dependency graph edges) |
196
+ | `enums` | enum declarations with enumerated values, per file |
197
+ | `external_urls` | `fetch(...)` / `axios` / `http.*` calls, `API_ENDPOINT` / `*_URL` / `*_HOST` constants, hardcoded `https?://` strings (exclude comments and test fixtures) |
198
+ | `configs` | CI workflow YAML files, build config paths, test framework config file paths |
199
+
200
+ **`--dry-run` behavior:** print symbol table summary counts per category (e.g. "exports: 42, imports: 156, enums: 7, external_urls: 4, configs: 3") plus top-N examples per category. Write nothing to disk.
201
+
202
+ **`--force` behavior:** unchanged — `--force` only affects draft generation (Phase 3/3b output files).
203
+ The symbol table itself is rebuilt from scratch on every run regardless of flags.
204
+
205
+ ### Step 2 — Topic Detection
206
+
207
+ Using the symbol table from Step 1, detect cross-directory topics. Each topic type has a
208
+ detection rule and a target output file. Skip any topic whose target file already exists
209
+ (unless `--force`). Skip any topic whose detection rule finds no matches.
210
+
211
+ | Topic | Detection Rule | Output |
212
+ |-------|---------------|--------|
213
+ | 数据流 / 调用链 | Entry files (`bin/`, `cmd/`, `main.*`, `index.*`) → trace import chain to leaf nodes; require ≥ 1 chain spanning ≥ 3 directories | `docs/data-flows.md` |
214
+ | 状态机 | Enums matching `*State` / `*Status` referenced by ≥ 2 source files | `docs/state-machines.md` |
215
+ | 外部集成 | `external_urls` entries from symbol table (exclude comment/test-fixture matches) | `docs/integrations.md` |
216
+ | 部署管线 | `.github/workflows/*.yml` / `.gitlab-ci.yml` / `circle.yml` / `Jenkinsfile` present, with deploy URL patterns detected | `docs/deployment.md` |
217
+ | Agent 入口 (AGENTS.md) | Project root has no `AGENTS.md` AND `src/` (or equivalent source root) has ≥ 3 subdirectories | `AGENTS.md` |
218
+ | 高引用目录 | Directory imported by ≥ 5 other source files, even if directory itself has < 3 source files | `<dir>/README.md` |
219
+
220
+ ### Step 3 — Source Annotations
221
+
222
+ Every topic document generated in Step 2 must cite `file:line` for each claim (function call,
223
+ endpoint URL, state transition, CI job, import path). Annotations must come from actual
224
+ symbol table records — do not fabricate line numbers. Follows the same "Do not fabricate"
225
+ rule as Phase 3.
226
+
227
+ ---
228
+
165
229
  ## Phase 4 — Report
166
230
 
167
231
  After all phases complete, output a summary:
@@ -181,6 +245,12 @@ Phase 3 — Fill
181
245
  N drafts generated: [list of paths]
182
246
  N skipped (already exist; use --force to regenerate)
183
247
 
248
+ Phase 3b — Deep Read
249
+ Symbol table: exports(N) imports(N) enums(N) external_urls(N) configs(N)
250
+ N topic documents generated: [list of paths and types]
251
+ N topics skipped (no matches or already exist; use --force to regenerate)
252
+ (if no topics generated: "no subject-level drafts generated")
253
+
184
254
  📋 Review priority (largest / most active modules first):
185
255
  1. src/commands/README.md — 8 source files
186
256
  2. docs/CONVENTIONS.md — 6 patterns detected