@aipper/aiws 0.0.29 → 0.0.31

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.
Files changed (278) hide show
  1. package/bin/aiws.js +2 -2
  2. package/dist/aiws-package.d.ts +4 -0
  3. package/dist/aiws-package.js +11 -0
  4. package/dist/aiws-package.js.map +1 -0
  5. package/dist/aiws-paths.d.ts +48 -0
  6. package/dist/aiws-paths.js +129 -0
  7. package/dist/aiws-paths.js.map +1 -0
  8. package/dist/backup.d.ts +27 -0
  9. package/dist/backup.js +125 -0
  10. package/dist/backup.js.map +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +773 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/codex-prompts.d.ts +17 -0
  15. package/dist/codex-prompts.js +49 -0
  16. package/dist/codex-prompts.js.map +1 -0
  17. package/dist/codex-skills.d.ts +17 -0
  18. package/dist/codex-skills.js +75 -0
  19. package/dist/codex-skills.js.map +1 -0
  20. package/dist/commands/change-advice.d.ts +25 -0
  21. package/dist/commands/change-advice.js +197 -0
  22. package/dist/commands/change-advice.js.map +1 -0
  23. package/dist/commands/change-evidence-command.d.ts +29 -0
  24. package/dist/commands/change-evidence-command.js +213 -0
  25. package/dist/commands/change-evidence-command.js.map +1 -0
  26. package/dist/commands/change-evidence-entry.d.ts +16 -0
  27. package/dist/commands/change-evidence-entry.js +35 -0
  28. package/dist/commands/change-evidence-entry.js.map +1 -0
  29. package/dist/commands/change-evidence.d.ts +108 -0
  30. package/dist/commands/change-evidence.js +341 -0
  31. package/dist/commands/change-evidence.js.map +1 -0
  32. package/dist/commands/change-finish.d.ts +71 -0
  33. package/dist/commands/change-finish.js +387 -0
  34. package/dist/commands/change-finish.js.map +1 -0
  35. package/dist/commands/change-git-status.d.ts +22 -0
  36. package/dist/commands/change-git-status.js +50 -0
  37. package/dist/commands/change-git-status.js.map +1 -0
  38. package/dist/commands/change-lifecycle-entry.d.ts +29 -0
  39. package/{src → dist}/commands/change-lifecycle-entry.js +21 -28
  40. package/dist/commands/change-lifecycle-entry.js.map +1 -0
  41. package/dist/commands/change-lifecycle.d.ts +56 -0
  42. package/dist/commands/change-lifecycle.js +211 -0
  43. package/dist/commands/change-lifecycle.js.map +1 -0
  44. package/dist/commands/change-metrics-command.d.ts +12 -0
  45. package/dist/commands/change-metrics-command.js +110 -0
  46. package/dist/commands/change-metrics-command.js.map +1 -0
  47. package/dist/commands/change-next-command.d.ts +18 -0
  48. package/dist/commands/change-next-command.js +138 -0
  49. package/dist/commands/change-next-command.js.map +1 -0
  50. package/dist/commands/change-review-gates.d.ts +107 -0
  51. package/dist/commands/change-review-gates.js +329 -0
  52. package/dist/commands/change-review-gates.js.map +1 -0
  53. package/dist/commands/change-scope-gate.d.ts +21 -0
  54. package/dist/commands/change-scope-gate.js +32 -0
  55. package/dist/commands/change-scope-gate.js.map +1 -0
  56. package/dist/commands/change-start.d.ts +30 -0
  57. package/dist/commands/change-start.js +91 -0
  58. package/dist/commands/change-start.js.map +1 -0
  59. package/dist/commands/change-state-command.d.ts +3 -0
  60. package/dist/commands/change-state-command.js +32 -0
  61. package/dist/commands/change-state-command.js.map +1 -0
  62. package/dist/commands/change-status-command.d.ts +13 -0
  63. package/dist/commands/change-status-command.js +126 -0
  64. package/dist/commands/change-status-command.js.map +1 -0
  65. package/dist/commands/change-status-context.d.ts +58 -0
  66. package/dist/commands/change-status-context.js +166 -0
  67. package/dist/commands/change-status-context.js.map +1 -0
  68. package/dist/commands/change-task-stats.d.ts +24 -0
  69. package/dist/commands/change-task-stats.js +66 -0
  70. package/dist/commands/change-task-stats.js.map +1 -0
  71. package/dist/commands/change-validate-entry.d.ts +17 -0
  72. package/dist/commands/change-validate-entry.js +44 -0
  73. package/dist/commands/change-validate-entry.js.map +1 -0
  74. package/dist/commands/change-validate.d.ts +32 -0
  75. package/dist/commands/change-validate.js +128 -0
  76. package/dist/commands/change-validate.js.map +1 -0
  77. package/dist/commands/change.d.ts +322 -0
  78. package/dist/commands/change.js +1731 -0
  79. package/dist/commands/change.js.map +1 -0
  80. package/dist/commands/codex-install-prompts.d.ts +4 -0
  81. package/dist/commands/codex-install-prompts.js +68 -0
  82. package/dist/commands/codex-install-prompts.js.map +1 -0
  83. package/dist/commands/codex-install-skills.d.ts +4 -0
  84. package/dist/commands/codex-install-skills.js +74 -0
  85. package/dist/commands/codex-install-skills.js.map +1 -0
  86. package/dist/commands/codex-status-prompts.d.ts +4 -0
  87. package/dist/commands/codex-status-prompts.js +44 -0
  88. package/dist/commands/codex-status-prompts.js.map +1 -0
  89. package/dist/commands/codex-status-skills.d.ts +4 -0
  90. package/dist/commands/codex-status-skills.js +54 -0
  91. package/dist/commands/codex-status-skills.js.map +1 -0
  92. package/dist/commands/codex-uninstall-prompts.d.ts +4 -0
  93. package/dist/commands/codex-uninstall-prompts.js +51 -0
  94. package/dist/commands/codex-uninstall-prompts.js.map +1 -0
  95. package/dist/commands/codex-uninstall-skills.d.ts +4 -0
  96. package/dist/commands/codex-uninstall-skills.js +59 -0
  97. package/dist/commands/codex-uninstall-skills.js.map +1 -0
  98. package/dist/commands/dashboard.d.ts +222 -0
  99. package/dist/commands/dashboard.js +193 -0
  100. package/dist/commands/dashboard.js.map +1 -0
  101. package/dist/commands/hooks-install.d.ts +4 -0
  102. package/dist/commands/hooks-install.js +90 -0
  103. package/dist/commands/hooks-install.js.map +1 -0
  104. package/dist/commands/hooks-status.d.ts +4 -0
  105. package/dist/commands/hooks-status.js +89 -0
  106. package/dist/commands/hooks-status.js.map +1 -0
  107. package/dist/commands/init.d.ts +4 -0
  108. package/dist/commands/init.js +100 -0
  109. package/dist/commands/init.js.map +1 -0
  110. package/dist/commands/opencode-auto.d.ts +11 -0
  111. package/dist/commands/opencode-auto.js +158 -0
  112. package/dist/commands/opencode-auto.js.map +1 -0
  113. package/dist/commands/opencode-status.d.ts +4 -0
  114. package/dist/commands/opencode-status.js +75 -0
  115. package/dist/commands/opencode-status.js.map +1 -0
  116. package/dist/commands/opencode-supervise.d.ts +24 -0
  117. package/dist/commands/opencode-supervise.js +188 -0
  118. package/dist/commands/opencode-supervise.js.map +1 -0
  119. package/dist/commands/rollback.d.ts +4 -0
  120. package/dist/commands/rollback.js +12 -0
  121. package/dist/commands/rollback.js.map +1 -0
  122. package/dist/commands/update.d.ts +4 -0
  123. package/dist/commands/update.js +212 -0
  124. package/dist/commands/update.js.map +1 -0
  125. package/dist/commands/validate.d.ts +4 -0
  126. package/dist/commands/validate.js +222 -0
  127. package/dist/commands/validate.js.map +1 -0
  128. package/dist/commands/ws-commit.d.ts +5 -0
  129. package/dist/commands/ws-commit.js +39 -0
  130. package/dist/commands/ws-commit.js.map +1 -0
  131. package/dist/commands/ws-deliver.d.ts +5 -0
  132. package/dist/commands/ws-deliver.js +59 -0
  133. package/dist/commands/ws-deliver.js.map +1 -0
  134. package/dist/commands/ws-finish.d.ts +5 -0
  135. package/dist/commands/ws-finish.js +142 -0
  136. package/dist/commands/ws-finish.js.map +1 -0
  137. package/dist/commands/ws-handoff.d.ts +5 -0
  138. package/dist/commands/ws-handoff.js +35 -0
  139. package/dist/commands/ws-handoff.js.map +1 -0
  140. package/dist/commands/ws-migrate.d.ts +5 -0
  141. package/dist/commands/ws-migrate.js +41 -0
  142. package/dist/commands/ws-migrate.js.map +1 -0
  143. package/dist/commands/ws-plan-verify.d.ts +5 -0
  144. package/dist/commands/ws-plan-verify.js +38 -0
  145. package/dist/commands/ws-plan-verify.js.map +1 -0
  146. package/dist/commands/ws-pull.d.ts +5 -0
  147. package/dist/commands/ws-pull.js +26 -0
  148. package/dist/commands/ws-pull.js.map +1 -0
  149. package/dist/commands/ws-push.d.ts +5 -0
  150. package/dist/commands/ws-push.js +68 -0
  151. package/dist/commands/ws-push.js.map +1 -0
  152. package/dist/commands/ws-submodule-setup.d.ts +5 -0
  153. package/dist/commands/ws-submodule-setup.js +55 -0
  154. package/dist/commands/ws-submodule-setup.js.map +1 -0
  155. package/dist/commands/ws-verify-before-complete.d.ts +5 -0
  156. package/dist/commands/ws-verify-before-complete.js +35 -0
  157. package/dist/commands/ws-verify-before-complete.js.map +1 -0
  158. package/dist/dashboard/app.d.ts +1 -0
  159. package/dist/dashboard/app.js +370 -0
  160. package/dist/dashboard/app.js.map +1 -0
  161. package/dist/delegation/cli.d.ts +6 -0
  162. package/dist/delegation/cli.js +14 -0
  163. package/dist/delegation/cli.js.map +1 -0
  164. package/dist/delegation/index.d.ts +35 -0
  165. package/dist/delegation/index.js +118 -0
  166. package/dist/delegation/index.js.map +1 -0
  167. package/dist/errors.d.ts +8 -0
  168. package/dist/errors.js +11 -0
  169. package/dist/errors.js.map +1 -0
  170. package/dist/exec.d.ts +9 -0
  171. package/dist/exec.js +22 -0
  172. package/dist/exec.js.map +1 -0
  173. package/dist/fs.d.ts +9 -0
  174. package/dist/fs.js +62 -0
  175. package/dist/fs.js.map +1 -0
  176. package/dist/governance.d.ts +10 -0
  177. package/dist/governance.js +135 -0
  178. package/dist/governance.js.map +1 -0
  179. package/dist/hash.d.ts +3 -0
  180. package/dist/hash.js +13 -0
  181. package/dist/hash.js.map +1 -0
  182. package/dist/hooks/deploy-claude.d.ts +13 -0
  183. package/dist/hooks/deploy-claude.js +67 -0
  184. package/dist/hooks/deploy-claude.js.map +1 -0
  185. package/dist/journal.d.ts +22 -0
  186. package/dist/journal.js +112 -0
  187. package/dist/journal.js.map +1 -0
  188. package/dist/json-schema-lite.d.ts +22 -0
  189. package/dist/json-schema-lite.js +148 -0
  190. package/dist/json-schema-lite.js.map +1 -0
  191. package/dist/managed-blocks.d.ts +24 -0
  192. package/dist/managed-blocks.js +84 -0
  193. package/dist/managed-blocks.js.map +1 -0
  194. package/dist/manifest.d.ts +24 -0
  195. package/dist/manifest.js +145 -0
  196. package/dist/manifest.js.map +1 -0
  197. package/dist/opencode-env.d.ts +62 -0
  198. package/dist/opencode-env.js +178 -0
  199. package/dist/opencode-env.js.map +1 -0
  200. package/dist/path-utils.d.ts +2 -0
  201. package/dist/path-utils.js +8 -0
  202. package/dist/path-utils.js.map +1 -0
  203. package/dist/spec.d.ts +17 -0
  204. package/dist/spec.js +174 -0
  205. package/dist/spec.js.map +1 -0
  206. package/dist/template.d.ts +20 -0
  207. package/dist/template.js +123 -0
  208. package/dist/template.js.map +1 -0
  209. package/dist/workspace.d.ts +4 -0
  210. package/dist/workspace.js +19 -0
  211. package/dist/workspace.js.map +1 -0
  212. package/package.json +11 -3
  213. package/src/aiws-package.js +0 -15
  214. package/src/backup.js +0 -149
  215. package/src/cli.js +0 -760
  216. package/src/codex-prompts.js +0 -74
  217. package/src/codex-skills.js +0 -111
  218. package/src/commands/change-advice.js +0 -181
  219. package/src/commands/change-evidence-command.js +0 -242
  220. package/src/commands/change-evidence-entry.js +0 -40
  221. package/src/commands/change-evidence.js +0 -340
  222. package/src/commands/change-finish.js +0 -413
  223. package/src/commands/change-git-status.js +0 -53
  224. package/src/commands/change-lifecycle.js +0 -236
  225. package/src/commands/change-metrics-command.js +0 -110
  226. package/src/commands/change-next-command.js +0 -133
  227. package/src/commands/change-review-gates.js +0 -331
  228. package/src/commands/change-scope-gate.js +0 -34
  229. package/src/commands/change-start.js +0 -85
  230. package/src/commands/change-state-command.js +0 -40
  231. package/src/commands/change-status-command.js +0 -125
  232. package/src/commands/change-status-context.js +0 -173
  233. package/src/commands/change-task-stats.js +0 -64
  234. package/src/commands/change-validate-entry.js +0 -45
  235. package/src/commands/change-validate.js +0 -127
  236. package/src/commands/change.js +0 -1829
  237. package/src/commands/codex-install-prompts.js +0 -68
  238. package/src/commands/codex-install-skills.js +0 -74
  239. package/src/commands/codex-status-prompts.js +0 -55
  240. package/src/commands/codex-status-skills.js +0 -63
  241. package/src/commands/codex-uninstall-prompts.js +0 -55
  242. package/src/commands/codex-uninstall-skills.js +0 -62
  243. package/src/commands/dashboard.js +0 -205
  244. package/src/commands/hooks-install.js +0 -92
  245. package/src/commands/hooks-status.js +0 -95
  246. package/src/commands/init.js +0 -101
  247. package/src/commands/opencode-auto.js +0 -167
  248. package/src/commands/opencode-status.js +0 -103
  249. package/src/commands/opencode-supervise.js +0 -200
  250. package/src/commands/rollback.js +0 -13
  251. package/src/commands/update.js +0 -145
  252. package/src/commands/validate.js +0 -228
  253. package/src/commands/ws-commit.js +0 -44
  254. package/src/commands/ws-deliver.js +0 -67
  255. package/src/commands/ws-finish.js +0 -83
  256. package/src/commands/ws-handoff.js +0 -40
  257. package/src/commands/ws-migrate.js +0 -41
  258. package/src/commands/ws-plan-verify.js +0 -44
  259. package/src/commands/ws-pull.js +0 -30
  260. package/src/commands/ws-push.js +0 -71
  261. package/src/commands/ws-submodule-setup.js +0 -65
  262. package/src/commands/ws-verify-before-complete.js +0 -39
  263. package/src/dashboard/app.js +0 -371
  264. package/src/errors.js +0 -15
  265. package/src/exec.js +0 -34
  266. package/src/fs.js +0 -91
  267. package/src/governance.js +0 -159
  268. package/src/hash.js +0 -25
  269. package/src/json-schema-lite.js +0 -164
  270. package/src/managed-blocks.js +0 -131
  271. package/src/manifest.js +0 -177
  272. package/src/opencode-env.js +0 -208
  273. package/src/path-utils.js +0 -20
  274. package/src/spec.js +0 -195
  275. package/src/template.js +0 -187
  276. package/src/workspace.js +0 -23
  277. /package/{src → dist}/dashboard/index.html +0 -0
  278. /package/{src → dist}/dashboard/style.css +0 -0
