oxe-cc 1.2.1 → 1.3.0

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 (276) hide show
  1. package/.cursor/commands/oxe-ask.md +2 -2
  2. package/.cursor/commands/oxe-capabilities.md +2 -2
  3. package/.cursor/commands/oxe-checkpoint.md +2 -2
  4. package/.cursor/commands/oxe-compact.md +2 -2
  5. package/.cursor/commands/oxe-dashboard.md +2 -2
  6. package/.cursor/commands/oxe-debug.md +2 -2
  7. package/.cursor/commands/oxe-discuss.md +2 -2
  8. package/.cursor/commands/oxe-execute.md +5 -2
  9. package/.cursor/commands/oxe-forensics.md +2 -2
  10. package/.cursor/commands/oxe-help.md +2 -2
  11. package/.cursor/commands/oxe-loop.md +2 -2
  12. package/.cursor/commands/oxe-milestone.md +2 -2
  13. package/.cursor/commands/oxe-next.md +2 -2
  14. package/.cursor/commands/oxe-obs.md +2 -2
  15. package/.cursor/commands/oxe-plan-agent.md +2 -2
  16. package/.cursor/commands/oxe-plan.md +2 -2
  17. package/.cursor/commands/oxe-project.md +2 -2
  18. package/.cursor/commands/oxe-quick.md +2 -2
  19. package/.cursor/commands/oxe-research.md +2 -2
  20. package/.cursor/commands/oxe-retro.md +2 -2
  21. package/.cursor/commands/oxe-review-pr.md +2 -2
  22. package/.cursor/commands/oxe-route.md +2 -2
  23. package/.cursor/commands/oxe-scan.md +2 -2
  24. package/.cursor/commands/oxe-security.md +2 -2
  25. package/.cursor/commands/oxe-session.md +2 -2
  26. package/.cursor/commands/oxe-ship.md +2 -2
  27. package/.cursor/commands/oxe-skill.md +2 -2
  28. package/.cursor/commands/oxe-spec.md +2 -2
  29. package/.cursor/commands/oxe-ui-review.md +2 -2
  30. package/.cursor/commands/oxe-ui-spec.md +2 -2
  31. package/.cursor/commands/oxe-update.md +2 -2
  32. package/.cursor/commands/oxe-validate-gaps.md +2 -2
  33. package/.cursor/commands/oxe-verify.md +5 -2
  34. package/.cursor/commands/oxe-workstream.md +2 -2
  35. package/.cursor/commands/oxe.md +2 -2
  36. package/.github/copilot-instructions.md +13 -13
  37. package/.github/prompts/oxe-ask.prompt.md +2 -2
  38. package/.github/prompts/oxe-capabilities.prompt.md +2 -2
  39. package/.github/prompts/oxe-checkpoint.prompt.md +2 -2
  40. package/.github/prompts/oxe-compact.prompt.md +2 -2
  41. package/.github/prompts/oxe-dashboard.prompt.md +2 -2
  42. package/.github/prompts/oxe-debug.prompt.md +2 -2
  43. package/.github/prompts/oxe-discuss.prompt.md +2 -2
  44. package/.github/prompts/oxe-execute.prompt.md +5 -2
  45. package/.github/prompts/oxe-forensics.prompt.md +2 -2
  46. package/.github/prompts/oxe-help.prompt.md +2 -2
  47. package/.github/prompts/oxe-loop.prompt.md +2 -2
  48. package/.github/prompts/oxe-milestone.prompt.md +2 -2
  49. package/.github/prompts/oxe-next.prompt.md +2 -2
  50. package/.github/prompts/oxe-obs.prompt.md +2 -2
  51. package/.github/prompts/oxe-plan-agent.prompt.md +2 -2
  52. package/.github/prompts/oxe-plan.prompt.md +2 -2
  53. package/.github/prompts/oxe-project.prompt.md +2 -2
  54. package/.github/prompts/oxe-quick.prompt.md +2 -2
  55. package/.github/prompts/oxe-research.prompt.md +2 -2
  56. package/.github/prompts/oxe-retro.prompt.md +2 -2
  57. package/.github/prompts/oxe-review-pr.prompt.md +2 -2
  58. package/.github/prompts/oxe-route.prompt.md +2 -2
  59. package/.github/prompts/oxe-scan.prompt.md +2 -2
  60. package/.github/prompts/oxe-security.prompt.md +2 -2
  61. package/.github/prompts/oxe-session.prompt.md +2 -2
  62. package/.github/prompts/oxe-ship.prompt.md +2 -2
  63. package/.github/prompts/oxe-skill.prompt.md +2 -2
  64. package/.github/prompts/oxe-spec.prompt.md +2 -2
  65. package/.github/prompts/oxe-ui-review.prompt.md +2 -2
  66. package/.github/prompts/oxe-ui-spec.prompt.md +2 -2
  67. package/.github/prompts/oxe-update.prompt.md +2 -2
  68. package/.github/prompts/oxe-validate-gaps.prompt.md +2 -2
  69. package/.github/prompts/oxe-verify.prompt.md +5 -2
  70. package/.github/prompts/oxe-workstream.prompt.md +2 -2
  71. package/.github/prompts/oxe.prompt.md +2 -2
  72. package/CHANGELOG.md +52 -17
  73. package/README.md +610 -551
  74. package/bin/banner.txt +1 -1
  75. package/bin/lib/oxe-agent-install.cjs +69 -69
  76. package/bin/lib/oxe-azure.cjs +1445 -1445
  77. package/bin/lib/oxe-context-engine.cjs +867 -867
  78. package/bin/lib/oxe-dashboard.cjs +76 -28
  79. package/bin/lib/oxe-operational.cjs +2144 -1340
  80. package/bin/lib/oxe-project-health.cjs +483 -1
  81. package/bin/lib/oxe-runtime-semantics.cjs +12 -0
  82. package/bin/oxe-cc.js +554 -152
  83. package/commands/oxe/ask.md +2 -2
  84. package/commands/oxe/capabilities.md +2 -2
  85. package/commands/oxe/checkpoint.md +2 -2
  86. package/commands/oxe/compact.md +2 -2
  87. package/commands/oxe/dashboard.md +2 -2
  88. package/commands/oxe/debug.md +2 -2
  89. package/commands/oxe/discuss.md +2 -2
  90. package/commands/oxe/execute.md +5 -2
  91. package/commands/oxe/forensics.md +2 -2
  92. package/commands/oxe/help.md +2 -2
  93. package/commands/oxe/loop.md +2 -2
  94. package/commands/oxe/milestone.md +2 -2
  95. package/commands/oxe/next.md +2 -2
  96. package/commands/oxe/obs.md +2 -2
  97. package/commands/oxe/oxe.md +2 -2
  98. package/commands/oxe/plan-agent.md +2 -2
  99. package/commands/oxe/plan.md +2 -2
  100. package/commands/oxe/project.md +2 -2
  101. package/commands/oxe/quick.md +2 -2
  102. package/commands/oxe/research.md +2 -2
  103. package/commands/oxe/retro.md +2 -2
  104. package/commands/oxe/review-pr.md +2 -2
  105. package/commands/oxe/route.md +2 -2
  106. package/commands/oxe/scan.md +2 -2
  107. package/commands/oxe/security.md +2 -2
  108. package/commands/oxe/session.md +2 -2
  109. package/commands/oxe/ship.md +2 -2
  110. package/commands/oxe/skill.md +2 -2
  111. package/commands/oxe/spec.md +2 -2
  112. package/commands/oxe/ui-review.md +2 -2
  113. package/commands/oxe/ui-spec.md +2 -2
  114. package/commands/oxe/update.md +2 -2
  115. package/commands/oxe/validate-gaps.md +2 -2
  116. package/commands/oxe/verify.md +5 -2
  117. package/commands/oxe/workstream.md +2 -2
  118. package/lib/runtime/delivery/branch-manager.d.ts +1 -0
  119. package/lib/runtime/delivery/branch-manager.js +7 -0
  120. package/lib/runtime/delivery/ci-checks.js +34 -1
  121. package/lib/runtime/delivery/delivery-records.d.ts +34 -0
  122. package/lib/runtime/delivery/delivery-records.js +48 -0
  123. package/lib/runtime/delivery/index.d.ts +1 -0
  124. package/lib/runtime/delivery/index.js +1 -0
  125. package/lib/runtime/delivery/promotion-pipeline.d.ts +26 -2
  126. package/lib/runtime/delivery/promotion-pipeline.js +111 -14
  127. package/lib/runtime/gate/gate-manager.d.ts +41 -0
  128. package/lib/runtime/gate/gate-manager.js +108 -1
  129. package/lib/runtime/index.d.ts +2 -2
  130. package/lib/runtime/index.js +3 -1
  131. package/lib/runtime/models/gate-decision.d.ts +4 -1
  132. package/lib/runtime/models/workspace.d.ts +3 -0
  133. package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
  134. package/lib/runtime/plugins/capability-adapter.js +204 -0
  135. package/lib/runtime/plugins/capability-matrix.d.ts +5 -0
  136. package/lib/runtime/plugins/capability-matrix.js +48 -17
  137. package/lib/runtime/plugins/index.d.ts +1 -0
  138. package/lib/runtime/plugins/index.js +1 -0
  139. package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
  140. package/lib/runtime/plugins/plugin-manifest.d.ts +1 -1
  141. package/lib/runtime/plugins/plugin-manifest.js +6 -2
  142. package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
  143. package/lib/runtime/plugins/plugin-registry.js +79 -2
  144. package/lib/runtime/policy/policy-engine.d.ts +19 -0
  145. package/lib/runtime/policy/policy-engine.js +76 -4
  146. package/lib/runtime/projection/projection-engine.d.ts +9 -1
  147. package/lib/runtime/projection/projection-engine.js +73 -3
  148. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +43 -1
  149. package/lib/runtime/scheduler/multi-agent-coordinator.js +151 -39
  150. package/lib/runtime/scheduler/run-journal.d.ts +1 -1
  151. package/lib/runtime/scheduler/scheduler.d.ts +19 -1
  152. package/lib/runtime/scheduler/scheduler.js +258 -13
  153. package/lib/runtime/verification/verification-compiler.d.ts +43 -0
  154. package/lib/runtime/verification/verification-compiler.js +137 -0
  155. package/lib/runtime/verification/verification-manifest.d.ts +9 -0
  156. package/lib/runtime/verification/verification-manifest.js +56 -6
  157. package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
  158. package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
  159. package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
  160. package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
  161. package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
  162. package/lib/runtime/workspace/strategies/inplace.js +2 -0
  163. package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
  164. package/lib/sdk/README.md +9 -9
  165. package/lib/sdk/index.cjs +33 -24
  166. package/lib/sdk/index.d.ts +149 -14
  167. package/oxe/templates/ACTIVE-RUN.template.json +32 -32
  168. package/oxe/templates/CAPABILITIES.template.md +7 -7
  169. package/oxe/templates/CAPABILITY.template.md +45 -45
  170. package/oxe/templates/CHECKPOINTS.template.md +7 -7
  171. package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
  172. package/oxe/templates/HYPOTHESES.template.md +33 -33
  173. package/oxe/templates/LESSONS-METRICS.template.json +13 -13
  174. package/oxe/templates/NOTES.template.md +16 -16
  175. package/oxe/templates/PLAN-REVIEW.template.md +31 -31
  176. package/oxe/templates/SESSION.template.md +34 -34
  177. package/oxe/templates/SKILL.template.md +26 -26
  178. package/oxe/templates/STATE.md +55 -55
  179. package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
  180. package/oxe/workflows/ask.md +96 -96
  181. package/oxe/workflows/capabilities.md +25 -25
  182. package/oxe/workflows/dashboard.md +33 -33
  183. package/oxe/workflows/discuss.md +12 -12
  184. package/oxe/workflows/execute.md +14 -0
  185. package/oxe/workflows/help.md +352 -352
  186. package/oxe/workflows/next.md +22 -22
  187. package/oxe/workflows/oxe.md +6 -6
  188. package/oxe/workflows/plan-agent.md +9 -9
  189. package/oxe/workflows/quick.md +10 -10
  190. package/oxe/workflows/references/reasoning-discovery.md +28 -28
  191. package/oxe/workflows/references/reasoning-execution.md +29 -29
  192. package/oxe/workflows/references/reasoning-planning.md +32 -32
  193. package/oxe/workflows/references/reasoning-review.md +29 -29
  194. package/oxe/workflows/references/reasoning-status.md +24 -24
  195. package/oxe/workflows/references/robustness-elevation.md +295 -295
  196. package/oxe/workflows/references/workflow-runtime-contracts.json +952 -930
  197. package/oxe/workflows/route.md +16 -16
  198. package/oxe/workflows/session.md +213 -213
  199. package/oxe/workflows/ship.md +142 -142
  200. package/oxe/workflows/skill.md +44 -44
  201. package/oxe/workflows/ui-review.md +36 -36
  202. package/oxe/workflows/verify-audit.md +73 -73
  203. package/oxe/workflows/verify.md +10 -0
  204. package/package.json +92 -92
  205. package/packages/runtime/package.json +17 -17
  206. package/packages/runtime/src/audit/audit-trail.ts +243 -243
  207. package/packages/runtime/src/audit/index.ts +2 -2
  208. package/packages/runtime/src/audit/policy-pack.ts +62 -62
  209. package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
  210. package/packages/runtime/src/compiler/index.ts +1 -1
  211. package/packages/runtime/src/context/context-pack-builder.ts +259 -259
  212. package/packages/runtime/src/context/context-pack-store.ts +197 -197
  213. package/packages/runtime/src/context/context-profiles.ts +60 -60
  214. package/packages/runtime/src/context/index.ts +3 -3
  215. package/packages/runtime/src/decision/decision-engine.ts +174 -174
  216. package/packages/runtime/src/decision/decision-memo.ts +211 -211
  217. package/packages/runtime/src/decision/index.ts +2 -2
  218. package/packages/runtime/src/delivery/branch-manager.ts +91 -84
  219. package/packages/runtime/src/delivery/ci-checks.ts +285 -252
  220. package/packages/runtime/src/delivery/delivery-records.ts +75 -0
  221. package/packages/runtime/src/delivery/index.ts +5 -4
  222. package/packages/runtime/src/delivery/pr-manager.ts +112 -112
  223. package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -180
  224. package/packages/runtime/src/events/bus.ts +92 -92
  225. package/packages/runtime/src/events/catalog.ts +29 -29
  226. package/packages/runtime/src/events/envelope.ts +14 -14
  227. package/packages/runtime/src/events/index.ts +3 -3
  228. package/packages/runtime/src/evidence/evidence-store.ts +130 -130
  229. package/packages/runtime/src/evidence/index.ts +1 -1
  230. package/packages/runtime/src/gate/gate-manager.ts +289 -137
  231. package/packages/runtime/src/gate/index.ts +1 -1
  232. package/packages/runtime/src/index.ts +41 -37
  233. package/packages/runtime/src/models/attempt.ts +19 -19
  234. package/packages/runtime/src/models/evidence.ts +21 -21
  235. package/packages/runtime/src/models/gate-decision.ts +25 -21
  236. package/packages/runtime/src/models/index.ts +8 -8
  237. package/packages/runtime/src/models/run.ts +24 -24
  238. package/packages/runtime/src/models/session.ts +11 -11
  239. package/packages/runtime/src/models/verification-result.ts +10 -10
  240. package/packages/runtime/src/models/work-item.ts +25 -25
  241. package/packages/runtime/src/models/workspace.ts +31 -28
  242. package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
  243. package/packages/runtime/src/plugins/capability-matrix.ts +126 -83
  244. package/packages/runtime/src/plugins/index.ts +5 -4
  245. package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
  246. package/packages/runtime/src/plugins/plugin-manifest.ts +118 -113
  247. package/packages/runtime/src/plugins/plugin-registry.ts +232 -124
  248. package/packages/runtime/src/policy/index.ts +1 -1
  249. package/packages/runtime/src/policy/policy-engine.ts +330 -244
  250. package/packages/runtime/src/projection/index.ts +1 -1
  251. package/packages/runtime/src/projection/projection-engine.ts +328 -249
  252. package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
  253. package/packages/runtime/src/reducers/index.ts +2 -2
  254. package/packages/runtime/src/reducers/run-state-reducer.ts +269 -269
  255. package/packages/runtime/src/scheduler/agent-registry.ts +132 -132
  256. package/packages/runtime/src/scheduler/agent-roles.ts +109 -109
  257. package/packages/runtime/src/scheduler/index.ts +4 -4
  258. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -333
  259. package/packages/runtime/src/scheduler/run-journal.ts +62 -62
  260. package/packages/runtime/src/scheduler/scheduler.ts +722 -441
  261. package/packages/runtime/src/verification/index.ts +2 -2
  262. package/packages/runtime/src/verification/verification-compiler.ts +436 -225
  263. package/packages/runtime/src/verification/verification-manifest.ts +252 -192
  264. package/packages/runtime/src/workspace/index.ts +5 -5
  265. package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
  266. package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
  267. package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
  268. package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
  269. package/packages/runtime/tsconfig.json +17 -17
  270. package/vscode-extension/.vscodeignore +7 -7
  271. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  272. package/vscode-extension/package.json +185 -185
  273. package/vscode-extension/src/extension.js +310 -310
  274. package/vscode-extension/src/shared/contextLoader.js +137 -137
  275. package/vscode-extension/src/shared/contractBuilder.js +159 -159
  276. package/vscode-extension/src/shared/stateReader.js +101 -101
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Scheduler = void 0;
4
4
  const bus_1 = require("../events/bus");
