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.
- package/README.md +46 -3
- package/bin/plan-governance-cli.mjs +28 -0
- package/package.json +7 -3
- package/resources/manifest.json +2 -1
- package/resources/skill/SKILL.md +54 -5
- package/resources/skill/agents/openai.yaml +1 -1
- package/resources/skill/assets/PLAN_MAP.template.md +2 -0
- package/resources/skill/assets/plan.template.md +35 -0
- package/scripts/check_plan_governance.py +1445 -22
- package/scripts/graph_governance.mjs +988 -0
- package/scripts/init_plan_governance.py +1 -0
- package/scripts/plan_governance_hook.py +30 -1
|
@@ -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
|
-
|
|
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):
|