@@ -1,173 +0,0 @@
1
- import path from "node:path";
2
-
3
- /**
4
- * @param {string} gitRoot
5
- * @param {string} changeId
6
- * @param {{
7
- * currentBranch: (gitRoot: string) => Promise<string>,
8
- * inferChangeIdFromBranch: (branch: string) => string
9
- * }} deps
10
- */
11
- export async function resolveChangeStatusContext(gitRoot, changeId, deps) {
12
- const rootBranch = await deps.currentBranch(gitRoot);
13
- const contextBranch = rootBranch;
14
- const inferred = deps.inferChangeIdFromBranch(contextBranch);
15
-
16
- return {
17
- worktree: path.resolve(gitRoot),
18
- branch: contextBranch,
19
- branchMatchesChange: inferred === changeId,
20
- source: "current_worktree",
21
- warning: "",
22
- currentWorktree: path.resolve(gitRoot),
23
- currentBranch: rootBranch,
24
- changeWorktree: "",
25
- };
26
- }
27
-
28
- /**
29
- * @param {string} changeDir
30
- * @param {{ pathExists: (path: string) => Promise<boolean>, readText: (path: string) => Promise<string> }} deps
31
- */
32
- export async function readChangeMetrics(changeDir, deps) {
33
- const metricsAbs = path.join(changeDir, "metrics.json");
34
- if (!(await deps.pathExists(metricsAbs))) return { state: "missing", abs: metricsAbs, events: [] };
35
- try {
36
- const parsed = JSON.parse(await deps.readText(metricsAbs));
37
- const events = Array.isArray(parsed?.events) ? parsed.events : [];
38
- return { state: "ok", abs: metricsAbs, events };
39
- } catch {
40
- return { state: "invalid", abs: metricsAbs, events: [] };
41
- }
42
- }
43
-
44
- const FINISH_DONE_COMPLETED_CLEANUPS = new Set([
45
- "removed",
46
- "pruned-missing",
47
- "skipped:current_worktree",
48
- ]);
49
-
50
- /**
51
- * @param {any} ev
52
- * @returns {{ state: string, reason: string, eventType: string } | null}
53
- */
54
- function classifyFinishLifecycleEvent(ev) {
55
- const type = String(ev?.type || "").trim();
56
- if (!type) return null;
57
- if (type === "finish_local") {
58
- return { state: "local", reason: "", eventType: type };
59
- }
60
- if (type === "finish_failed") {
61
- return { state: "failed", reason: String(ev?.payload?.error || ""), eventType: type };
62
- }
63
- if (type === "finish_cleanup_pending") {
64
- return {
65
- state: "cleanup_pending",
66
- reason: String(ev?.payload?.reason || ev?.payload?.cleanup || ""),
67
- eventType: type,
68
- };
69
- }
70
- if (type === "finish") {
71
- return { state: "done", reason: "", eventType: type };
72
- }
73
- if (type !== "finish_done") return null;
74
-
75
- const payload = ev?.payload && typeof ev.payload === "object" ? ev.payload : null;
76
- const hasPush = payload ? Object.prototype.hasOwnProperty.call(payload, "push") : false;
77
- const pushCompleted = hasPush ? payload?.push === true : null;
78
- const cleanup = String(payload?.cleanup || "").trim();
79
-
80
- if (pushCompleted === false || cleanup === "not_requested") {
81
- return { state: "local", reason: "", eventType: type };
82
- }
83
- if (!cleanup) {
84
- return { state: "done", reason: "", eventType: type };
85
- }
86
- if (FINISH_DONE_COMPLETED_CLEANUPS.has(cleanup)) {
87
- return { state: "done", reason: "", eventType: type };
88
- }
89
-
90
- return {
91
- state: "cleanup_pending",
92
- reason: cleanup.startsWith("skipped:") ? cleanup.slice("skipped:".length) : cleanup,
93
- eventType: type,
94
- };
95
- }
96
-
97
- /**
98
- * @param {{ state: string, events: any[] }} metrics
99
- */
100
- export function summarizeLifecycleSignals(metrics) {
101
- const events = Array.isArray(metrics?.events) ? metrics.events : [];
102
- /** @type {Record<string, number>} */
103
- const eventCounts = {};
104
- let finishState = "";
105
- let finishStateReason = "";
106
- let finishStateEventType = "";
107
- for (const ev of events) {
108
- const type = String(ev?.type || "").trim();
109
- if (!type) continue;
110
- eventCounts[type] = (eventCounts[type] || 0) + 1;
111
- const finishIsTerminal = finishState === "done";
112
- if (finishIsTerminal && type !== "finish_done" && type !== "finish") continue;
113
- const classified = classifyFinishLifecycleEvent(ev);
114
- if (!classified) continue;
115
- finishState = classified.state;
116
- finishStateReason = classified.reason;
117
- finishStateEventType = classified.eventType;
118
- }
119
-
120
- const latest = events.length > 0 ? events[events.length - 1] : null;
121
- const validateEvents = events.filter((ev) => ev?.type === "validate");
122
- const latestStrictValidate = [...validateEvents].reverse().find((ev) => ev?.payload?.strict === true) || null;
123
- const latestStrictScopeValidate =
124
- [...validateEvents].reverse().find((ev) => ev?.payload?.strict === true && ev?.payload?.check_scope === true) || null;
125
- const strictScopeValidateRuns = validateEvents.filter((ev) => ev?.payload?.strict === true && ev?.payload?.check_scope === true).length;
126
-
127
- return {
128
- metricsState: String(metrics?.state || "missing"),
129
- latestEventType: String(latest?.type || ""),
130
- eventCounts,
131
- evidenceRuns: eventCounts.evidence || 0,
132
- finishRuns: (eventCounts.finish || 0) + (eventCounts.finish_done || 0),
133
- finishCleanupPendingReason: finishState === "cleanup_pending" ? finishStateReason : "",
134
- finishState,
135
- finishStateReason,
136
- finishStateEventType,
137
- archiveRuns: eventCounts.archive || 0,
138
- strictValidatePass: latestStrictValidate ? latestStrictValidate?.payload?.ok === true : false,
139
- strictScopeValidateRuns,
140
- strictScopeValidatePass: latestStrictScopeValidate ? latestStrictScopeValidate?.payload?.ok === true : false,
141
- strictScopeValidateAt: String(latestStrictScopeValidate?.timestamp || ""),
142
- strictScopeValidateErrors: Number(latestStrictScopeValidate?.payload?.errors || 0),
143
- strictScopeValidateWarnings: Number(latestStrictScopeValidate?.payload?.warnings || 0),
144
- };
145
- }
146
-
147
- /**
148
- * @param {Record<string, string | null>} curTruth
149
- * @param {any} baseline
150
- * @returns {{ baselineLabel: string, baselineAt: string, driftFiles: string[] }}
151
- */
152
- export function truthDrift(curTruth, baseline) {
153
- /** @type {string[]} */
154
- const driftFiles = [];
155
-
156
- const createdTruth = baseline?.base_truth_files && typeof baseline.base_truth_files === "object" ? baseline.base_truth_files : {};
157
- const syncedTruth = baseline?.synced_truth_files && typeof baseline.synced_truth_files === "object" ? baseline.synced_truth_files : {};
158
- const effective = Object.keys(syncedTruth).length > 0 ? syncedTruth : createdTruth;
159
- const baselineLabel = Object.keys(syncedTruth).length > 0 ? "sync" : "creation";
160
- const baselineAt = Object.keys(syncedTruth).length > 0 ? String(baseline?.synced_at || "") : String(baseline?.created_at || "");
161
-
162
- for (const [rel, info] of Object.entries(effective || {})) {
163
- const baseSha = info && typeof info === "object" ? String(info.sha256 || "") : "";
164
- const curSha = curTruth[rel] ?? null;
165
- if (curSha == null) {
166
- driftFiles.push(rel);
167
- continue;
168
- }
169
- if (baseSha && curSha !== baseSha) driftFiles.push(rel);
170
- }
171
-
172
- return { baselineLabel, baselineAt, driftFiles };
173
- }
@@ -1,64 +0,0 @@
1
- /**
2
- * Parse checkbox tasks with AIWS-specific control markers.
3
- *
4
- * Supported markers:
5
- * - `[optional]`: unchecked optional tasks do not block archive/finish.
6
- * - `[n/a: ...]` / `[na: ...]` / `[not-applicable: ...]`: task is treated as closed.
7
- *
8
- * Returned `total/done/unchecked` are the effective gate counts. Optional open
9
- * tasks are reported separately via `optionalUnchecked`.
10
- *
11
- * @param {string} text
12
- */
13
- export function checkboxStats(text) {
14
- const lines = String(text || "").split(/\r?\n/);
15
- let total = 0;
16
- let done = 0;
17
- let unchecked = 0;
18
- let totalAll = 0;
19
- let doneAll = 0;
20
- let uncheckedAll = 0;
21
- let optionalTotal = 0;
22
- let optionalUnchecked = 0;
23
- let naCount = 0;
24
-
25
- for (const rawLine of lines) {
26
- const match = rawLine.match(/^\s*-\s+\[([ xX])\]\s+(.*)$/);
27
- if (!match) continue;
28
- totalAll += 1;
29
- const checked = String(match[1] || "").toLowerCase() === "x";
30
- const body = String(match[2] || "");
31
- const isOptional = /\[(?:optional|Optional)\]/.test(body);
32
- const isNa = /\[(?:n\/a|na|not-applicable)\s*:[^\]]+\]/i.test(body);
33
-
34
- if (checked) doneAll += 1;
35
- else uncheckedAll += 1;
36
-
37
- if (isOptional) {
38
- optionalTotal += 1;
39
- if (!checked && !isNa) optionalUnchecked += 1;
40
- continue;
41
- }
42
-
43
- total += 1;
44
- if (checked || isNa) {
45
- done += 1;
46
- if (isNa) naCount += 1;
47
- } else {
48
- unchecked += 1;
49
- }
50
- }
51
-
52
- return {
53
- total,
54
- done,
55
- unchecked,
56
- hasCheckboxes: totalAll > 0,
57
- totalAll,
58
- doneAll,
59
- uncheckedAll,
60
- optionalTotal,
61
- optionalUnchecked,
62
- naCount,
63
- };
64
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * @param {{
3
- * gitRoot: string,
4
- * changeId: string,
5
- * options: { strict: boolean, allowTruthDrift: boolean, checkEvidence: boolean, checkScope: boolean }
6
- * }} input
7
- * @param {{
8
- * appendMetricsEvent: (gitRoot: string, changeId: string, type: string, payload: any) => Promise<void>,
9
- * validateChangeArtifacts: (gitRoot: string, changeId: string, options: any) => Promise<any>,
10
- * UserError: typeof import("../errors.js").UserError
11
- * }} deps
12
- */
13
- export async function runChangeValidateCommand(input, deps) {
14
- const { gitRoot, changeId, options } = input;
15
- const result = await deps.validateChangeArtifacts(gitRoot, changeId, {
16
- strict: options.strict === true,
17
- allowTruthDrift: options.allowTruthDrift === true,
18
- checkEvidence: options.checkEvidence === true,
19
- checkScope: options.checkScope === true,
20
- });
21
-
22
- await deps.appendMetricsEvent(gitRoot, changeId, "validate", {
23
- ok: result.ok === true,
24
- strict: options.strict === true,
25
- allow_truth_drift: options.allowTruthDrift === true,
26
- check_evidence: options.checkEvidence === true,
27
- check_scope: options.checkScope === true,
28
- errors: Array.isArray(result.errors) ? result.errors.length : 0,
29
- warnings: Array.isArray(result.warnings) ? result.warnings.length : 0,
30
- exit_code: result.exitCode,
31
- });
32
-
33
- if (result.raw) {
34
- return {
35
- output: result.ok ? `ok: change validated (${changeId})\n` : "",
36
- stderr: result.raw + "\n",
37
- errorToThrow: result.ok ? null : new deps.UserError(""),
38
- };
39
- }
40
- return {
41
- output: result.ok ? `ok: change validated (${changeId})\n` : "",
42
- stderr: "",
43
- errorToThrow: result.ok ? null : new deps.UserError(""),
44
- };
45
- }
@@ -1,127 +0,0 @@
1
- function parseChangeCheckerOutput(stdout, stderr) {
2
- const text = [String(stdout || ""), String(stderr || "")].filter(Boolean).join("\n");
3
- /** @type {string[]} */
4
- const errors = [];
5
- /** @type {string[]} */
6
- const warnings = [];
7
- for (const raw of text.split("\n")) {
8
- const line = raw.trim();
9
- if (!line) continue;
10
- if (line.startsWith("error: ")) errors.push(line.replace(/^error:\s*/, ""));
11
- else if (line.startsWith("warn: ")) warnings.push(line.replace(/^warn:\s*/, ""));
12
- }
13
- return { errors, warnings, raw: text.trim() };
14
- }
15
-
16
- function classifyCheckMessage(msg) {
17
- const s = String(msg || "");
18
- if (s.includes("truth file") || s.includes("truth drift") || s.includes("allow-truth-drift")) return "truth_drift";
19
- if (s.includes("WS:TODO") || s.includes("unrendered template placeholders")) return "placeholders";
20
- if (s.includes("missing:") || s.includes("empty:") || s.includes("Missing change dir")) return "missing_files";
21
- if (
22
- s.includes("Change_ID") ||
23
- s.includes("Req_ID") ||
24
- s.includes("Problem_ID") ||
25
- s.includes("Contract_Row") ||
26
- s.includes("Plan_File") ||
27
- s.includes("Evidence_Path")
28
- ) {
29
- return "bindings";
30
- }
31
- if (s.includes("scope check") || s.includes("out-of-scope")) return "scope_gate";
32
- if (
33
- s.includes("finish gate") ||
34
- s.includes("validate stamp") ||
35
- s.includes("verify-before-complete") ||
36
- s.includes("spec review") ||
37
- s.includes("quality review")
38
- ) {
39
- return "finish_gate";
40
- }
41
- if (
42
- s.includes("missing required sections") ||
43
- s.includes("has empty sections") ||
44
- s.includes("Plan section") ||
45
- s.includes("Verify section") ||
46
- s.includes("scope is too broad") ||
47
- s.includes("too abstract")
48
- ) {
49
- return "plan_quality";
50
- }
51
- return "other";
52
- }
53
-
54
- function groupCheckMessages(errors, warnings) {
55
- const groups = {
56
- truth_drift: { errors: [], warnings: [] },
57
- missing_files: { errors: [], warnings: [] },
58
- placeholders: { errors: [], warnings: [] },
59
- bindings: { errors: [], warnings: [] },
60
- scope_gate: { errors: [], warnings: [] },
61
- finish_gate: { errors: [], warnings: [] },
62
- plan_quality: { errors: [], warnings: [] },
63
- other: { errors: [], warnings: [] },
64
- };
65
-
66
- for (const message of errors || []) {
67
- const group = classifyCheckMessage(message);
68
- groups[group].errors.push(message);
69
- }
70
- for (const message of warnings || []) {
71
- const group = classifyCheckMessage(message);
72
- groups[group].warnings.push(message);
73
- }
74
- return groups;
75
- }
76
-
77
- /**
78
- * @param {string} gitRoot
79
- * @param {string} changeId
80
- * @param {{ strict: boolean, allowTruthDrift: boolean, checkEvidence?: boolean, checkScope?: boolean }} options
81
- * @param {{
82
- * assertValidChangeId: (changeId: string) => void,
83
- * collectFinishGateErrors: (changeId: string, reviewGates: any) => string[],
84
- * computeChangeStatus: (gitRoot: string, changeId: string) => Promise<any>,
85
- * ensureTruthFiles: (gitRoot: string) => Promise<void>,
86
- * resolveWsChangeChecker: (gitRoot: string) => Promise<{ args: string[] }>,
87
- * runPython: (cwd: string, args: string[]) => Promise<{ code: number, stdout: string, stderr: string }>
88
- * }} deps
89
- */
90
- export async function validateChangeArtifacts(gitRoot, changeId, options, deps) {
91
- deps.assertValidChangeId(changeId);
92
- await deps.ensureTruthFiles(gitRoot);
93
-
94
- const checker = await deps.resolveWsChangeChecker(gitRoot);
95
- const args = [...checker.args, "--workspace-root", gitRoot, "--change-id", changeId];
96
- if (options.strict) args.push("--strict");
97
- if (options.allowTruthDrift) args.push("--allow-truth-drift");
98
- if (options.checkEvidence) args.push("--check-evidence");
99
- if (options.checkScope) args.push("--check-scope");
100
-
101
- const res = await deps.runPython(gitRoot, ["-u", ...args]);
102
- const parsed = parseChangeCheckerOutput(res.stdout, res.stderr);
103
- const errors = [...parsed.errors];
104
- const warnings = [...parsed.warnings];
105
-
106
- if (options.checkEvidence === true) {
107
- const status = await deps.computeChangeStatus(gitRoot, changeId);
108
- errors.push(...deps.collectFinishGateErrors(changeId, status.reviewGates));
109
- }
110
-
111
- const rawLines = [];
112
- if (parsed.raw) rawLines.push(parsed.raw);
113
- for (const message of errors.slice(parsed.errors.length)) rawLines.push(`error: ${message}`);
114
- for (const message of warnings.slice(parsed.warnings.length)) rawLines.push(`warn: ${message}`);
115
- const exitCode = res.code === 0 && errors.length > 0 ? 1 : res.code;
116
- return {
117
- ok: exitCode === 0,
118
- changeId,
119
- strict: options.strict === true,
120
- allowTruthDrift: options.allowTruthDrift === true,
121
- exitCode,
122
- errors,
123
- warnings,
124
- groups: groupCheckMessages(errors, warnings),
125
- raw: rawLines.filter(Boolean).join("\n").trim(),
126
- };
127
- }