plan-governance-cli 2.0.1 → 2.0.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/README.md +4 -4
- package/package.json +1 -1
- package/resources/skill/SKILL.md +1 -1
- package/resources/skill/assets/plan.template.md +4 -2
- package/resources/skill/references/cli.md +1 -1
- package/resources/skill/references/planning.md +3 -1
- package/resources/skill/references/verification.md +12 -12
- package/scripts/check_plan_governance.py +39 -26
- package/scripts/init_plan_governance.py +1 -1
package/README.md
CHANGED
|
@@ -209,9 +209,9 @@ plan-governance-cli graph code impact --repo modelpad --file Sources/ModelPadCor
|
|
|
209
209
|
|
|
210
210
|
## 持续推进
|
|
211
211
|
|
|
212
|
-
在已授权的跨轮任务中可使用 `goal`;skill
|
|
212
|
+
在已授权的跨轮任务中可使用 `goal`;skill 本身不定义整计划自主执行运行时。所有风险级别默认自验,只有用户明确要求时才独立复核;旧策略名和旧记录格式采用相同行为并保留历史,无需逐计划迁移。
|
|
213
213
|
|
|
214
|
-
[验证规范](resources/skill/references/verification.md)
|
|
214
|
+
[验证规范](resources/skill/references/verification.md)统一维护按需复核、任务复用、证据复用、修复自验与用户验收;其他会话从同一 skill 读取。用户明确要求独立复核时安排只读 subagent,复用已有同范围任务/结果,等待异常先核准任务 ID 和状态,且复核者不得再委派复核。技术完成待用户验收的适用功能计划仍保持实施中。
|
|
215
215
|
|
|
216
216
|
恢复已有计划时可读取派生工作集:
|
|
217
217
|
|
|
@@ -385,9 +385,9 @@ python3 -m pytest
|
|
|
385
385
|
|
|
386
386
|
状态与当前阶段由 `docs/PLAN_MAP.md` 维护。每阶段必须具备自身 Step 0、验证/完成和失败边界、无有效阻塞及适用复核,不能凭上一阶段完成自动待实施。
|
|
387
387
|
|
|
388
|
-
|
|
388
|
+
新旧计划统一默认自验:高风险或高影响变更仍按实际后果验证,只有用户明确要求才独立复核,原发现保留。旧 `风险分流`、`单次独立复核` 标签和缺省六列格式只作为兼容记录形式;固定字段、历史保护和严格检查语义以[阶段门规范](resources/skill/references/verification.md#step-0-与阶段门)为准。
|
|
389
389
|
|
|
390
|
-
|
|
390
|
+
收到用户明确请求并派发独立复核时显式传入推理强度:安全、权限、隐私、资金、数据完整性等高风险复核使用 `high`,其他独立复核使用 `medium`。推理强度不决定是否复核。
|
|
391
391
|
|
|
392
392
|
使用 `check --strict-readiness` 做准入/CI/发布机械检查;默认检查兼容告警,机械通过不代替真实风险判断、业务验收或用户接受。
|
|
393
393
|
|
package/package.json
CHANGED
package/resources/skill/SKILL.md
CHANGED
|
@@ -13,7 +13,7 @@ description: 维护已有项目计划,或为需要跨阶段、跨会话协调
|
|
|
13
13
|
|
|
14
14
|
首次接手读取地图、当前相关计划及必要契约;恢复只核对当前阶段、实际差异和最近证据。只实施已授权且准入的范围;实质边界变化时调整受影响计划,日常进展随工作同步。事实源与格式见 planning。
|
|
15
15
|
|
|
16
|
-
按 verification
|
|
16
|
+
按 verification 验证:所有风险级别默认由实施者自验,仅在用户明确要求时安排独立复核;派发时显式传入推理强度,高风险用 `high`,其余用 `medium`。旧策略名和旧记录格式不改变此行为。适用检查通过后完成交付;未解决问题如实保留。交付说明完成结果、必要证据和剩余事项,明确约定的用户体验验收继续有效。
|
|
17
17
|
|
|
18
18
|
## 按需读取
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
- 当前阶段写细,后续阶段写粗。
|
|
23
23
|
- 完成时必须记录可验证证据。
|
|
24
|
-
- 按共享 skill 的 verification
|
|
24
|
+
- 按共享 skill 的 verification 规范判断风险和验证范围;所有风险级别默认自验,仅在用户明确要求时独立复核,修复后记录适用验证。
|
|
25
25
|
|
|
26
26
|
## 影响模块或文件
|
|
27
27
|
|
|
@@ -47,10 +47,12 @@
|
|
|
47
47
|
<!-- 标题必须保持为“阶段准入摘要”,不要改成“阶段 1 准入摘要”等带编号变体;阶段身份以 PLAN_MAP.md 为准。 -->
|
|
48
48
|
### 阶段准入摘要
|
|
49
49
|
|
|
50
|
+
<!-- 用户明确要求独立复核时,可在下表增加 | 独立复核请求 | [用户请求](#记录该请求的章节) |。 -->
|
|
51
|
+
|
|
50
52
|
| 字段 | 内容 |
|
|
51
53
|
|---|---|
|
|
52
54
|
| 准入状态 | {{status}} |
|
|
53
|
-
| 复核策略 |
|
|
55
|
+
| 复核策略 | 默认自验 |
|
|
54
56
|
| Step 0 | 当前阶段 Step 0 证据的链接或锚点 |
|
|
55
57
|
| 样本矩阵 | 样本/fixture 或替代基线的链接或锚点 |
|
|
56
58
|
| 验证方式 | 可执行命令和输出位置的链接或锚点 |
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
`plan-governance-cli setup --target codex --dry-run` 预览主治理 skill 的同步差异,manifest 包含入口、按需参考、代理元数据和模板。迁移规则位于主 skill 的 `references/migration.md`,可通过 `plan-governance-cli guide migration` 按需读取;不会注册第二个 migration skill。`--destination DIR` 指定主 skill 目标目录。实际覆盖需既有用户授权并按 setup 冲突提示处理,不自动清理目标之外的用户目录。setup 只支持 Codex 单目标同步;项目初始化器只维护 `AGENTS.md`。项目升级不迁移旧计划,受管块外内容必须保持。
|
|
22
22
|
|
|
23
|
-
仅更新计划格式不等于更新项目入口。已有项目在任务交接、没有进行中的实施或复核时更新受管入口;升级不批量回写历史,旧策略名和六列格式按 verification
|
|
23
|
+
仅更新计划格式不等于更新项目入口。已有项目在任务交接、没有进行中的实施或复核时更新受管入口;升级不批量回写历史,旧策略名和六列格式按 verification 解释为默认自验,保留真实历史发现。安装副本与仓库开发规则有差异时说明本次选用来源,不能因版本号相同就混读正文。
|
|
24
24
|
|
|
25
25
|
## 初始化、模板和检查脚本
|
|
26
26
|
|
|
@@ -48,9 +48,11 @@
|
|
|
48
48
|
|
|
49
49
|
目标、授权、关键契约或高影响后果变化时,重新判断受影响范围的准入与验证;等待必要取舍期间,可继续无依赖的已授权工作。普通反馈、测试结果和状态更新在当前任务内处理并同步,不自动暂停、重开阶段或再索取授权。范围调整不能移走真实阻塞。
|
|
50
50
|
|
|
51
|
+
发现异常时,先判断是否影响当前目标、验收或安全边界;影响则处理,关系不明则做有限核查,无关则记录后继续。不要因发现新问题自动扩大当前任务;调整既有验收条件时,须保留真实风险并同步阶段门。
|
|
52
|
+
|
|
51
53
|
## 执行与恢复
|
|
52
54
|
|
|
53
|
-
沿用已确认决定,只展开本次差异、证据缺口及直接依赖。跨阶段工作按 [阶段门](verification.md#step-0-与阶段门)
|
|
55
|
+
沿用已确认决定,只展开本次差异、证据缺口及直接依赖。跨阶段工作按 [阶段门](verification.md#step-0-与阶段门)判断,每阶段有自身基线与完成条件;上一阶段通过不自动放行下一阶段,已有独立检查可按 verification 显式复用。未来事项需注明承接范围与依赖,不以未准入的后续工作阻断无关的当前交付。
|
|
54
56
|
|
|
55
57
|
文档变更后做适用链接、结构和引用检查,运行所选版本的 `plan-governance-cli check .`;准入/发布使用 `--strict-readiness`。纯落档不重复代码测试。用户验收与证据真实性按 verification,不以文档格式通过替代。
|
|
56
58
|
|
|
@@ -8,21 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
| 记录形式 | 解释 |
|
|
10
10
|
|---|---|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
11
|
+
| 默认自验 | 当前模板标签 |
|
|
12
|
+
| 单次独立复核、风险分流 | 历史标签,按默认自验解释,不触发迁移或重审 |
|
|
13
13
|
| 无字段 | 保留六列历史格式,后续自验类型见旧计划兼容 |
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
显式字段的空值、未知值和重复声明不能放行。升级不批量改写计划;原检查按真实日期、结论、证据和身份保留,旧复核发现须由真实修复自验闭环,格式统一本身不解决问题。CLI 能力不符时说明缺口,更新按授权处理。
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 自验与按需独立复核
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
以下方式适用于所有计划;普通无计划任务也按实际风险选择验证,不建立阶段表。
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
所有风险级别默认由实施者自验。改变权限、安全、隐私、资金、数据完整性、核心契约或产生广泛/难以撤销后果时,按实际风险扩大验证深度、受影响回归和失败边界;风险不清先查事实。风险、目录、行数、阶段事件或一般实施授权均不自动触发独立复核,也不反复征求用户是否复核。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
用户明确要求独立复核时,按其指定范围安排。已有同范围结果可复用;已审范围内的增量和修复合并处理,不把每个修复拆成新范围。后续独立通过不能清除先前检查留下的真实发现。
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
收到明确请求后,安排一名未参与实现或测试编写的只读复核者,提供范围、差异、风险和证据入口,并要求其自行完成、不得再委派复核。创建复核 subagent 时显式传入推理强度:涉及安全、权限、隐私、资金、数据完整性或同类高风险后果时用 `high`,其他独立复核用 `medium`。派发前复用已有同范围任务或结果;等待失败先核对准确任务 ID 与实际状态,只有确认原任务不存在或不可恢复才补发。冻结受审范围并告知变化。独立者给出发现后,实施者修复并验证原问题及受影响回归;未解决则保持未完成。检查不可用/超时如实记录,不伪填已完成结论;仅因历史检查不可用或超时而缺少独立基线时,可转为适用自验。复核不代替外部授权。
|
|
26
26
|
|
|
27
27
|
## Step 0 与阶段门
|
|
28
28
|
|
|
@@ -34,7 +34,7 @@ Step 0 可采用缺陷复现、迁移快照/兼容样本、新功能验收 fixtu
|
|
|
34
34
|
|
|
35
35
|
验证用户可观察结果和受影响回归,完成项目要求的检查。纯文档做适用文档检查并注明覆盖率不适用。检查通过后,只有新变化、失败或未解疑点才扩大或重复验证。
|
|
36
36
|
|
|
37
|
-
复用证据须覆盖当前工作树、依赖/配置、环境和验收契约,内容可访问;仅 HEAD
|
|
37
|
+
复用证据须覆盖当前工作树、依赖/配置、环境和验收契约,内容可访问;仅 HEAD/版本相同不足以证明有效。已有独立检查若跨阶段复用,可在当前阶段以 `复核基线复用` 明确关联原记录、来源阶段和范围;未来阶段或未解决基线不可复用。缺口补受影响验证,未解决冲突如实保留。只有状态、证据或链接同步时,不重新跑代码全套;无关任务失败如实报告,不擅自接管。
|
|
38
38
|
|
|
39
39
|
自验失败自主修复/复验。保留独立发现,按“发现 → 修复 → 验证”闭环并准确标记自验。机械检查只证明结构,不能证明风险、范围、独立性或证据真实性。可选 attestation 的显式检查见 [CLI](cli.md#初始化模板和检查脚本)。
|
|
40
40
|
|
|
@@ -62,10 +62,10 @@ Step 0 可采用缺陷复现、迁移快照/兼容样本、新功能验收 fixtu
|
|
|
62
62
|
|
|
63
63
|
`阶段复核记录` 按 `日期、类型、阶段、方式、风险、结论、证据、复核者` 八列追加,日期顺序和最新表与当前阶段末条一致。完整结果须有有效日期、证据、身份及已判断风险;普通无计划任务无需建表。
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
高风险/高影响自验无需独立基线,但须有覆盖实际风险的验证证据。已有跨阶段独立基线若选择复用,追加类型 `复核基线复用`、方式 `自验` 的当前阶段记录,证据须包含来源阶段并关联原记录和相同范围。独立发现修复后用类型 `修复自验`、方式 `自验` 追加,证据说明原发现与修复回归,不能以普通自验或第二次独立通过覆盖未修复发现。自验不伪称独立通过;上一阶段历史不自动阻断当前阶段。
|
|
66
66
|
|
|
67
|
-
结论以明确前缀记录:`通过`、`未通过`等;复核入口不可用/超时直接写其状态,实际查出的证据冲突可作为发现。通过说明不能覆盖结构化未解决事项。check 默认对新准入缺陷 WARNING,待实施/实施中在 `--strict-readiness` 下 ERROR。workset 保持 schema 1
|
|
67
|
+
结论以明确前缀记录:`通过`、`未通过`等;复核入口不可用/超时直接写其状态,实际查出的证据冲突可作为发现。通过说明不能覆盖结构化未解决事项。check 默认对新准入缺陷 WARNING,待实施/实施中在 `--strict-readiness` 下 ERROR。workset 保持 schema 1:默认待自验 `verify`;仅当前阶段摘要有 `独立复核请求` 且填入可追溯的用户明确请求证据时,待办为 `independent_review`,即使自验通过也要等已请求的独立检查完成,不能仅凭 `方式:独立` 或旧策略名推断请求;通过待地图同步 `sync`、失败 `blocked/resolve_blocker`、歧义 `unknown/unknown`。不自动写状态,hook 只提示。
|
|
68
68
|
|
|
69
69
|
### 旧计划兼容
|
|
70
70
|
|
|
71
|
-
没有策略字段时,保留固定标题 `阶段路线图`、`当前阶段`、`阶段准入摘要`、`最新独立准入复核`、`独立复核记录`,不为统一行为重写历史。摘要字段为准入状态、Step 0
|
|
71
|
+
没有策略字段时,保留固定标题 `阶段路线图`、`当前阶段`、`阶段准入摘要`、`最新独立准入复核`、`独立复核记录`,不为统一行为重写历史。摘要字段为准入状态、Step 0、样本矩阵、验证方式、失败/回滚边界、当前阻塞项及最新独立准入复核;按需增加 `独立复核请求` 及用户请求证据链接。最新表含日期、阶段、结论、证据、复核者;历史使用日期、类型、阶段、结论、证据、复核者六列。自验写类型 `普通自验`;独立发现后的闭环写 `修复自验`,且不能清除真实未解决发现;跨阶段复用写 `复核基线复用` 并关联原记录。其他历史类型按独立检查解释,最新表与当前阶段末条适用记录一致。标题不加阶段编号,阶段身份以地图为准。
|
|
@@ -231,6 +231,17 @@ def legacy_review_method(kind):
|
|
|
231
231
|
return "自验" if kind == "复核基线复用" or "自验" in kind else "独立"
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
def independent_review_requested(summary):
|
|
235
|
+
"""只有明确的用户请求证据才将待办派给独立复核。"""
|
|
236
|
+
request = summary.get("独立复核请求", "").strip()
|
|
237
|
+
return bool(request and request != "无" and not is_placeholder(request))
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def review_unavailable(conclusion):
|
|
241
|
+
"""工具未完成不等于审出了实质问题。"""
|
|
242
|
+
return conclusion.strip().startswith(("超时", "复核工具超时", "复核入口不可用"))
|
|
243
|
+
|
|
244
|
+
|
|
234
245
|
def phase_precedes(plan_text, candidate, current):
|
|
235
246
|
"""只允许路线图中更早的阶段;标准数字阶段可在精简路线图中回退比较。"""
|
|
236
247
|
roadmap = [row[0] for row in phase_roadmap_rows(plan_text)]
|
|
@@ -243,7 +254,7 @@ def phase_precedes(plan_text, candidate, current):
|
|
|
243
254
|
|
|
244
255
|
|
|
245
256
|
def legacy_review_state(plan_text, phase):
|
|
246
|
-
"""
|
|
257
|
+
"""在不改写六列历史的前提下应用默认自验和真实发现闭环。"""
|
|
247
258
|
result = {"passed": False, "pending_action": None, "issues": [], "blockers": []}
|
|
248
259
|
issues, blockers = result["issues"], result["blockers"]
|
|
249
260
|
rows = review_history_rows(plan_text)
|
|
@@ -299,7 +310,7 @@ def legacy_review_state(plan_text, phase):
|
|
|
299
310
|
outcome = review_outcome(row[3])
|
|
300
311
|
if method == "独立":
|
|
301
312
|
state["reviewed"] = completed_independent(row)
|
|
302
|
-
if outcome == "failed":
|
|
313
|
+
if outcome == "failed" and not review_unavailable(row[3]):
|
|
303
314
|
state["unresolved"] = True
|
|
304
315
|
elif (row[1] == "修复自验" and state["reviewed"] and outcome == "passed"
|
|
305
316
|
and qualified(row)):
|
|
@@ -319,7 +330,7 @@ def legacy_review_state(plan_text, phase):
|
|
|
319
330
|
issues.append("旧独立复核记录结论为空或未知")
|
|
320
331
|
if method == "独立":
|
|
321
332
|
reviewed = completed_independent(row)
|
|
322
|
-
if outcome == "failed":
|
|
333
|
+
if outcome == "failed" and not review_unavailable(row[3]):
|
|
323
334
|
unresolved = row[3]
|
|
324
335
|
elif row[1] == "复核基线复用":
|
|
325
336
|
referenced = [source for source in reusable_prior_phases if source in row[4]]
|
|
@@ -328,9 +339,7 @@ def legacy_review_state(plan_text, phase):
|
|
|
328
339
|
elif outcome == "passed" and qualified(row):
|
|
329
340
|
reviewed = True
|
|
330
341
|
elif row[1] == "修复自验":
|
|
331
|
-
if
|
|
332
|
-
issues.append("旧格式修复自验缺少已完成的独立复核基线")
|
|
333
|
-
elif outcome == "passed" and qualified(row):
|
|
342
|
+
if outcome == "passed" and qualified(row) and reviewed:
|
|
334
343
|
unresolved = None
|
|
335
344
|
if outcome == "passed" and not qualified(row):
|
|
336
345
|
issues.append("旧独立复核记录通过缺少有效日期、类型、证据或身份")
|
|
@@ -346,15 +355,19 @@ def legacy_review_state(plan_text, phase):
|
|
|
346
355
|
review.get(field) == current[-1][index]
|
|
347
356
|
for field, index in [("日期", 0), ("阶段", 2), ("结论", 3), ("证据", 4), ("复核者", 5)]
|
|
348
357
|
)
|
|
349
|
-
|
|
358
|
+
summary = key_value_table(fixed_section(top_level_section(plan_text, "当前阶段"), "阶段准入摘要"))
|
|
359
|
+
requested = independent_review_requested(summary)
|
|
360
|
+
awaiting_requested_review = requested and outcome == "passed" and not reviewed
|
|
361
|
+
result["passed"] = outcome == "passed" and latest_matches and not issues and not blockers and not awaiting_requested_review
|
|
350
362
|
if outcome == "pending" and not issues and not blockers:
|
|
351
|
-
|
|
352
|
-
|
|
363
|
+
result["pending_action"] = "independent_review" if requested else "verify"
|
|
364
|
+
elif awaiting_requested_review and not issues and not blockers:
|
|
365
|
+
result["pending_action"] = "independent_review"
|
|
353
366
|
return result
|
|
354
367
|
|
|
355
368
|
|
|
356
369
|
def risk_review_state(plan_text, phase):
|
|
357
|
-
"""
|
|
370
|
+
"""显式风险策略的共享事实判定;历史策略名不改变默认自验行为。"""
|
|
358
371
|
summary_section = fixed_section(top_level_section(plan_text, "当前阶段"), "阶段准入摘要")
|
|
359
372
|
policies = [row for row in markdown_table_rows(summary_section) if row[0] == "复核策略"]
|
|
360
373
|
result = {"enabled": bool(policies), "passed": False, "pending_action": None,
|
|
@@ -362,8 +375,8 @@ def risk_review_state(plan_text, phase):
|
|
|
362
375
|
if not policies:
|
|
363
376
|
return result
|
|
364
377
|
issues, blockers = result["issues"], result["blockers"]
|
|
365
|
-
if len(policies) != 1 or len(policies[0]) != 2 or policies[0][1] not in {"风险分流", "单次独立复核"}:
|
|
366
|
-
issues.append("复核策略必须唯一且为
|
|
378
|
+
if len(policies) != 1 or len(policies[0]) != 2 or policies[0][1] not in {"风险分流", "单次独立复核", "默认自验"}:
|
|
379
|
+
issues.append("复核策略必须唯一且为 默认自验/风险分流/单次独立复核;空值、未知值或重复声明不能准入")
|
|
367
380
|
risks = {"低风险", "高影响", "高风险"}
|
|
368
381
|
summary = key_value_table(summary_section)
|
|
369
382
|
if "最新独立准入复核" in summary:
|
|
@@ -464,7 +477,7 @@ def risk_review_state(plan_text, phase):
|
|
|
464
477
|
else:
|
|
465
478
|
state["reviewed_high"] = False
|
|
466
479
|
row_outcome = review_outcome(row[5])
|
|
467
|
-
if row_outcome == "failed":
|
|
480
|
+
if row_outcome == "failed" and not review_unavailable(row[5]):
|
|
468
481
|
state["unresolved"] = True
|
|
469
482
|
elif (row[1] == "修复自验" and state["reviewed_high"]
|
|
470
483
|
and review_outcome(row[5]) == "passed"
|
|
@@ -489,7 +502,7 @@ def risk_review_state(plan_text, phase):
|
|
|
489
502
|
reviewed_high = row[4] in {"高风险", "高影响"}
|
|
490
503
|
else:
|
|
491
504
|
reviewed = reviewed_high = False
|
|
492
|
-
if review_outcome(row[5]) == "failed":
|
|
505
|
+
if review_outcome(row[5]) == "failed" and not review_unavailable(row[5]):
|
|
493
506
|
unresolved_single = row[5]
|
|
494
507
|
elif review_outcome(row[5]) == "passed" and completed(row):
|
|
495
508
|
# 后续独立通过可形成新范围基线,但不能清除既有独立发现。
|
|
@@ -503,12 +516,8 @@ def risk_review_state(plan_text, phase):
|
|
|
503
516
|
and not any(is_placeholder(value) for value in row)
|
|
504
517
|
and valid_date(row[0]) is not None):
|
|
505
518
|
reviewed = reviewed_high = True
|
|
506
|
-
elif row[4] in {"高风险", "高影响"} and not reviewed_high:
|
|
507
|
-
issues.append("高风险/高影响自验缺少同范围独立复核基线或明确的跨阶段复用记录")
|
|
508
519
|
if row[1] == "修复自验":
|
|
509
|
-
if
|
|
510
|
-
issues.append("修复自验缺少已完成的独立复核基线")
|
|
511
|
-
elif (review_outcome(row[5]) == "passed" and row[4] in risks
|
|
520
|
+
if (reviewed and review_outcome(row[5]) == "passed" and row[4] in risks
|
|
512
521
|
and not any(is_placeholder(value) for value in row)
|
|
513
522
|
and valid_date(row[0]) is not None):
|
|
514
523
|
unresolved_single = None
|
|
@@ -560,7 +569,7 @@ def risk_review_state(plan_text, phase):
|
|
|
560
569
|
row_outcome = review_outcome(row[3])
|
|
561
570
|
if not qualified(row, legacy=True):
|
|
562
571
|
issues.append("旧独立复核记录缺少有效日期、类型、证据或身份,迁移不能掩盖")
|
|
563
|
-
if row_outcome == "failed":
|
|
572
|
+
if row_outcome == "failed" and not review_unavailable(row[3]):
|
|
564
573
|
unresolved = row[3]
|
|
565
574
|
elif row_outcome == "passed" and qualified(row, legacy=True):
|
|
566
575
|
pass
|
|
@@ -581,9 +590,13 @@ def risk_review_state(plan_text, phase):
|
|
|
581
590
|
elif not legacy_history or any(is_placeholder(legacy.get(field))
|
|
582
591
|
for field in ["日期", "阶段", "结论", "证据", "复核者"]) or valid_date(legacy.get("日期", "")) is None:
|
|
583
592
|
issues.append("旧最新独立准入复核缺少有效字段或当前阶段历史,不能降级放行")
|
|
584
|
-
|
|
593
|
+
requested = independent_review_requested(summary)
|
|
594
|
+
awaiting_requested_review = requested and outcome == "passed" and not reviewed
|
|
595
|
+
result["passed"] = outcome == "passed" and not issues and not blockers and not awaiting_requested_review
|
|
585
596
|
if outcome == "pending" and not issues and not blockers:
|
|
586
|
-
result["pending_action"] = "
|
|
597
|
+
result["pending_action"] = "independent_review" if requested else "verify"
|
|
598
|
+
elif awaiting_requested_review and not issues and not blockers:
|
|
599
|
+
result["pending_action"] = "independent_review"
|
|
587
600
|
return result
|
|
588
601
|
|
|
589
602
|
|
|
@@ -748,7 +761,7 @@ def check_phase_structure(plan_name, data, plan_text, strict, warnings, errors,
|
|
|
748
761
|
warnings,
|
|
749
762
|
errors,
|
|
750
763
|
strict,
|
|
751
|
-
f"{plan_name}:
|
|
764
|
+
f"{plan_name}: 旧格式当前阶段记录未满足自验或已请求复核的准入",
|
|
752
765
|
)
|
|
753
766
|
|
|
754
767
|
|
|
@@ -2406,19 +2419,19 @@ def workset_payload(root, include_history=False, strict=False):
|
|
|
2406
2419
|
"state": "known" if kind else "unknown",
|
|
2407
2420
|
"kind": kind or "unknown",
|
|
2408
2421
|
"reason": ("当前阶段复核通过,待同步 PLAN_MAP 准入状态" if kind == "sync" else
|
|
2409
|
-
"
|
|
2422
|
+
"当前阶段待自验" if kind == "verify" else
|
|
2410
2423
|
"当前阶段待独立复核" if kind == "independent_review" else
|
|
2411
2424
|
"当前阶段复核声明无法确定"),
|
|
2412
2425
|
}
|
|
2413
2426
|
elif not current_review_passes(plan_text, data["phase"]):
|
|
2414
2427
|
legacy_state = legacy_review_state(plan_text, data["phase"])
|
|
2415
|
-
kind = legacy_state["pending_action"] or "
|
|
2428
|
+
kind = legacy_state["pending_action"] or "verify"
|
|
2416
2429
|
readiness = "design"
|
|
2417
2430
|
action = {
|
|
2418
2431
|
"state": "known",
|
|
2419
2432
|
"kind": kind,
|
|
2420
2433
|
"reason": ("当前阶段待自验" if kind == "verify" else
|
|
2421
|
-
"
|
|
2434
|
+
"用户已明确要求独立复核"),
|
|
2422
2435
|
}
|
|
2423
2436
|
else:
|
|
2424
2437
|
readiness = "design"
|
|
@@ -58,7 +58,7 @@ def agent_rules_body():
|
|
|
58
58
|
|
|
59
59
|
最小执行边界:
|
|
60
60
|
|
|
61
|
-
- 普通一次性任务直接处理;已有计划按共享 verification
|
|
61
|
+
- 普通一次性任务直接处理;已有计划按共享 verification 验证。新旧计划均默认自验,仅在用户明确要求时独立复核;未解决问题继续阻塞。
|
|
62
62
|
- 只实施已授权、已准入的当前阶段。每个阶段有自身 Step 0、验证/完成和失败边界;未解决问题不能记为完成,不可用或超时不能冒充已检查。已有授权不重复索取,新增高影响外部动作按实际授权处理。
|
|
63
63
|
- 首次读取 `docs/PLAN_MAP.md`、索引登记的相关 `docs/plans/` 计划及适用契约/ADR/migration;恢复先核对当前工作集、最近证据和实际 diff,缺失或冲突再展开。
|
|
64
64
|
- 地图维护状态、阶段、关系、阻塞与证据入口;计划记录本次差异及验证,现行契约优先复用 Schema/OpenAPI。新事实不写回历史草案,变化同步地图及相关引用。
|