5
+ const policy_engine_1 = require("../policy/policy-engine");
6
+ const audit_trail_1 = require("../audit/audit-trail");
5
7
  const run_journal_1 = require("./run-journal");
6
8
  class Scheduler {
7
9
  constructor() {
@@ -23,6 +25,10 @@ class Scheduler {
23
25
  this.journal = (0, run_journal_1.createJournal)(ctx.runId);
24
26
  (0, run_journal_1.saveJournal)(ctx.projectRoot, ctx.runId, this.journal);
25
27
  this.emit(ctx, { type: 'RunStarted', payload: { run_id: ctx.runId } });
28
+ ctx.auditTrail?.record('run_started', ctx.policyActor ?? 'runtime', {
29
+ runId: ctx.runId,
30
+ detail: { session_id: ctx.sessionId ?? null },
31
+ });
26
32
  for (const wave of graph.waves) {
27
33
  if (this.cancelled)
28
34
  break;
@@ -35,7 +41,11 @@ class Scheduler {
35
41
  this.journal.blocked_work_items = blocked.slice();
36
42
  this.journal.partial_result = { run_id: ctx.runId, completed, failed, blocked };
37
43
  (0, run_journal_1.saveJournal)(ctx.projectRoot, ctx.runId, this.journal);
38
- return { run_id: ctx.runId, status: 'paused', completed, failed, blocked };
44
+ ctx.auditTrail?.record('run_paused', ctx.policyActor ?? 'runtime', {
45
+ runId: ctx.runId,
46
+ detail: { completed, failed, blocked },
47
+ });
48
+ return { run_id: ctx.runId, status: 'paused', completed, failed, blocked, pending_gates: this.journal.pending_gates.slice() };
39
49
  }
40
50
  const waveFailed = await this.runWave(wave.node_ids, graph, ctx, status, completed, failed, blocked);
41
51
  // Sync journal after each wave
@@ -62,17 +72,36 @@ class Scheduler {
62
72
  ? 'cancelled'
63
73
  : failed.length > 0
64
74
  ? 'failed'
65
- : 'completed';
75
+ : blocked.length > 0
76
+ ? 'blocked'
77
+ : 'completed';
66
78
  this.emit(ctx, {
67
79
  type: 'RunCompleted',
68
80
  payload: { run_id: ctx.runId, status: finalStatus },
69
81
  });
70
- this.journal.scheduler_state = this.cancelled ? 'cancelled' : 'completed';
82
+ ctx.auditTrail?.record('run_completed', ctx.policyActor ?? 'runtime', {
83
+ runId: ctx.runId,
84
+ detail: {
85
+ status: finalStatus,
86
+ completed: completed.length,
87
+ failed: failed.length,
88
+ blocked: blocked.length,
89
+ pending_gates: this.journal.pending_gates.slice(),
90
+ },
91
+ });
92
+ this.journal.scheduler_state = this.cancelled ? 'cancelled' : finalStatus === 'blocked' ? 'blocked' : 'completed';
71
93
  this.journal.completed_work_items = completed.slice();
72
94
  this.journal.failed_work_items = failed.slice();
73
95
  this.journal.blocked_work_items = blocked.slice();
74
96
  (0, run_journal_1.saveJournal)(ctx.projectRoot, ctx.runId, this.journal);
75
- return { run_id: ctx.runId, status: finalStatus, completed, failed, blocked };
97
+ return {
98
+ run_id: ctx.runId,
99
+ status: finalStatus,
100
+ completed,
101
+ failed,
102
+ blocked,
103
+ pending_gates: this.journal.pending_gates.slice(),
104
+ };
76
105
  }
77
106
  /**
78
107
  * Recover a previously paused run by loading its journal and re-running
@@ -117,7 +146,11 @@ class Scheduler {
117
146
  this.journal.blocked_work_items = blocked.slice();
118
147
  this.journal.partial_result = { run_id: ctx.runId, completed, failed, blocked };
119
148
  (0, run_journal_1.saveJournal)(ctx.projectRoot, ctx.runId, this.journal);
120
- return { run_id: ctx.runId, status: 'paused', completed, failed, blocked };
149
+ ctx.auditTrail?.record('run_paused', ctx.policyActor ?? 'runtime', {
150
+ runId: ctx.runId,
151
+ detail: { recovered: true, completed, failed, blocked },
152
+ });
153
+ return { run_id: ctx.runId, status: 'paused', completed, failed, blocked, pending_gates: this.journal.pending_gates.slice() };
121
154
  }
122
155
  // Skip waves fully completed
123
156
  const allDone = wave.node_ids.every((id) => restoredCompleted.has(id) || restoredFailed.has(id) || restoredBlocked.has(id));
@@ -146,18 +179,37 @@ class Scheduler {
146
179
  ? 'cancelled'
147
180
  : failed.length > 0
148
181
  ? 'failed'
149
- : 'completed';
182
+ : blocked.length > 0
183
+ ? 'blocked'
184
+ : 'completed';
150
185
  this.emit(ctx, {
151
186
  type: 'RunCompleted',
152
187
  payload: { run_id: ctx.runId, status: finalStatus, recovered: true },
153
188
  });
154
- this.journal.scheduler_state = this.cancelled ? 'cancelled' : 'completed';
189
+ ctx.auditTrail?.record('run_recovered', ctx.policyActor ?? 'runtime', {
190
+ runId: ctx.runId,
191
+ detail: {
192
+ status: finalStatus,
193
+ completed: completed.length,
194
+ failed: failed.length,
195
+ blocked: blocked.length,
196
+ pending_gates: this.journal.pending_gates.slice(),
197
+ },
198
+ });
199
+ this.journal.scheduler_state = this.cancelled ? 'cancelled' : finalStatus === 'blocked' ? 'blocked' : 'completed';
155
200
  this.journal.completed_work_items = completed.slice();
156
201
  this.journal.failed_work_items = failed.slice();
157
202
  this.journal.blocked_work_items = blocked.slice();
158
203
  (0, run_journal_1.saveJournal)(ctx.projectRoot, ctx.runId, this.journal);
159
204
  (0, run_journal_1.deleteJournal)(ctx.projectRoot, ctx.runId);
160
- return { run_id: ctx.runId, status: finalStatus, completed, failed, blocked };
205
+ return {
206
+ run_id: ctx.runId,
207
+ status: finalStatus,
208
+ completed,
209
+ failed,
210
+ blocked,
211
+ pending_gates: this.journal.pending_gates.slice(),
212
+ };
161
213
  }
162
214
  async runWave(nodeIds, graph, ctx, status, completed, failed, blocked) {
163
215
  const eligible = [];
@@ -189,16 +241,16 @@ class Scheduler {
189
241
  });
190
242
  const mutations = eligible.filter((id) => !readOnly.includes(id));
191
243
  if (readOnly.length > 0) {
192
- await Promise.all(readOnly.map((id) => this.runNode(id, graph, ctx, status, completed, failed)));
244
+ await Promise.all(readOnly.map((id) => this.runNode(id, graph, ctx, status, completed, failed, blocked)));
193
245
  }
194
246
  for (const id of mutations) {
195
247
  if (this.cancelled)
196
248
  break;
197
- await this.runNode(id, graph, ctx, status, completed, failed);
249
+ await this.runNode(id, graph, ctx, status, completed, failed, blocked);
198
250
  }
199
251
  return failed.length > 0;
200
252
  }
201
- async runNode(nodeId, graph, ctx, status, completed, failed) {
253
+ async runNode(nodeId, graph, ctx, status, completed, failed, blocked) {
202
254
  const node = graph.nodes.get(nodeId);
203
255
  status.set(nodeId, 'running');
204
256
  this.emit(ctx, {
@@ -209,6 +261,11 @@ class Scheduler {
209
261
  let lease = null;
210
262
  let lastResult = null;
211
263
  const maxAttempts = node.policy.max_retries + 1;
264
+ const quotaBlocked = this.consumeQuotaForNode(ctx, node);
265
+ if (quotaBlocked) {
266
+ this.blockNode(nodeId, ctx, status, blocked, 'quota_exceeded', quotaBlocked);
267
+ return;
268
+ }
212
269
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
213
270
  const attemptId = `${nodeId}-a${attempt}`;
214
271
  this.emit(ctx, {
@@ -218,20 +275,50 @@ class Scheduler {
218
275
  payload: { attempt_number: attempt },
219
276
  });
220
277
  try {
278
+ const policyDecision = this.evaluatePolicyForNode(node, ctx);
279
+ if (policyDecision && !policyDecision.allowed) {
280
+ this.emit(ctx, {
281
+ type: 'PolicyEvaluated',
282
+ work_item_id: nodeId,
283
+ attempt_id: attemptId,
284
+ payload: { ...policyDecision },
285
+ });
286
+ ctx.auditTrail?.record('policy_denied', ctx.policyActor ?? 'runtime', {
287
+ runId: ctx.runId,
288
+ workItemId: nodeId,
289
+ detail: { reason: policyDecision.reason, rule_id: policyDecision.rule_id },
290
+ });
291
+ this.blockNode(nodeId, ctx, status, blocked, 'policy_denied', policyDecision.reason);
292
+ return;
293
+ }
294
+ if (policyDecision) {
295
+ this.emit(ctx, {
296
+ type: 'PolicyEvaluated',
297
+ work_item_id: nodeId,
298
+ attempt_id: attemptId,
299
+ payload: { ...policyDecision },
300
+ });
301
+ }
302
+ if (policyDecision?.gate_required || node.policy.requires_human_approval) {
303
+ const gateId = await this.requestGateForNode(node, ctx, policyDecision);
304
+ this.blockNode(nodeId, ctx, status, blocked, 'pending_gate', gateId);
305
+ return;
306
+ }
221
307
  const wsReq = {
222
308
  work_item_id: nodeId,
223
309
  attempt_number: attempt,
224
310
  strategy: node.workspace_strategy,
225
311
  mutation_scope: node.mutation_scope,
226
312
  };
227
- lease = await ctx.workspaceManager.allocate(wsReq);
313
+ const workspaceManager = ctx.pluginRegistry?.workspaceProviderFor(node.workspace_strategy) ?? ctx.workspaceManager;
314
+ lease = await workspaceManager.allocate(wsReq);
228
315
  this.emit(ctx, {
229
316
  type: 'WorkspaceAllocated',
230
317
  work_item_id: nodeId,
231
318
  attempt_id: attemptId,
232
319
  payload: { workspace_id: lease.workspace_id, strategy: lease.strategy },
233
320
  });
234
- lastResult = await ctx.executor.execute(node, lease, ctx.runId, attempt);
321
+ lastResult = await this.executeNode(node, lease, ctx, attempt, attemptId);
235
322
  if (lastResult.success) {
236
323
  this.emit(ctx, {
237
324
  type: 'WorkItemCompleted',
@@ -246,6 +333,11 @@ class Scheduler {
246
333
  if (lastResult.failure_class === 'policy')
247
334
  break;
248
335
  if (attempt < maxAttempts) {
336
+ const retryBlocked = this.consumeRetryQuota(ctx);
337
+ if (retryBlocked) {
338
+ this.blockNode(nodeId, ctx, status, blocked, 'quota_exceeded', retryBlocked);
339
+ return;
340
+ }
249
341
  this.emit(ctx, {
250
342
  type: 'RetryScheduled',
251
343
  work_item_id: nodeId,
@@ -313,6 +405,136 @@ class Scheduler {
313
405
  static loadJournal(projectRoot, runId) {
314
406
  return (0, run_journal_1.loadJournal)(projectRoot, runId);
315
407
  }
408
+ async executeNode(node, lease, ctx, attempt, attemptId) {
409
+ const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
410
+ const provider = primaryAction ? ctx.pluginRegistry?.toolProviderFor(primaryAction.type) : null;
411
+ if (!provider || !primaryAction) {
412
+ return ctx.executor.execute(node, lease, ctx.runId, attempt);
413
+ }
414
+ ctx.auditTrail?.record('plugin_invoked', ctx.policyActor ?? 'runtime', {
415
+ runId: ctx.runId,
416
+ workItemId: node.id,
417
+ resource: provider.name,
418
+ detail: { action_type: primaryAction.type, attempt_id: attemptId },
419
+ });
420
+ this.emit(ctx, {
421
+ type: 'ToolInvoked',
422
+ work_item_id: node.id,
423
+ attempt_id: attemptId,
424
+ payload: { provider: provider.name, action_type: primaryAction.type },
425
+ });
426
+ const result = await provider.invoke({
427
+ action_type: primaryAction.type,
428
+ work_item_id: node.id,
429
+ run_id: ctx.runId,
430
+ attempt_id: attemptId,
431
+ params: {
432
+ command: primaryAction.command ?? null,
433
+ targets: primaryAction.targets ?? [],
434
+ },
435
+ workspace_root: lease.root_path,
436
+ });
437
+ this.emit(ctx, {
438
+ type: result.success ? 'ToolCompleted' : 'ToolFailed',
439
+ work_item_id: node.id,
440
+ attempt_id: attemptId,
441
+ payload: {
442
+ provider: provider.name,
443
+ action_type: primaryAction.type,
444
+ evidence_paths: result.evidence_paths,
445
+ side_effects_applied: result.side_effects_applied,
446
+ error: result.error ?? null,
447
+ },
448
+ });
449
+ return {
450
+ success: result.success,
451
+ failure_class: result.success ? null : provider.kind === 'external_operation' ? 'policy' : 'env',
452
+ evidence: result.evidence_paths,
453
+ output: result.output,
454
+ };
455
+ }
456
+ evaluatePolicyForNode(node, ctx) {
457
+ if (!ctx.policyEngine)
458
+ return null;
459
+ const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
460
+ const decisionContext = {
461
+ tool: primaryAction?.type ?? 'custom',
462
+ kind: node.workspace_strategy,
463
+ mutation_scope: node.mutation_scope,
464
+ affected_paths: node.mutation_scope,
465
+ side_effect_class: inferSideEffectClass(node),
466
+ mutation_count: node.mutation_scope.length,
467
+ node_policy: {
468
+ max_retries: node.policy.max_retries,
469
+ },
470
+ };
471
+ const evaluated = ctx.policyEngine.evaluate(decisionContext);
472
+ const persisted = {
473
+ ...evaluated,
474
+ run_id: ctx.runId,
475
+ work_item_id: node.id,
476
+ action: primaryAction?.type ?? 'custom',
477
+ actor: ctx.policyActor ?? 'runtime',
478
+ override: false,
479
+ rationale: null,
480
+ context: decisionContext,
481
+ };
482
+ (0, policy_engine_1.savePolicyDecision)(ctx.projectRoot, persisted);
483
+ return persisted;
484
+ }
485
+ async requestGateForNode(node, ctx, decision) {
486
+ if (!ctx.gateManager)
487
+ return 'gate-missing-manager';
488
+ const scope = inferGateScope(node);
489
+ const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
490
+ const gate = await ctx.gateManager.request(scope, {
491
+ run_id: ctx.runId,
492
+ work_item_id: node.id,
493
+ action: primaryAction?.type ?? 'custom',
494
+ description: `Gate required before executing ${node.id}`,
495
+ evidence_refs: [],
496
+ risks: [decision?.reason ?? 'human approval required'],
497
+ rationale: decision?.reason ?? 'node policy requires approval',
498
+ policy_decision_id: decision?.decision_id ?? null,
499
+ });
500
+ if (this.journal && !this.journal.pending_gates.includes(gate.gate_id)) {
501
+ this.journal.pending_gates.push(gate.gate_id);
502
+ }
503
+ ctx.auditTrail?.record('gate_requested', ctx.policyActor ?? 'runtime', {
504
+ runId: ctx.runId,
505
+ workItemId: node.id,
506
+ detail: { gate_id: gate.gate_id, scope: gate.scope, action: gate.action },
507
+ });
508
+ return gate.gate_id;
509
+ }
510
+ blockNode(nodeId, ctx, status, blocked, reason, detail = null) {
511
+ this.emit(ctx, {
512
+ type: 'WorkItemBlocked',
513
+ work_item_id: nodeId,
514
+ payload: { reason, detail },
515
+ });
516
+ status.set(nodeId, 'blocked');
517
+ if (!blocked.includes(nodeId))
518
+ blocked.push(nodeId);
519
+ }
520
+ consumeQuotaForNode(ctx, node) {
521
+ if (!ctx.quota)
522
+ return null;
523
+ let quota = (0, audit_trail_1.consumeQuota)(ctx.quota, 'work_items', 1);
524
+ if (node.mutation_scope.length > 0) {
525
+ quota = (0, audit_trail_1.consumeQuota)(quota, 'mutations', 1);
526
+ }
527
+ const violation = (0, audit_trail_1.checkQuota)(quota);
528
+ ctx.quota = quota;
529
+ return violation ? `${violation.quota_type}:${violation.consumed}/${violation.limit}` : null;
530
+ }
531
+ consumeRetryQuota(ctx) {
532
+ if (!ctx.quota)
533
+ return null;
534
+ ctx.quota = (0, audit_trail_1.consumeQuota)(ctx.quota, 'retries', 1);
535
+ const violation = (0, audit_trail_1.checkQuota)(ctx.quota);
536
+ return violation ? `${violation.quota_type}:${violation.consumed}/${violation.limit}` : null;
537
+ }
316
538
  emit(ctx, input) {
317
539
  const event = (0, bus_1.appendEvent)(ctx.projectRoot, ctx.sessionId, {
318
540
  run_id: ctx.runId,
@@ -322,3 +544,26 @@ class Scheduler {
322
544
  }
323
545
  }
324
546
  exports.Scheduler = Scheduler;
547
+ function inferSideEffectClass(node) {
548
+ if (node.mutation_scope.length > 0)
549
+ return 'write_fs';
550
+ if (node.actions.some((action) => action.type === 'run_tests' || action.type === 'run_lint'))
551
+ return 'spawn_process';
552
+ return 'read_fs';
553
+ }
554
+ function pickPrimaryAction(node, pluginRegistry) {
555
+ const candidateActions = node.actions.filter((action) => action.type !== 'collect_evidence');
556
+ const preferredMutation = candidateActions.find((action) => action.type === 'generate_patch')
557
+ || candidateActions.find((action) => action.type === 'run_tests')
558
+ || candidateActions[0];
559
+ if (!pluginRegistry)
560
+ return preferredMutation;
561
+ return candidateActions.find((action) => pluginRegistry.toolProviderFor(action.type)) || preferredMutation;
562
+ }
563
+ function inferGateScope(node) {
564
+ if (node.mutation_scope.length > 0)
565
+ return 'critical_mutation';
566
+ if (node.actions.some((action) => action.type === 'collect_evidence'))
567
+ return 'security';
568
+ return 'plan_approval';
569
+ }
@@ -1,5 +1,9 @@
1
1
  import type { EvidenceType } from '../models/evidence';
2
2
  import type { VerificationStatus } from '../models/verification-result';
3
+ import type { VerificationResult } from '../models/verification-result';
4
+ import type { EvidenceStore } from '../evidence/evidence-store';
5
+ import type { PluginRegistry } from '../plugins/plugin-registry';
6
+ import { type EvidenceCoverageSummary, type ResidualRiskLedger, type VerificationManifest } from './verification-manifest';
3
7
  export type CheckType = 'unit' | 'integration' | 'contract' | 'smoke' | 'policy' | 'security' | 'ux_snapshot' | 'performance_baseline' | 'custom';
4
8
  export interface AcceptanceCheck {
5
9
  id: string;
@@ -24,6 +28,26 @@ export interface CheckResult {
24
28
  exit_code: number | null;
25
29
  duration_ms: number;
26
30
  error: string | null;
31
+ evidence_refs?: string[];
32
+ }
33
+ export interface ExecutedVerificationSuite {
34
+ results: CheckResult[];
35
+ verification_results: VerificationResult[];
36
+ evidence_refs: Map<string, string[]>;
37
+ manifest: VerificationManifest;
38
+ risk_ledger: ResidualRiskLedger;
39
+ evidence_coverage: EvidenceCoverageSummary;
40
+ }
41
+ export interface VerifyRunResult {
42
+ status: 'passed' | 'failed' | 'partial';
43
+ suite: AcceptanceCheckSuite;
44
+ executed: ExecutedVerificationSuite | null;
45
+ gaps: string[];
46
+ verification_results: VerificationResult[];
47
+ check_results: CheckResult[];
48
+ manifest: VerificationManifest | null;
49
+ risk_ledger: ResidualRiskLedger | null;
50
+ evidence_coverage: EvidenceCoverageSummary | null;
27
51
  }
28
52
  interface Criterion {
29
53
  id: string;
@@ -45,6 +69,14 @@ interface ParsedPlanLike {
45
69
  export declare function compile(spec: ParsedSpecLike, plan: ParsedPlanLike): AcceptanceCheckSuite;
46
70
  export declare function runCheck(check: AcceptanceCheck, cwd: string, timeoutMs?: number): Promise<CheckResult>;
47
71
  export declare function runSuite(suite: AcceptanceCheckSuite, cwd: string, timeoutMs?: number): Promise<CheckResult[]>;
72
+ export declare function executeSuite(suite: AcceptanceCheckSuite, cwd: string, options: {
73
+ timeoutMs?: number;
74
+ runId: string;
75
+ workItemId: string;
76
+ attemptNumber?: number;
77
+ evidenceStore?: EvidenceStore;
78
+ pluginRegistry?: PluginRegistry;
79
+ }): Promise<ExecutedVerificationSuite>;
48
80
  export declare function summarizeSuite(results: CheckResult[]): {
49
81
  total: number;
50
82
  pass: number;
@@ -53,4 +85,15 @@ export declare function summarizeSuite(results: CheckResult[]): {
53
85
  error: number;
54
86
  allPassed: boolean;
55
87
  };
88
+ export declare function verifyRun(input: {
89
+ projectRoot: string;
90
+ runId: string;
91
+ workItemId: string;
92
+ cwd: string;
93
+ suite: AcceptanceCheckSuite;
94
+ pluginRegistry?: PluginRegistry;
95
+ evidenceStore?: EvidenceStore;
96
+ attemptNumber?: number;
97
+ timeoutMs?: number;
98
+ }): Promise<VerifyRunResult>;
56
99
  export {};
@@ -6,9 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.compile = compile;
7
7
  exports.runCheck = runCheck;
8
8
  exports.runSuite = runSuite;
9
+ exports.executeSuite = executeSuite;
9
10
  exports.summarizeSuite = summarizeSuite;
11
+ exports.verifyRun = verifyRun;
10
12
  const crypto_1 = __importDefault(require("crypto"));
11
13
  const child_process_1 = require("child_process");
14
+ const verification_manifest_1 = require("./verification-manifest");
12
15
  function inferCheckType(howToVerify) {
13
16
  const v = howToVerify.toLowerCase();
14
17
  if (v.includes('npm test') || v.includes('jest') || v.includes('vitest') || v.includes('node --test'))
@@ -132,12 +135,125 @@ async function runSuite(suite, cwd, timeoutMs = 60000) {
132
135
  }
133
136
  return results;
134
137
  }
138
+ async function executeSuite(suite, cwd, options) {
139
+ const results = [];
140
+ const verificationResults = [];
141
+ const evidenceRefs = new Map();
142
+ const timeoutMs = options.timeoutMs ?? 60000;
143
+ const attemptNumber = options.attemptNumber ?? 1;
144
+ for (const check of suite.checks) {
145
+ const provider = options.pluginRegistry?.verifierProviderFor(check.type);
146
+ let result;
147
+ let verificationResult;
148
+ if (provider) {
149
+ const providerResult = await provider.execute({
150
+ check_id: check.id,
151
+ check_type: check.type,
152
+ command: check.command,
153
+ work_item_id: options.workItemId,
154
+ workspace_root: cwd,
155
+ evidence_dir: '',
156
+ });
157
+ result = {
158
+ check_id: check.id,
159
+ acceptance_ref: check.acceptance_ref,
160
+ status: providerResult.status,
161
+ stdout: providerResult.summary ?? '',
162
+ stderr: '',
163
+ exit_code: providerResult.status === 'pass' ? 0 : 1,
164
+ duration_ms: 0,
165
+ error: providerResult.status === 'error' ? providerResult.summary ?? 'provider error' : null,
166
+ evidence_refs: providerResult.evidence_refs,
167
+ };
168
+ verificationResult = providerResult;
169
+ }
170
+ else {
171
+ result = await runCheck(check, cwd, timeoutMs);
172
+ const collectedEvidence = options.evidenceStore
173
+ ? await collectCheckEvidence(options.evidenceStore, check, result, {
174
+ run_id: options.runId,
175
+ work_item_id: options.workItemId,
176
+ attempt_number: attemptNumber,
177
+ })
178
+ : [];
179
+ result.evidence_refs = collectedEvidence;
180
+ verificationResult = {
181
+ verification_id: `vr-${crypto_1.default.randomBytes(4).toString('hex')}`,
182
+ work_item_id: options.workItemId,
183
+ check_id: check.id,
184
+ status: result.status,
185
+ evidence_refs: collectedEvidence,
186
+ summary: result.error || result.stderr || result.stdout || null,
187
+ };
188
+ }
189
+ if (result.evidence_refs && result.evidence_refs.length > 0) {
190
+ evidenceRefs.set(check.id, result.evidence_refs);
191
+ }
192
+ results.push(result);
193
+ verificationResults.push(verificationResult);
194
+ }
195
+ const manifest = (0, verification_manifest_1.buildManifest)(options.runId, results, {
196
+ workItemId: options.workItemId,
197
+ granularity: 'work_item',
198
+ evidenceRefs,
199
+ });
200
+ const riskLedger = (0, verification_manifest_1.buildRiskLedger)(options.runId, manifest);
201
+ const evidenceCoverage = (0, verification_manifest_1.summarizeEvidenceCoverage)(manifest);
202
+ return {
203
+ results,
204
+ verification_results: verificationResults,
205
+ evidence_refs: evidenceRefs,
206
+ manifest,
207
+ risk_ledger: riskLedger,
208
+ evidence_coverage: evidenceCoverage,
209
+ };
210
+ }
135
211
  function summarizeSuite(results) {
136
212
  const counts = { total: results.length, pass: 0, fail: 0, skip: 0, error: 0 };
137
213
  for (const r of results)
138
214
  counts[r.status]++;
139
215
  return { ...counts, allPassed: counts.fail === 0 && counts.error === 0 };
140
216
  }
217
+ async function verifyRun(input) {
218
+ const gaps = [];
219
+ if (!input.suite || !Array.isArray(input.suite.checks) || input.suite.checks.length === 0) {
220
+ gaps.push('Nenhum check executável foi compilado a partir de SPEC/PLAN.');
221
+ return {
222
+ status: 'partial',
223
+ suite: input.suite,
224
+ executed: null,
225
+ gaps,
226
+ verification_results: [],
227
+ check_results: [],
228
+ manifest: null,
229
+ risk_ledger: null,
230
+ evidence_coverage: null,
231
+ };
232
+ }
233
+ const executed = await executeSuite(input.suite, input.cwd, {
234
+ timeoutMs: input.timeoutMs,
235
+ runId: input.runId,
236
+ workItemId: input.workItemId,
237
+ attemptNumber: input.attemptNumber,
238
+ evidenceStore: input.evidenceStore,
239
+ pluginRegistry: input.pluginRegistry,
240
+ });
241
+ (0, verification_manifest_1.saveManifest)(input.projectRoot, input.runId, executed.manifest);
242
+ (0, verification_manifest_1.saveRiskLedger)(input.projectRoot, input.runId, executed.risk_ledger);
243
+ (0, verification_manifest_1.saveEvidenceCoverage)(input.projectRoot, input.runId, executed.evidence_coverage);
244
+ const summary = summarizeSuite(executed.results);
245
+ return {
246
+ status: summary.total === 0 ? 'partial' : summary.allPassed ? 'passed' : 'failed',
247
+ suite: input.suite,
248
+ executed,
249
+ gaps,
250
+ verification_results: executed.verification_results,
251
+ check_results: executed.results,
252
+ manifest: executed.manifest,
253
+ risk_ledger: executed.risk_ledger,
254
+ evidence_coverage: executed.evidence_coverage,
255
+ };
256
+ }
141
257
  function hashObject(obj) {
142
258
  return crypto_1.default
143
259
  .createHash('sha256')
@@ -145,3 +261,24 @@ function hashObject(obj) {
145
261
  .digest('hex')
146
262
  .slice(0, 12);
147
263
  }
264
+ async function collectCheckEvidence(store, check, result, options) {
265
+ const refs = [];
266
+ if (result.stdout) {
267
+ const evidence = await store.collect('stdout', result.stdout, options);
268
+ refs.push(evidence.evidence_id);
269
+ }
270
+ if (result.stderr) {
271
+ const evidence = await store.collect('stderr', result.stderr, options);
272
+ refs.push(evidence.evidence_id);
273
+ }
274
+ const summaryEvidence = await store.collect(check.evidence_type_expected, JSON.stringify({
275
+ check_id: check.id,
276
+ type: check.type,
277
+ command: check.command,
278
+ status: result.status,
279
+ exit_code: result.exit_code,
280
+ duration_ms: result.duration_ms,
281
+ }, null, 2), options);
282
+ refs.push(summaryEvidence.evidence_id);
283
+ return refs;
284
+ }
@@ -43,6 +43,12 @@ export interface ResidualRiskLedger {
43
43
  generated_at: string;
44
44
  risks: ResidualRisk[];
45
45
  }
46
+ export interface EvidenceCoverageSummary {
47
+ total_checks: number;
48
+ checks_with_evidence: number;
49
+ total_evidence_refs: number;
50
+ coverage_percent: number;
51
+ }
46
52
  export declare function classifyFailure(result: CheckResult): FailureClass | null;
47
53
  export declare function buildManifest(runId: string, results: CheckResult[], options?: {
48
54
  workItemId?: string;
@@ -52,7 +58,10 @@ export declare function buildManifest(runId: string, results: CheckResult[], opt
52
58
  evidenceRefs?: Map<string, string[]>;
53
59
  }): VerificationManifest;
54
60
  export declare function buildRiskLedger(runId: string, manifest: VerificationManifest): ResidualRiskLedger;
61
+ export declare function summarizeEvidenceCoverage(manifest: VerificationManifest): EvidenceCoverageSummary;
55
62
  export declare function saveManifest(projectRoot: string, runId: string, manifest: VerificationManifest): void;
56
63
  export declare function loadManifest(projectRoot: string, runId: string): VerificationManifest | null;
57
64
  export declare function saveRiskLedger(projectRoot: string, runId: string, ledger: ResidualRiskLedger): void;
58
65
  export declare function loadRiskLedger(projectRoot: string, runId: string): ResidualRiskLedger | null;
66
+ export declare function saveEvidenceCoverage(projectRoot: string, runId: string, coverage: EvidenceCoverageSummary): void;
67
+ export declare function loadEvidenceCoverage(projectRoot: string, runId: string): EvidenceCoverageSummary | null;