@seanyao/roll 4.710.3 → 4.713.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 +19 -0
- package/dist/postinstall.mjs +2 -0
- package/dist/roll.mjs +4417 -5149
- package/docs/architecture.md +57 -7
- package/guide/en/loop.md +17 -0
- package/guide/zh/loop.md +13 -0
- package/package.json +1 -1
- package/skills/roll-build/SKILL.md +3 -0
- package/skills/roll-build/references/full-contract.md +48 -15
- package/skills/roll-loop/SKILL.md +8 -0
- package/skills/roll-loop/references/full-contract.md +10 -6
package/docs/architecture.md
CHANGED
|
@@ -77,10 +77,10 @@ web 站点与静态展示(当前不是活体 Supervisor 控制台)
|
|
|
77
77
|
|
|
78
78
|
这是系统的引擎。一个 Loop 是一个自治进程,按定时器唤醒,执行一个 Cycle。
|
|
79
79
|
|
|
80
|
-
**Cycle
|
|
80
|
+
**Cycle 生命周期**:选故事(先查租约 `deliveryLease`)→ 路由 agent → 创建隔离工作区 → agent 执行(TCR 循环)→ attest 硬闸 → 送交 PR → AWAITING_MERGE 挂起并释放 loop → pick 下一张卡。交付推进由 Delivery Reconciler 在任意 `roll` 调用时机会性对账完成——不依赖独立 daemon。
|
|
81
81
|
|
|
82
82
|
**关键约束**:
|
|
83
|
-
- 一 Cycle 只做一个 Story
|
|
83
|
+
- 一 Cycle 只做一个 Story。AWAITING_MERGE 后释放 loop,拿下一个;交付由 Delivery Reconciler 对账推进,不 block loop。
|
|
84
84
|
- 进程可能被 SIGKILL。下次唤醒时,通过锁龄、心跳、PID 判断孤儿态,安全接管或重做。
|
|
85
85
|
- 心跳每 60 秒写入一次。超时无心跳 → 判定死亡并落终态。
|
|
86
86
|
- 退出时无条件写入终态。这是硬约束——trap 兜底。
|
|
@@ -89,8 +89,7 @@ web 站点与静态展示(当前不是活体 Supervisor 控制台)
|
|
|
89
89
|
**Loop 类型**:
|
|
90
90
|
| 类型 | 职责 |
|
|
91
91
|
|------|------|
|
|
92
|
-
| main | 消费待办,执行完整的 pick→TCR→PR→对账
|
|
93
|
-
| pr | 监控 open loop PR:CI 挂了自愈,绿了合并 |
|
|
92
|
+
| main | 消费待办,执行完整的 pick→TCR→PR→AWAITING_MERGE→对账 周期(含 Delivery Reconciler 机会性对账) |
|
|
94
93
|
| ci | 监控 CI 状态 |
|
|
95
94
|
| alert | 消费 ALERT 文件,推送到用户 |
|
|
96
95
|
|
|
@@ -139,13 +138,62 @@ cycle 写 `loop:pending`,只做恢复探测,不启动 Builder、不把卡记
|
|
|
139
138
|
**反规则**:不因历史表现自动改写角色绑定。不做失败后的静默跨 agent 重试。指标可以*建议*
|
|
140
139
|
策略变更,但绝不绕过 human-on-the-loop。
|
|
141
140
|
|
|
142
|
-
### BC4 ·
|
|
141
|
+
### BC4 · 交付(Delivery Reconciler)
|
|
143
142
|
|
|
144
143
|
每次交付是一个 Pull Request。一个 Story 至多同时有一个 open PR。
|
|
145
144
|
|
|
146
|
-
|
|
145
|
+
**最后一公里 = 一个 reconcile 闭环,无独立守护进程。**
|
|
147
146
|
|
|
148
|
-
|
|
147
|
+
#### 交付生命周期
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
building ──attest earned──► publishable ──push+PR──► awaiting_merge ──┐
|
|
151
|
+
│ │
|
|
152
|
+
└─attest MISSING──► blocked_no_evidence (fail-loud,不推分支) │
|
|
153
|
+
▼
|
|
154
|
+
awaiting_merge ──L1/L2 强信号命中──► delivered / delivered_external
|
|
155
|
+
awaiting_merge ──CI 绿未合──► 自驱合并 (gh pr merge --squash) ──► 下轮判 delivered
|
|
156
|
+
awaiting_merge ──CI 红──► ci_failed ──► fix-forward cycle
|
|
157
|
+
awaiting_merge ──同卡他 cycle 已 delivered──► superseded(带原因)
|
|
158
|
+
awaiting_merge ──证据不足──► 留 awaiting_merge(绝不误判)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**交付状态**:
|
|
162
|
+
|
|
163
|
+
| 状态 | 含义 |
|
|
164
|
+
|------|------|
|
|
165
|
+
| `building` | TCR 进行中 |
|
|
166
|
+
| `blocked_no_evidence` | 过了测试但缺 attest/ac-map → fail-loud,未推分支 |
|
|
167
|
+
| `awaiting_merge` | 分支+PR 已开;挂起,loop 释放并继续下一张卡 |
|
|
168
|
+
| `ci_failed` | PR CI 红 → 需 fix-forward |
|
|
169
|
+
| `delivered` | 合进 main:runner 自驱合并 |
|
|
170
|
+
| `delivered_external` | 合进 main:外部(supervisor / 人手动合 / 其他 cycle)——patch-id / PR-state 反查确认,一等公民 |
|
|
171
|
+
| `superseded` | 同卡另一 cycle 已 delivered |
|
|
172
|
+
| `abandoned` | lease 释放 / 卡撤销 |
|
|
173
|
+
|
|
174
|
+
#### 分层真相判定(强→弱,任一强信号即 delivered)
|
|
175
|
+
|
|
176
|
+
| 层 | 信号 | 可靠性 | 何时可用 |
|
|
177
|
+
|---|---|---|---|
|
|
178
|
+
| L1 | **PR 状态**:`gh pr view` → `MERGED` | 最强(权威) | gh 可用且 PR 可解析时 |
|
|
179
|
+
| L2 | **patch-id 等价**:`git patch-id(diff origin/main...branch)` ∈ main 候选 merge commit 的 patch-id 集 | 强(squash/rebase 安全) | 离线也行;不依赖 gh |
|
|
180
|
+
| L3 | **backlog Done + attest 报告存在** | 弱(仅佐证,单独不足) | 兜底交叉验证 |
|
|
181
|
+
|
|
182
|
+
**判定规则**:`delivered` 需 ≥1 个强信号(L1 或 L2)。L3 单独不足以判 delivered(agent 可能预写 Done)。L1 与 L2 冲突时以 L1 为准并告警。全不命中 → 留 `awaiting_merge`,**绝不误判**。
|
|
183
|
+
|
|
184
|
+
#### Delivery Reconciler
|
|
185
|
+
|
|
186
|
+
纯判定 + 薄 IO,在任意 `roll` 调用 / cycle 边界 / `roll loop reconcile` 时机会性运行:
|
|
187
|
+
|
|
188
|
+
- **触发点**:(a) 每次 `roll loop` cycle 边界;(b) 任意 `roll` 命令的前置机会性 reconcile;(c) 显式 `roll loop reconcile [--json]`;(d) CI 里可选一步
|
|
189
|
+
- **自驱合并**:CI 绿且未合 → `gh pr merge --squash`,不依赖仓库 auto-merge 开关、不依赖 launchd
|
|
190
|
+
- **外部合并反查**:supervisor / 人手动合并被 patch-id / PR-state 自动回填为 `delivered_external`——手动合并是一等支持路径,不是泄漏
|
|
191
|
+
- **幂等 & 崩溃可续**:reconcile 反复跑永远安全,向真相收敛
|
|
192
|
+
- **退役守护进程**:原 `com.roll.pr.<slug>` launchd PR-loop 守护已退役,合并逻辑整体搬进 Delivery Reconciler,不再需要常驻进程
|
|
193
|
+
|
|
194
|
+
#### 交付判定
|
|
195
|
+
|
|
196
|
+
合并入 main 才算交付。PR 已开、CI 已绿、agent 声称完成都不算——事后对账,只认 main 上真实的 merge commit。main 是唯一交付真相;reconcile 只把真相投影回 cycle 行。
|
|
149
197
|
|
|
150
198
|
### BC5 · 演化
|
|
151
199
|
|
|
@@ -281,6 +329,8 @@ v4 把"一张 Story 怎么交付"和"项目级怎么协调"分成两层。
|
|
|
281
329
|
|
|
282
330
|
剖面在 Cycle 开始时选一次并记入 `execution:profile` 事件。角色之间只通过 artifact(`role-artifacts/designer/design-contract.md` / `execute-evidence` / `eval-report.md` + `artifact-manifest.json`)交接,不共享原始会话;每个角色都是 fresh session。`evaluate` 不是单一 `pass/fail`——blocking review、score、attest 是三个分开的契约。evaluate→execute 的修复回合受硬熔断约束(最大轮数、重复 finding 签名、预算、超时),触界即升级。
|
|
283
331
|
|
|
332
|
+
**攻防结对(Adversarial pairing,`verified` / `designed` 剖面内的 Builder 步)**:在这两个剖面里,Builder 步不再是单个 agent 同时写测试和实现,而是由**循环引擎真正编排**(US-LOOP-100..106,全在 `@roll/core` + CLI runner):先 spawn 一个 test_author 写红测试 → 再 spawn 一个**异构**的 implementer 只写实现变绿(不得改测试)→ 绿后进入攻防回合(attacker 补破坏性测试 → implementer 修),直到攻不动。终止由纯函数 `adversarialNextStep` 三重独立判定(按优先级 总超时 → 回合上限 → 连续无洞,任一命中即停)保证**无人值守绝不挂死**;任何攻防异常(无异构伙伴 / agent 不可用 / 单回合挂死)经 `adversarialDegradeDecision` **降级回标准单 builder** 完成本卡并记 `adversarial:degraded` 事件——不静默、不死锁。默认参数:`max_rounds=4`、`dry_rounds_to_stop=2`、`total_timeout_sec=2700`。每卡结果(回合数 / 抓洞数 / 终止原因 / 是否降级)折进 runs 行,`roll loop adversarial` 输出攻防 vs 标准 cohort 的只读影子跑聚合,供 owner 用数据决定是否扩大剖面覆盖(设计 §9)。攻防路径**默认休眠**,仅当项目把 `execution_policy.mode` opt-in 到 verified/designed 才启用;`standard` 剖面零变化。
|
|
333
|
+
|
|
284
334
|
**Supervisor**:项目级协调者,负责不属于某一张具体 Story 的工作——跨 Story/Epic 上下文、backlog 排序、风险分级、执行剖面建议、路由/Rig 建议、预算、并行、卡住的 cycle、重复失败、文件冲突、合并队列、发布就绪、truth coverage / 显式 release blockers、系统级用户交互("接下来做什么?""为什么卡住?")与 owner 升级。
|
|
285
335
|
|
|
286
336
|
Supervisor **绝不**:实现具体 Story、写 Story 的评估报告、覆盖 Evaluator 裁定、绕过 attest 闸、直接标记 Story 为 Done、用指标静默改写路由/策略。v4.0 的 Supervisor 是 observe/advise(`roll supervisor`):先用确定性 selector 把事实结构化,再(必要时)让 agent 措辞建议;历史 Done 缺少结构化 DeliveryRecord 只作为 truth coverage/backfill 提醒,发布是否阻塞以显式 release blockers / release consistency 为准;持久化策略变更一律需 owner 确认。安全并行调度(`max_parallel_cycles`、文件冲突串行化、合并队列/预算暂停)的决策逻辑已就位,活体并行交付留待 v4.1。
|
package/guide/en/loop.md
CHANGED
|
@@ -271,6 +271,23 @@ three ranking suggestions and reasons. The ranking is advisory only; Hold, Cut,
|
|
|
271
271
|
unsatisfied dependencies, skip-list, open PR, merged-delivery, and pending-publish
|
|
272
272
|
gates still decide eligibility.
|
|
273
273
|
|
|
274
|
+
### One Card, One Lease
|
|
275
|
+
|
|
276
|
+
By default a card has exactly one delivery lease. Before picking, the picker
|
|
277
|
+
consults the delivery leases derived from the event stream: a card already
|
|
278
|
+
`in_flight`, `awaiting_merge`, `ci_red`, or `delivered` is skipped with a
|
|
279
|
+
`card held: <state> (<cycle>)` reason (event `pick:skipped`, idle reason
|
|
280
|
+
`all_leased`). Same-card parallel builds are off — quality redundancy comes
|
|
281
|
+
from the adversarial pair inside one cycle, not from duplicate builds that only
|
|
282
|
+
one merge can land. A cycle that ended without delivering releases its lease,
|
|
283
|
+
so a legal fix-forward retry of the same card stays pickable.
|
|
284
|
+
|
|
285
|
+
`roll loop run-once --race` is the explicit opt-in for same-card parallel
|
|
286
|
+
racing (carried to child cycles as `ROLL_LOOP_RACE=1`). On the FIRST merge,
|
|
287
|
+
`roll loop reconcile` atomically supersedes the remaining sibling cycles
|
|
288
|
+
(`delivery:reconciled{superseded}`), so racing costs at most one merge plus
|
|
289
|
+
discarded sibling work — never duplicate deliveries.
|
|
290
|
+
|
|
274
291
|
### Goal Mode vs Scheduled Mode
|
|
275
292
|
|
|
276
293
|
`roll loop go` is a manual goal session, not a launchd scheduler tick. While it
|
package/guide/zh/loop.md
CHANGED
|
@@ -240,6 +240,19 @@ roll agent list # 查看本机已装的 agent
|
|
|
240
240
|
Hold、Cut、未满足依赖、skip-list、open PR、已合并交付和 pending-publish gate 仍决定
|
|
241
241
|
卡片是否可选。
|
|
242
242
|
|
|
243
|
+
### 一卡一租约
|
|
244
|
+
|
|
245
|
+
默认一张卡只有一条交付租约。选卡前 picker 会先咨询由事件流投影出的交付租约:
|
|
246
|
+
卡已处 `in_flight`、`awaiting_merge`、`ci_red` 或 `delivered` 一律 skip,理由形如
|
|
247
|
+
`card held: <state> (<cycle>)`(事件 `pick:skipped`,idle 理由 `all_leased`)。
|
|
248
|
+
同卡并行建造默认关闭——质量冗余由单 cycle 内的攻防结对提供,不靠"只有一份能合入"
|
|
249
|
+
的重复建造。已结束但未交付的 cycle 会释放租约,所以同卡的合法 fix-forward 重试仍可被选。
|
|
250
|
+
|
|
251
|
+
`roll loop run-once --race` 是同卡并行竞速的显式开关(经 `ROLL_LOOP_RACE=1` 传给
|
|
252
|
+
子 cycle)。首个 merge 发生时,`roll loop reconcile` 原子取消其余 sibling cycle
|
|
253
|
+
(`delivery:reconciled{superseded}`),竞速的代价至多是一份合入加 sibling 废活,
|
|
254
|
+
绝不产生重复交付。
|
|
255
|
+
|
|
243
256
|
### Goal Mode 与定时模式
|
|
244
257
|
|
|
245
258
|
`roll loop go` 是手动 goal session,不是 launchd 定时 tick。运行期间 Roll 会持有
|
package/package.json
CHANGED
|
@@ -43,6 +43,7 @@ same TCR, evidence, Evaluator, and release gates apply in both modes.
|
|
|
43
43
|
- In the test-gated loop the tests are the weakest link: an isolated Test Adequacy reviewer (Phase 6 Agent 4) audits the tests against the AC, seeing only AC + test files — never the implementation diff or builder reasoning. Self-review of one's own tests (Phase 2) is necessary but not isolation.
|
|
44
44
|
- Self-review, attest, and E2E evidence remain required. The Review Score is produced by the runner's fresh-session peer Reviewer — the agent does NOT self-score.
|
|
45
45
|
- Docs/code/product alignment is a DoD gate: user-visible behavior, command, output-copy, site, or delivery-view changes update the touched README/docs/guide/site/help in the same delivery.
|
|
46
|
+
- Done ≡ merged to `main`. After publish the cycle is `awaiting_merge`; the Delivery Reconciler (no daemon) self-drives the merge and reconciles truth from `main` — manual merges are first-class (`delivered_external`). Never pre-flip a card to Done on an open PR.
|
|
46
47
|
|
|
47
48
|
## Gotchas
|
|
48
49
|
|
|
@@ -58,3 +59,5 @@ same TCR, evidence, Evaluator, and release gates apply in both modes.
|
|
|
58
59
|
## Role in v4 execution profiles
|
|
59
60
|
|
|
60
61
|
**roll-build is the Builder capability in every execution profile** (`standard` / `verified` / `designed`). Under `designed` it receives the Designer's `design-contract.md` via artifact refs (no shared raw session). Under `verified`/`designed` an independent **Evaluator** (a fresh session) judges the delivery and may open a BOUNDED repair round — you address the blocking findings and write a repair note mapping findings → changes. `standard` is Builder-only. Roles: Supervisor / Designer / Builder / Evaluator.
|
|
62
|
+
|
|
63
|
+
Under `verified`/`designed` the Builder step itself is the **engine-orchestrated adversarial pair** (US-LOOP-100..106, dormant until `execution_policy.mode` opts in): the loop spawns a heterogeneous test_author ≠ implementer and drives attack rounds, with deterministic never-hang termination, fail-closed degrade to a single builder (`adversarial:degraded`), and a `roll loop adversarial` shadow-run aggregate. See references/full-contract.md § US-SKILL-031.
|
|
@@ -750,17 +750,21 @@ story (loop or manual Phase 10.6) and earn the report at delivery time.
|
|
|
750
750
|
|
|
751
751
|
**Done ≡ merged (FIX-322/323).** A card is `✅ Done` only once its delivery is
|
|
752
752
|
**merged to `main`** — not when the branch is pushed and not while the PR is
|
|
753
|
-
merely open. `
|
|
754
|
-
|
|
753
|
+
merely open. `awaiting_merge` (pushed / PR open, awaiting merge) is **not**
|
|
754
|
+
delivered. Consequences you can rely on:
|
|
755
755
|
|
|
756
|
-
- The picker **skips** any card that already has a merged delivery
|
|
757
|
-
reset to 📋 Todo after merge is not re-picked
|
|
758
|
-
-
|
|
759
|
-
|
|
756
|
+
- The picker **skips** any card that already has a merged delivery (one card,
|
|
757
|
+
one `deliveryLease`), so a card reset to 📋 Todo after merge is not re-picked
|
|
758
|
+
and re-built.
|
|
759
|
+
- Truth reconciles from `main`: the **Delivery Reconciler** (US-DELIV-001..007,
|
|
760
|
+
no daemon — the `com.roll.pr.<slug>` PR Loop is retired) confirms merges via
|
|
761
|
+
PR-state (L1) / patch-id (L2) and flips the cycle to `delivered` — manual /
|
|
762
|
+
external merges included (`delivered_external` is first-class).
|
|
760
763
|
|
|
761
764
|
So on the manual path, flip the row to Done **after** the PR merges; under
|
|
762
|
-
`roll-loop` the
|
|
763
|
-
merge
|
|
765
|
+
`roll-loop` the cycle ends at publish (`awaiting_merge`) and the reconciler
|
|
766
|
+
self-drives the merge (`gh pr merge --squash` on green CI) and flips the row
|
|
767
|
+
once the merge lands on `main` — do not pre-flip on a still-open PR.
|
|
764
768
|
|
|
765
769
|
Both locations must be updated — neither can be skipped:
|
|
766
770
|
|
|
@@ -863,10 +867,11 @@ Before creating any file or directory:
|
|
|
863
867
|
Work is not complete until it reaches:
|
|
864
868
|
commit → push → CI signal → **PR merged to main** → deploy → online
|
|
865
869
|
verification → backlog update.
|
|
866
|
-
A pushed branch or an open PR is `
|
|
867
|
-
the row flips to `✅ Done` only after the merge. Truth reconciles from
|
|
868
|
-
|
|
869
|
-
|
|
870
|
+
A pushed branch or an open PR is `awaiting_merge`, NOT delivered;
|
|
871
|
+
the row flips to `✅ Done` only after the merge. Truth reconciles from
|
|
872
|
+
`main`: the Delivery Reconciler confirms merges via PR-state / patch-id
|
|
873
|
+
(manual merges included → `delivered_external`) and the picker skips
|
|
874
|
+
already-merged cards.
|
|
870
875
|
|
|
871
876
|
2. **TCR for every micro-step**
|
|
872
877
|
- Each behavior change: Test → Green=Commit / Red=Revert
|
|
@@ -987,7 +992,9 @@ distilled from the US-EVID-026 delivery retro.
|
|
|
987
992
|
Under the `verified` and `designed` execution profiles, the **test author and the
|
|
988
993
|
implementer are DIFFERENT, heterogeneous agents** — the agent that makes a test
|
|
989
994
|
pass is never the one that wrote it, so tests and implementation cannot be
|
|
990
|
-
co-shaped to be mutually flattering.
|
|
995
|
+
co-shaped to be mutually flattering. **This is now orchestrated by the loop engine
|
|
996
|
+
itself** (US-LOOP-100..106), not left to builder self-discipline — the runner
|
|
997
|
+
spawns the roles and drives the rounds:
|
|
991
998
|
|
|
992
999
|
1. Test author writes a RED test for the next micro-step.
|
|
993
1000
|
2. Implementer (a different agent) writes ONLY production code to turn it green;
|
|
@@ -995,14 +1002,40 @@ co-shaped to be mutually flattering. The loop is:
|
|
|
995
1002
|
3. **Attack round** — once green, the test author writes ≥1 *breaking* test
|
|
996
1003
|
targeting an untested failure mode; the implementer fixes; repeat until the
|
|
997
1004
|
attacker is dry (N consecutive rounds surface no new hole).
|
|
998
|
-
4. The attacker's breaking tests are
|
|
999
|
-
|
|
1005
|
+
4. The attacker's breaking tests are committed to the branch as real test files,
|
|
1006
|
+
so Phase 6 **Agent 4** audits them as part of the suite — "these failure modes
|
|
1007
|
+
are now pinned" is auditable via the tests themselves. (The engine tracks the
|
|
1008
|
+
attack-test paths in-cycle for the round bookkeeping; it does not forward them
|
|
1009
|
+
as a separate persisted data channel.)
|
|
1010
|
+
|
|
1011
|
+
How the engine runs it (all in `@roll/core` + the CLI runner, not a prose
|
|
1012
|
+
convention):
|
|
1013
|
+
|
|
1014
|
+
- **Sequencing** — the orchestrator's execute phase emits a `spawn_role`
|
|
1015
|
+
subsequence (`test_author → implementer → attack rounds`) instead of a single
|
|
1016
|
+
`spawn_agent`, driven by the pure `adversarialNextStep` termination algorithm
|
|
1017
|
+
(three independent stops, checked in precedence order total-timeout → max-rounds
|
|
1018
|
+
→ dry-streak; any one halts the loop, so it can **never hang unattended**).
|
|
1019
|
+
`standard` cycles still emit the single builder,
|
|
1020
|
+
byte-unchanged.
|
|
1021
|
+
- **Fail-closed degrade** — any adversarial exception (no heterogeneous partner,
|
|
1022
|
+
an unavailable agent, a hung round) routes through `adversarialDegradeDecision`
|
|
1023
|
+
and falls back to a standard single builder that completes the card, emitting an
|
|
1024
|
+
`adversarial:degraded` event — **never silent, never deadlock**. The role spawns
|
|
1025
|
+
carry the same main-checkout write-protection as the builder.
|
|
1026
|
+
- **Observability** — each cycle's outcome (`rounds / holesFound /
|
|
1027
|
+
terminationReason / degraded`) is folded onto the runs row, and
|
|
1028
|
+
`roll loop adversarial` prints the read-only shadow-run aggregate (adversarial
|
|
1029
|
+
vs standard cohort, avg holes, degrade rate) so profile expansion is a
|
|
1030
|
+
data-backed decision (design §9), not a guess.
|
|
1000
1031
|
|
|
1001
1032
|
Cost: this approximately 2–3× the agent calls, so it is **bound to `verified` /
|
|
1002
1033
|
`designed`** (high-stakes cards). `standard` keeps the single-builder + downstream
|
|
1003
1034
|
audit unchanged. The profile choice is recorded (which was picked, and why).
|
|
1004
1035
|
Independence is by session/context, not vendor (same FIX-343 red line): the
|
|
1005
1036
|
test-author session must not be the implementer's session or a sub-agent of it.
|
|
1037
|
+
The adversarial path is **dormant until a project opts into the verified/designed
|
|
1038
|
+
execution profile** (`execution_policy.mode`); a standard-mode project is unaffected.
|
|
1006
1039
|
|
|
1007
1040
|
### US-SKILL-032 — Independent heterogeneous code review
|
|
1008
1041
|
|
|
@@ -38,6 +38,14 @@ bypasses pause, budget, route, evidence, Evaluator, or release gates.
|
|
|
38
38
|
4. Persist events, runs, alerts, and status.
|
|
39
39
|
5. Pause on repeated failure.
|
|
40
40
|
|
|
41
|
+
## Delivery Lifecycle (US-DELIV-001..007)
|
|
42
|
+
|
|
43
|
+
最后一公里 = 一个 reconcile 闭环,无独立守护进程(`com.roll.pr.<slug>` PR Loop 已退役)。
|
|
44
|
+
|
|
45
|
+
- A cycle ends at publish: branch pushed + PR opened → `awaiting_merge`; the loop is released to pick the next card. Nothing blocks on merge.
|
|
46
|
+
- The **Delivery Reconciler** advances delivery opportunistically — cycle boundaries, read paths, and explicit `roll loop reconcile`: CI-green PRs are merged self-drive (`gh pr merge --squash`); merged PRs reconcile from `main` (L1 PR-state / L2 patch-id) to `delivered`; external / manual merges reconcile to `delivered_external` (first-class); insufficient evidence stays `awaiting_merge` — never misjudge.
|
|
47
|
+
- Reconcile is idempotent and crash-safe: any single `roll` invocation can advance the truth.
|
|
48
|
+
|
|
41
49
|
## Hard Gates
|
|
42
50
|
|
|
43
51
|
- Loop never cuts a release autonomously.
|
|
@@ -301,14 +301,18 @@ After each item completes:
|
|
|
301
301
|
|
|
302
302
|
**Path B — heal exhausted (≥`ROLL_LOOP_HEAL_MAX`, default 2) or disabled (`ROLL_LOOP_NO_HEAL=1`) (exit 1):**
|
|
303
303
|
|
|
304
|
-
1. Do NOT force ✅ Done here. CI red means the PR will not merge.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
1. Do NOT force ✅ Done here. CI red means the PR will not merge. The main
|
|
305
|
+
loop never waits for merge — it publishes the PR, records
|
|
306
|
+
`awaiting_merge`, and exits; the **Delivery Reconciler**
|
|
307
|
+
(US-DELIV-001..007, no daemon — the `com.roll.pr.<slug>` PR Loop is
|
|
308
|
+
retired) advances it opportunistically on cycle boundaries and on
|
|
309
|
+
`roll loop reconcile`: self-drive merge (`gh pr merge --squash`) once CI
|
|
310
|
+
turns green, then reconcile to `delivered` / `delivered_external` from
|
|
311
|
+
`main` (L1 PR-state / L2 patch-id). There is no false-Done risk:
|
|
308
312
|
with worktree isolation the ✅ Done lives only in the unmerged PR, never on
|
|
309
313
|
the loop's main checkout, and the story is not re-picked meanwhile via the
|
|
310
|
-
open-PR eligibility gate (FIX-146)
|
|
311
|
-
✅ Done lands on main only when the
|
|
314
|
+
open-PR eligibility gate (FIX-146) / `deliveryLease`. The story's
|
|
315
|
+
✅ Done lands on main only when the reconciler confirms the merge.
|
|
312
316
|
2. Write ALERT to `~/.shared/roll/loop/ALERT-<slug>.md` with:
|
|
313
317
|
- story ID, time, commit SHA
|
|
314
318
|
- heal attempts made (read `heal_count:` from `state-<slug>.yaml`)
|