plan-governance-cli 0.2.4 → 0.3.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.
@@ -92,6 +92,7 @@ def agent_rules_body():
92
92
  - 验证方式、完成条件、失败策略和回滚或安全边界明确。
93
93
  - 没有未解决的当前阶段阻塞项,且 `PLAN_MAP.md` 已同步。
94
94
  - 最新独立准入复核明确为“通过”。
95
+ - 机器识别的结构化章节标题固定为 `阶段路线图`、`当前阶段`、`阶段准入摘要`、`最新独立准入复核`、`独立复核记录`;不要写成 `阶段 1 准入摘要` 等带编号变体,阶段编号以 `PLAN_MAP.md` 的当前阶段为准。
95
96
 
96
97
  专项计划应保留追加式独立复核记录,并显式维护最新结论的日期、阶段、结论、证据和复核者。历史记录不得覆盖;`PLAN_MAP.md` 只链接最新有效结论。
97
98
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  import argparse
3
+ import importlib.util
3
4
  import re
4
5
  import subprocess
5
6
  import sys
@@ -134,6 +135,16 @@ def active_plans(root):
134
135
  return [plan for plan in plans if plan["status"] in ACTIVE_STATUSES], blockers
135
136
 
136
137
 
138
+ def load_next_checker():
139
+ checker_path = Path(__file__).with_name("check_plan_governance.py")
140
+ spec = importlib.util.spec_from_file_location("plan_governance_next_checker", checker_path)
141
+ if spec is None or spec.loader is None:
142
+ return None
143
+ module = importlib.util.module_from_spec(spec)
144
+ spec.loader.exec_module(module)
145
+ return module
146
+
147
+
137
148
  def target_matches_path(target, path):
138
149
  normalized_target = normalize_scope_path(target)
139
150
  normalized_path = normalize_scope_path(path)
@@ -178,7 +189,25 @@ def print_session_start(root):
178
189
  print(f"- {row[0]}: {row[4]}")
179
190
  else:
180
191
  print("[plan-governance] 当前阻塞项:无。")
181
- return 0
192
+
193
+ checker = load_next_checker()
194
+ if checker is None:
195
+ return 0
196
+ hook_status = 0
197
+ for plan in active:
198
+ payload, status = checker.plan_next_payload(root, plan["name"])
199
+ if payload["status"] == "not_enabled":
200
+ continue
201
+ ready = ",".join(item["id"] for item in payload.get("ready_steps", [])) or "-"
202
+ blocked = ",".join(item["id"] for item in payload.get("blocked_steps", [])) or "-"
203
+ action = payload["next_action"]
204
+ print(
205
+ f"[plan-governance] autonomous next: {plan['name']} | "
206
+ f"{payload['status']} | ready={ready} | blocked={blocked} | "
207
+ f"next={action['kind']}:{action['reason']}"
208
+ )
209
+ hook_status = max(hook_status, status)
210
+ return hook_status
182
211
 
183
212
 
184
213
  def print_pre_write(root, paths):