oxe-cc 1.0.0 → 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 (322) hide show
  1. package/.cursor/commands/oxe-ask.md +3 -3
  2. package/.cursor/commands/oxe-capabilities.md +3 -3
  3. package/.cursor/commands/oxe-checkpoint.md +3 -3
  4. package/.cursor/commands/oxe-compact.md +3 -3
  5. package/.cursor/commands/oxe-dashboard.md +3 -3
  6. package/.cursor/commands/oxe-debug.md +3 -3
  7. package/.cursor/commands/oxe-discuss.md +3 -3
  8. package/.cursor/commands/oxe-execute.md +7 -4
  9. package/.cursor/commands/oxe-forensics.md +3 -3
  10. package/.cursor/commands/oxe-help.md +3 -3
  11. package/.cursor/commands/oxe-loop.md +3 -3
  12. package/.cursor/commands/oxe-milestone.md +3 -3
  13. package/.cursor/commands/oxe-next.md +3 -3
  14. package/.cursor/commands/oxe-obs.md +3 -3
  15. package/.cursor/commands/oxe-plan-agent.md +3 -3
  16. package/.cursor/commands/oxe-plan.md +3 -3
  17. package/.cursor/commands/oxe-project.md +3 -3
  18. package/.cursor/commands/oxe-quick.md +3 -3
  19. package/.cursor/commands/oxe-research.md +3 -3
  20. package/.cursor/commands/oxe-retro.md +3 -3
  21. package/.cursor/commands/oxe-review-pr.md +3 -3
  22. package/.cursor/commands/oxe-route.md +3 -3
  23. package/.cursor/commands/oxe-scan.md +3 -3
  24. package/.cursor/commands/oxe-security.md +3 -3
  25. package/.cursor/commands/oxe-session.md +4 -4
  26. package/.cursor/commands/oxe-ship.md +45 -0
  27. package/.cursor/commands/oxe-skill.md +3 -3
  28. package/.cursor/commands/oxe-spec.md +3 -3
  29. package/.cursor/commands/oxe-ui-review.md +3 -3
  30. package/.cursor/commands/oxe-ui-spec.md +3 -3
  31. package/.cursor/commands/oxe-update.md +3 -3
  32. package/.cursor/commands/oxe-validate-gaps.md +3 -3
  33. package/.cursor/commands/oxe-verify.md +6 -3
  34. package/.cursor/commands/oxe-workstream.md +3 -3
  35. package/.cursor/commands/oxe.md +6 -6
  36. package/.github/copilot-instructions.md +94 -4
  37. package/.github/prompts/oxe-ask.prompt.md +3 -3
  38. package/.github/prompts/oxe-capabilities.prompt.md +3 -3
  39. package/.github/prompts/oxe-checkpoint.prompt.md +3 -3
  40. package/.github/prompts/oxe-compact.prompt.md +3 -3
  41. package/.github/prompts/oxe-dashboard.prompt.md +3 -3
  42. package/.github/prompts/oxe-debug.prompt.md +3 -3
  43. package/.github/prompts/oxe-discuss.prompt.md +3 -3
  44. package/.github/prompts/oxe-execute.prompt.md +7 -4
  45. package/.github/prompts/oxe-forensics.prompt.md +3 -3
  46. package/.github/prompts/oxe-help.prompt.md +3 -3
  47. package/.github/prompts/oxe-loop.prompt.md +3 -3
  48. package/.github/prompts/oxe-milestone.prompt.md +3 -3
  49. package/.github/prompts/oxe-next.prompt.md +3 -3
  50. package/.github/prompts/oxe-obs.prompt.md +3 -3
  51. package/.github/prompts/oxe-plan-agent.prompt.md +3 -3
  52. package/.github/prompts/oxe-plan.prompt.md +3 -3
  53. package/.github/prompts/oxe-project.prompt.md +3 -3
  54. package/.github/prompts/oxe-quick.prompt.md +3 -3
  55. package/.github/prompts/oxe-research.prompt.md +3 -3
  56. package/.github/prompts/oxe-retro.prompt.md +3 -3
  57. package/.github/prompts/oxe-review-pr.prompt.md +3 -3
  58. package/.github/prompts/oxe-route.prompt.md +3 -3
  59. package/.github/prompts/oxe-scan.prompt.md +3 -3
  60. package/.github/prompts/oxe-security.prompt.md +3 -3
  61. package/.github/prompts/oxe-session.prompt.md +4 -4
  62. package/.github/prompts/oxe-ship.prompt.md +45 -0
  63. package/.github/prompts/oxe-skill.prompt.md +3 -3
  64. package/.github/prompts/oxe-spec.prompt.md +3 -3
  65. package/.github/prompts/oxe-ui-review.prompt.md +3 -3
  66. package/.github/prompts/oxe-ui-spec.prompt.md +3 -3
  67. package/.github/prompts/oxe-update.prompt.md +3 -3
  68. package/.github/prompts/oxe-validate-gaps.prompt.md +3 -3
  69. package/.github/prompts/oxe-verify.prompt.md +6 -3
  70. package/.github/prompts/oxe-workstream.prompt.md +3 -3
  71. package/.github/prompts/oxe.prompt.md +5 -5
  72. package/AGENTS.md +43 -28
  73. package/CHANGELOG.md +193 -0
  74. package/README.md +610 -529
  75. package/bin/banner.txt +1 -1
  76. package/bin/lib/oxe-agent-install.cjs +69 -69
  77. package/bin/lib/oxe-azure.cjs +1445 -1445
  78. package/bin/lib/oxe-context-engine.cjs +867 -867
  79. package/bin/lib/oxe-dashboard.cjs +76 -28
  80. package/bin/lib/oxe-operational.cjs +2144 -1340
  81. package/bin/lib/oxe-project-health.cjs +483 -1
  82. package/bin/lib/oxe-runtime-semantics.cjs +12 -0
  83. package/bin/oxe-cc.js +554 -152
  84. package/commands/oxe/ask.md +7 -3
  85. package/commands/oxe/capabilities.md +2 -2
  86. package/commands/oxe/checkpoint.md +3 -3
  87. package/commands/oxe/compact.md +3 -3
  88. package/commands/oxe/dashboard.md +2 -2
  89. package/commands/oxe/debug.md +3 -3
  90. package/commands/oxe/discuss.md +2 -2
  91. package/commands/oxe/execute.md +7 -4
  92. package/commands/oxe/forensics.md +3 -3
  93. package/commands/oxe/help.md +2 -2
  94. package/commands/oxe/loop.md +3 -3
  95. package/commands/oxe/milestone.md +3 -3
  96. package/commands/oxe/next.md +3 -3
  97. package/commands/oxe/obs.md +3 -3
  98. package/commands/oxe/oxe.md +5 -5
  99. package/commands/oxe/plan-agent.md +2 -2
  100. package/commands/oxe/plan.md +2 -2
  101. package/commands/oxe/project.md +3 -3
  102. package/commands/oxe/quick.md +2 -2
  103. package/commands/oxe/research.md +3 -3
  104. package/commands/oxe/retro.md +3 -3
  105. package/commands/oxe/review-pr.md +3 -3
  106. package/commands/oxe/route.md +3 -3
  107. package/commands/oxe/scan.md +3 -3
  108. package/commands/oxe/security.md +3 -3
  109. package/commands/oxe/session.md +4 -4
  110. package/commands/oxe/ship.md +49 -0
  111. package/commands/oxe/skill.md +2 -2
  112. package/commands/oxe/spec.md +4 -4
  113. package/commands/oxe/ui-review.md +3 -3
  114. package/commands/oxe/ui-spec.md +3 -3
  115. package/commands/oxe/update.md +2 -2
  116. package/commands/oxe/validate-gaps.md +3 -3
  117. package/commands/oxe/verify.md +7 -4
  118. package/commands/oxe/workstream.md +3 -3
  119. package/lib/runtime/audit/audit-trail.d.ts +71 -0
  120. package/lib/runtime/audit/audit-trail.js +154 -0
  121. package/lib/runtime/audit/index.d.ts +2 -0
  122. package/lib/runtime/audit/index.js +18 -0
  123. package/lib/runtime/audit/policy-pack.d.ts +15 -0
  124. package/lib/runtime/audit/policy-pack.js +57 -0
  125. package/lib/runtime/context/context-pack-builder.d.ts +15 -0
  126. package/lib/runtime/context/context-pack-builder.js +42 -0
  127. package/lib/runtime/context/context-pack-store.d.ts +38 -0
  128. package/lib/runtime/context/context-pack-store.js +142 -0
  129. package/lib/runtime/context/context-profiles.d.ts +11 -0
  130. package/lib/runtime/context/context-profiles.js +51 -0
  131. package/lib/runtime/context/index.d.ts +2 -0
  132. package/lib/runtime/context/index.js +2 -0
  133. package/lib/runtime/decision/decision-engine.d.ts +43 -0
  134. package/lib/runtime/decision/decision-engine.js +127 -0
  135. package/lib/runtime/decision/decision-memo.d.ts +53 -0
  136. package/lib/runtime/decision/decision-memo.js +173 -0
  137. package/lib/runtime/decision/index.d.ts +2 -0
  138. package/lib/runtime/decision/index.js +18 -0
  139. package/lib/runtime/delivery/branch-manager.d.ts +1 -0
  140. package/lib/runtime/delivery/branch-manager.js +7 -0
  141. package/lib/runtime/delivery/ci-checks.js +34 -1
  142. package/lib/runtime/delivery/delivery-records.d.ts +34 -0
  143. package/lib/runtime/delivery/delivery-records.js +48 -0
  144. package/lib/runtime/delivery/index.d.ts +2 -0
  145. package/lib/runtime/delivery/index.js +2 -0
  146. package/lib/runtime/delivery/promotion-pipeline.d.ts +63 -0
  147. package/lib/runtime/delivery/promotion-pipeline.js +224 -0
  148. package/lib/runtime/gate/gate-manager.d.ts +41 -0
  149. package/lib/runtime/gate/gate-manager.js +108 -1
  150. package/lib/runtime/index.d.ts +5 -2
  151. package/lib/runtime/index.js +7 -1
  152. package/lib/runtime/models/gate-decision.d.ts +4 -1
  153. package/lib/runtime/models/workspace.d.ts +3 -0
  154. package/lib/runtime/plugins/capability-adapter.d.ts +12 -0
  155. package/lib/runtime/plugins/capability-adapter.js +204 -0
  156. package/lib/runtime/plugins/capability-matrix.d.ts +25 -0
  157. package/lib/runtime/plugins/capability-matrix.js +90 -0
  158. package/lib/runtime/plugins/index.d.ts +3 -0
  159. package/lib/runtime/plugins/index.js +3 -0
  160. package/lib/runtime/plugins/plugin-abi.d.ts +2 -0
  161. package/lib/runtime/plugins/plugin-manifest.d.ts +22 -0
  162. package/lib/runtime/plugins/plugin-manifest.js +95 -0
  163. package/lib/runtime/plugins/plugin-registry.d.ts +46 -0
  164. package/lib/runtime/plugins/plugin-registry.js +84 -2
  165. package/lib/runtime/policy/policy-engine.d.ts +47 -1
  166. package/lib/runtime/policy/policy-engine.js +172 -9
  167. package/lib/runtime/projection/projection-engine.d.ts +9 -1
  168. package/lib/runtime/projection/projection-engine.js +73 -3
  169. package/lib/runtime/reducers/run-state-reducer.d.ts +26 -0
  170. package/lib/runtime/reducers/run-state-reducer.js +117 -1
  171. package/lib/runtime/scheduler/agent-registry.d.ts +44 -0
  172. package/lib/runtime/scheduler/agent-registry.js +96 -0
  173. package/lib/runtime/scheduler/agent-roles.d.ts +54 -0
  174. package/lib/runtime/scheduler/agent-roles.js +62 -0
  175. package/lib/runtime/scheduler/index.d.ts +3 -0
  176. package/lib/runtime/scheduler/index.js +3 -0
  177. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +45 -1
  178. package/lib/runtime/scheduler/multi-agent-coordinator.js +234 -35
  179. package/lib/runtime/scheduler/run-journal.d.ts +18 -0
  180. package/lib/runtime/scheduler/run-journal.js +54 -0
  181. package/lib/runtime/scheduler/scheduler.d.ts +29 -1
  182. package/lib/runtime/scheduler/scheduler.js +387 -14
  183. package/lib/runtime/verification/index.d.ts +1 -0
  184. package/lib/runtime/verification/index.js +1 -0
  185. package/lib/runtime/verification/verification-compiler.d.ts +43 -0
  186. package/lib/runtime/verification/verification-compiler.js +137 -0
  187. package/lib/runtime/verification/verification-manifest.d.ts +67 -0
  188. package/lib/runtime/verification/verification-manifest.js +179 -0
  189. package/lib/runtime/workspace/strategies/ephemeral-container.d.ts +1 -0
  190. package/lib/runtime/workspace/strategies/ephemeral-container.js +4 -0
  191. package/lib/runtime/workspace/strategies/git-worktree.d.ts +1 -0
  192. package/lib/runtime/workspace/strategies/git-worktree.js +2 -0
  193. package/lib/runtime/workspace/strategies/inplace.d.ts +1 -0
  194. package/lib/runtime/workspace/strategies/inplace.js +2 -0
  195. package/lib/runtime/workspace/workspace-manager.d.ts +2 -1
  196. package/lib/sdk/README.md +9 -9
  197. package/lib/sdk/index.cjs +33 -24
  198. package/lib/sdk/index.d.ts +149 -14
  199. package/oxe/templates/ACTIVE-RUN.template.json +32 -32
  200. package/oxe/templates/CAPABILITIES.template.md +7 -7
  201. package/oxe/templates/CAPABILITY.template.md +45 -45
  202. package/oxe/templates/CHECKPOINTS.template.md +7 -7
  203. package/oxe/templates/EXECUTION-RUNTIME.template.md +68 -68
  204. package/oxe/templates/HYPOTHESES.template.md +33 -33
  205. package/oxe/templates/LESSONS-METRICS.template.json +13 -13
  206. package/oxe/templates/NOTES.template.md +16 -16
  207. package/oxe/templates/PLAN-REVIEW.template.md +31 -31
  208. package/oxe/templates/SESSION.template.md +34 -34
  209. package/oxe/templates/SKILL.template.md +26 -26
  210. package/oxe/templates/STATE.md +55 -55
  211. package/oxe/templates/WORKFLOW_AUTHORING.md +18 -18
  212. package/oxe/workflows/ask.md +96 -92
  213. package/oxe/workflows/capabilities.md +25 -25
  214. package/oxe/workflows/checkpoint.md +14 -10
  215. package/oxe/workflows/dashboard.md +33 -33
  216. package/oxe/workflows/debug.md +19 -15
  217. package/oxe/workflows/discuss.md +12 -12
  218. package/oxe/workflows/execute.md +44 -2
  219. package/oxe/workflows/forensics.md +13 -9
  220. package/oxe/workflows/help.md +352 -304
  221. package/oxe/workflows/loop.md +17 -13
  222. package/oxe/workflows/next.md +22 -22
  223. package/oxe/workflows/obs.md +4 -0
  224. package/oxe/workflows/oxe.md +64 -31
  225. package/oxe/workflows/plan-agent.md +9 -9
  226. package/oxe/workflows/project.md +6 -1
  227. package/oxe/workflows/quick.md +10 -10
  228. package/oxe/workflows/references/reasoning-discovery.md +28 -28
  229. package/oxe/workflows/references/reasoning-execution.md +29 -29
  230. package/oxe/workflows/references/reasoning-planning.md +32 -32
  231. package/oxe/workflows/references/reasoning-review.md +29 -29
  232. package/oxe/workflows/references/reasoning-status.md +24 -24
  233. package/oxe/workflows/references/robustness-elevation.md +295 -295
  234. package/oxe/workflows/references/workflow-runtime-contracts.json +952 -907
  235. package/oxe/workflows/research.md +32 -28
  236. package/oxe/workflows/retro.md +4 -0
  237. package/oxe/workflows/review-pr.md +15 -11
  238. package/oxe/workflows/route.md +16 -16
  239. package/oxe/workflows/scan.md +4 -0
  240. package/oxe/workflows/security.md +14 -10
  241. package/oxe/workflows/session.md +213 -197
  242. package/oxe/workflows/ship.md +142 -0
  243. package/oxe/workflows/skill.md +44 -44
  244. package/oxe/workflows/spec.md +15 -0
  245. package/oxe/workflows/ui-review.md +20 -16
  246. package/oxe/workflows/ui-spec.md +7 -3
  247. package/oxe/workflows/validate-gaps.md +13 -9
  248. package/oxe/workflows/verify-audit.md +73 -73
  249. package/oxe/workflows/verify.md +52 -3
  250. package/package.json +92 -92
  251. package/packages/runtime/package.json +17 -17
  252. package/packages/runtime/src/audit/audit-trail.ts +243 -0
  253. package/packages/runtime/src/audit/index.ts +2 -0
  254. package/packages/runtime/src/audit/policy-pack.ts +62 -0
  255. package/packages/runtime/src/compiler/graph-compiler.ts +245 -245
  256. package/packages/runtime/src/compiler/index.ts +1 -1
  257. package/packages/runtime/src/context/context-pack-builder.ts +259 -193
  258. package/packages/runtime/src/context/context-pack-store.ts +197 -0
  259. package/packages/runtime/src/context/context-profiles.ts +60 -0
  260. package/packages/runtime/src/context/index.ts +3 -1
  261. package/packages/runtime/src/decision/decision-engine.ts +174 -0
  262. package/packages/runtime/src/decision/decision-memo.ts +211 -0
  263. package/packages/runtime/src/decision/index.ts +2 -0
  264. package/packages/runtime/src/delivery/branch-manager.ts +91 -84
  265. package/packages/runtime/src/delivery/ci-checks.ts +285 -252
  266. package/packages/runtime/src/delivery/delivery-records.ts +75 -0
  267. package/packages/runtime/src/delivery/index.ts +5 -3
  268. package/packages/runtime/src/delivery/pr-manager.ts +112 -112
  269. package/packages/runtime/src/delivery/promotion-pipeline.ts +334 -0
  270. package/packages/runtime/src/events/bus.ts +92 -92
  271. package/packages/runtime/src/events/catalog.ts +29 -29
  272. package/packages/runtime/src/events/envelope.ts +14 -14
  273. package/packages/runtime/src/events/index.ts +3 -3
  274. package/packages/runtime/src/evidence/evidence-store.ts +130 -130
  275. package/packages/runtime/src/evidence/index.ts +1 -1
  276. package/packages/runtime/src/gate/gate-manager.ts +289 -137
  277. package/packages/runtime/src/gate/index.ts +1 -1
  278. package/packages/runtime/src/index.ts +41 -32
  279. package/packages/runtime/src/models/attempt.ts +19 -19
  280. package/packages/runtime/src/models/evidence.ts +21 -21
  281. package/packages/runtime/src/models/gate-decision.ts +25 -21
  282. package/packages/runtime/src/models/index.ts +8 -8
  283. package/packages/runtime/src/models/run.ts +24 -24
  284. package/packages/runtime/src/models/session.ts +11 -11
  285. package/packages/runtime/src/models/verification-result.ts +10 -10
  286. package/packages/runtime/src/models/work-item.ts +25 -25
  287. package/packages/runtime/src/models/workspace.ts +31 -28
  288. package/packages/runtime/src/plugins/capability-adapter.ts +206 -0
  289. package/packages/runtime/src/plugins/capability-matrix.ts +126 -0
  290. package/packages/runtime/src/plugins/index.ts +5 -2
  291. package/packages/runtime/src/plugins/plugin-abi.ts +97 -95
  292. package/packages/runtime/src/plugins/plugin-manifest.ts +118 -0
  293. package/packages/runtime/src/plugins/plugin-registry.ts +232 -119
  294. package/packages/runtime/src/policy/index.ts +1 -1
  295. package/packages/runtime/src/policy/policy-engine.ts +330 -113
  296. package/packages/runtime/src/projection/index.ts +1 -1
  297. package/packages/runtime/src/projection/projection-engine.ts +328 -249
  298. package/packages/runtime/src/reducers/debug-reducer.ts +36 -36
  299. package/packages/runtime/src/reducers/index.ts +2 -2
  300. package/packages/runtime/src/reducers/run-state-reducer.ts +269 -127
  301. package/packages/runtime/src/scheduler/agent-registry.ts +132 -0
  302. package/packages/runtime/src/scheduler/agent-roles.ts +109 -0
  303. package/packages/runtime/src/scheduler/index.ts +4 -1
  304. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +521 -231
  305. package/packages/runtime/src/scheduler/run-journal.ts +62 -0
  306. package/packages/runtime/src/scheduler/scheduler.ts +722 -281
  307. package/packages/runtime/src/verification/index.ts +2 -1
  308. package/packages/runtime/src/verification/verification-compiler.ts +436 -225
  309. package/packages/runtime/src/verification/verification-manifest.ts +252 -0
  310. package/packages/runtime/src/workspace/index.ts +5 -5
  311. package/packages/runtime/src/workspace/strategies/ephemeral-container.ts +126 -121
  312. package/packages/runtime/src/workspace/strategies/git-worktree.ts +79 -77
  313. package/packages/runtime/src/workspace/strategies/inplace.ts +38 -35
  314. package/packages/runtime/src/workspace/workspace-manager.ts +16 -15
  315. package/packages/runtime/tsconfig.json +17 -17
  316. package/vscode-extension/.vscodeignore +7 -7
  317. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  318. package/vscode-extension/package.json +185 -185
  319. package/vscode-extension/src/extension.js +310 -310
  320. package/vscode-extension/src/shared/contextLoader.js +137 -137
  321. package/vscode-extension/src/shared/contractBuilder.js +159 -159
  322. package/vscode-extension/src/shared/stateReader.js +101 -101
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StrategySelector = void 0;
7
+ exports.buildBlastRadius = buildBlastRadius;
8
+ exports.buildRollbackPlan = buildRollbackPlan;
9
+ exports.buildMemo = buildMemo;
10
+ exports.saveMemo = saveMemo;
11
+ exports.loadMemo = loadMemo;
12
+ exports.listMemos = listMemos;
13
+ const crypto_1 = __importDefault(require("crypto"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const fs_1 = __importDefault(require("fs"));
16
+ // ─── BlastRadius estimation ───────────────────────────────────────────────────
17
+ function deriveSubsystems(mutationScope) {
18
+ const seen = new Set();
19
+ for (const p of mutationScope) {
20
+ const parts = p.replace(/\\/g, '/').split('/');
21
+ if (parts.length >= 2)
22
+ seen.add(parts[0]);
23
+ else
24
+ seen.add(p);
25
+ }
26
+ return [...seen];
27
+ }
28
+ function estimateRiskScore(mutationScope, retryCount, riskLevel) {
29
+ let score = 0;
30
+ score += Math.min(0.4, mutationScope.length * 0.05);
31
+ score += retryCount > 0 ? Math.min(0.2, retryCount * 0.05) : 0;
32
+ switch (riskLevel) {
33
+ case 'critical':
34
+ score += 0.4;
35
+ break;
36
+ case 'high':
37
+ score += 0.3;
38
+ break;
39
+ case 'medium':
40
+ score += 0.15;
41
+ break;
42
+ case 'low':
43
+ score += 0.05;
44
+ break;
45
+ default: break;
46
+ }
47
+ return Math.min(1, score);
48
+ }
49
+ function buildBlastRadius(mutationScope, retryCount, riskLevel) {
50
+ const risk_score = estimateRiskScore(mutationScope, retryCount, riskLevel);
51
+ return {
52
+ estimated_files: mutationScope.length,
53
+ subsystems: deriveSubsystems(mutationScope),
54
+ risk_score: Math.round(risk_score * 100) / 100,
55
+ reversible: riskLevel !== 'critical' && mutationScope.length <= 10,
56
+ };
57
+ }
58
+ // ─── RollbackPlan ─────────────────────────────────────────────────────────────
59
+ function buildRollbackPlan(blastRadius, retryCount) {
60
+ if (blastRadius.risk_score >= 0.7 || !blastRadius.reversible) {
61
+ return {
62
+ strategy: 'restore_workspace',
63
+ steps: ['snapshot workspace before mutation', 'restore snapshot on failure', 'verify clean state'],
64
+ estimated_cost: 'high',
65
+ preconditions: ['workspace snapshot available', 'no shared-state mutations'],
66
+ };
67
+ }
68
+ if (retryCount > 1 || blastRadius.estimated_files > 5) {
69
+ return {
70
+ strategy: 'revert_commit',
71
+ steps: ['record commit SHA before change', 'git revert on failure'],
72
+ estimated_cost: 'medium',
73
+ preconditions: ['git repo initialized', 'changes committed atomically'],
74
+ };
75
+ }
76
+ return {
77
+ strategy: 'undo_patch',
78
+ steps: ['apply inverse patch'],
79
+ estimated_cost: 'low',
80
+ preconditions: ['original file state recorded'],
81
+ };
82
+ }
83
+ // ─── StrategySelector ────────────────────────────────────────────────────────
84
+ class StrategySelector {
85
+ select(mutationScope, retryCount, riskLevel) {
86
+ if (riskLevel === 'critical')
87
+ return 'feature_flag';
88
+ if (retryCount > 1)
89
+ return 'minimal_patch';
90
+ if (mutationScope.length > 8)
91
+ return 'isolated_refactor';
92
+ if (riskLevel === 'high')
93
+ return 'feature_flag';
94
+ if (mutationScope.length > 3)
95
+ return 'expand_contract';
96
+ if (mutationScope.length === 0)
97
+ return 'no_op';
98
+ return 'minimal_patch';
99
+ }
100
+ alternatives(chosen, mutationScope, riskLevel) {
101
+ const all = ['minimal_patch', 'isolated_refactor', 'expand_contract', 'feature_flag', 'no_op'];
102
+ return all
103
+ .filter((s) => s !== chosen)
104
+ .map((s) => ({ strategy: s, reason: this.rejectionReason(s, chosen, mutationScope, riskLevel) }));
105
+ }
106
+ rejectionReason(s, chosen, mutationScope, riskLevel) {
107
+ switch (s) {
108
+ case 'no_op': return 'mutation scope is non-empty; no-op would not satisfy requirements';
109
+ case 'feature_flag': return riskLevel !== 'critical' && riskLevel !== 'high' ? 'risk level does not warrant feature flag overhead' : `${chosen} preferred for scope size`;
110
+ case 'isolated_refactor': return mutationScope.length <= 8 ? 'scope is small enough for simpler strategy' : `${chosen} preferred`;
111
+ case 'expand_contract': return 'expand-contract requires coordinated deployment; overhead not justified here';
112
+ case 'minimal_patch': return `${chosen} preferred due to scope or risk level`;
113
+ default: return 'not applicable';
114
+ }
115
+ }
116
+ }
117
+ exports.StrategySelector = StrategySelector;
118
+ function buildMemo(input) {
119
+ const selector = new StrategySelector();
120
+ const chosen = selector.select(input.mutation_scope, input.retry_count, input.risk_level);
121
+ const blast_radius = buildBlastRadius(input.mutation_scope, input.retry_count, input.risk_level);
122
+ const rollback_plan = buildRollbackPlan(blast_radius, input.retry_count);
123
+ const alternatives_rejected = selector.alternatives(chosen, input.mutation_scope, input.risk_level);
124
+ return {
125
+ memo_id: `memo-${crypto_1.default.randomBytes(4).toString('hex')}`,
126
+ work_item_id: input.work_item_id,
127
+ run_id: input.run_id,
128
+ problem_summary: input.problem_summary,
129
+ chosen_strategy: chosen,
130
+ alternatives_rejected,
131
+ blast_radius,
132
+ rollback_plan,
133
+ min_evidence_required: input.min_evidence_required ?? [],
134
+ confidence: input.confidence ?? (1 - blast_radius.risk_score),
135
+ created_at: new Date().toISOString(),
136
+ };
137
+ }
138
+ function memoDir(projectRoot, runId) {
139
+ return path_1.default.join(projectRoot, '.oxe', 'runs', runId, 'memos');
140
+ }
141
+ function saveMemo(projectRoot, memo) {
142
+ const dir = memoDir(projectRoot, memo.run_id);
143
+ fs_1.default.mkdirSync(dir, { recursive: true });
144
+ fs_1.default.writeFileSync(path_1.default.join(dir, `${memo.memo_id}.json`), JSON.stringify(memo, null, 2), 'utf8');
145
+ }
146
+ function loadMemo(projectRoot, runId, memoId) {
147
+ const p = path_1.default.join(memoDir(projectRoot, runId), `${memoId}.json`);
148
+ if (!fs_1.default.existsSync(p))
149
+ return null;
150
+ try {
151
+ return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
152
+ }
153
+ catch {
154
+ return null;
155
+ }
156
+ }
157
+ function listMemos(projectRoot, runId) {
158
+ const dir = memoDir(projectRoot, runId);
159
+ if (!fs_1.default.existsSync(dir))
160
+ return [];
161
+ return fs_1.default
162
+ .readdirSync(dir)
163
+ .filter((f) => f.endsWith('.json'))
164
+ .map((f) => {
165
+ try {
166
+ return JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, f), 'utf8'));
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ })
172
+ .filter((m) => m !== null);
173
+ }
@@ -0,0 +1,2 @@
1
+ export * from './decision-engine';
2
+ export * from './decision-memo';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./decision-engine"), exports);
18
+ __exportStar(require("./decision-memo"), exports);
@@ -15,5 +15,6 @@ export declare class BranchManager {
15
15
  listOxeBranches(): BranchInfo[];
16
16
  mergeWorktreeBranch(worktreeBranch: string, targetBranch: string): void;
17
17
  branchExists(name: string): boolean;
18
+ push(remote: string, branchName: string, setUpstream?: boolean): void;
18
19
  private git;
19
20
  }
@@ -68,6 +68,13 @@ class BranchManager {
68
68
  });
69
69
  return result.status === 0;
70
70
  }
71
+ push(remote, branchName, setUpstream = false) {
72
+ const args = ['push'];
73
+ if (setUpstream)
74
+ args.push('-u');
75
+ args.push(remote, branchName);
76
+ this.git(args);
77
+ }
71
78
  git(args) {
72
79
  return (0, child_process_1.execFileSync)('git', args, {
73
80
  cwd: this.projectRoot,
@@ -41,6 +41,25 @@ exports.verifyAcceptanceCheck = {
41
41
  name: 'oxe-verify-acceptance',
42
42
  description: 'Checks that VERIFY.md exists and contains no failed criteria',
43
43
  async run(ctx) {
44
+ const manifestPath = path_1.default.join(ctx.projectRoot, '.oxe', 'runs', ctx.runId || '', 'verification-manifest.json');
45
+ if (ctx.runId && fs_1.default.existsSync(manifestPath)) {
46
+ try {
47
+ const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
48
+ const failCount = Number(manifest.summary?.fail || 0);
49
+ const errorCount = Number(manifest.summary?.error || 0);
50
+ return failCount === 0 && errorCount === 0
51
+ ? { check: this.name, status: 'pass', message: `Manifest reports ${manifest.summary.total} checks with no failures` }
52
+ : {
53
+ check: this.name,
54
+ status: 'fail',
55
+ message: `Manifest reports ${failCount} failed and ${errorCount} errored checks`,
56
+ details: manifest.summary,
57
+ };
58
+ }
59
+ catch (err) {
60
+ return { check: this.name, status: 'error', message: `Failed to parse verification manifest: ${String(err)}` };
61
+ }
62
+ }
44
63
  const verifyPath = ctx.sessionId
45
64
  ? path_1.default.join(ctx.projectRoot, '.oxe', ctx.sessionId, 'verification', 'VERIFY.md')
46
65
  : path_1.default.join(ctx.projectRoot, '.oxe', 'VERIFY.md');
@@ -86,7 +105,21 @@ exports.policyCheck = {
86
105
  details: pending.map((g) => ({ gate_id: g.gate_id, scope: g.scope })),
87
106
  };
88
107
  }
89
- return { check: this.name, status: 'pass', message: 'All gates resolved' };
108
+ if (ctx.runId) {
109
+ const policyPath = path_1.default.join(ctx.projectRoot, '.oxe', 'runs', ctx.runId, 'policy-decisions.json');
110
+ if (fs_1.default.existsSync(policyPath)) {
111
+ const policyDecisions = JSON.parse(fs_1.default.readFileSync(policyPath, 'utf8'));
112
+ const withoutRationale = policyDecisions.filter((decision) => decision.override && !decision.rationale);
113
+ if (withoutRationale.length > 0) {
114
+ return {
115
+ check: this.name,
116
+ status: 'fail',
117
+ message: `${withoutRationale.length} policy override(s) without rationale`,
118
+ };
119
+ }
120
+ }
121
+ }
122
+ return { check: this.name, status: 'pass', message: 'All gates resolved and policy overrides are justified' };
90
123
  }
91
124
  catch (err) {
92
125
  return { check: this.name, status: 'error', message: `Failed to read GATES.json: ${String(err)}` };
@@ -0,0 +1,34 @@
1
+ export type PromotionTarget = 'local_commit' | 'remote_promotion';
2
+ export type PromotionRemoteTarget = 'pr_draft' | 'branch_push';
3
+ export interface CommitRecord {
4
+ run_id: string;
5
+ branch: string;
6
+ commit_sha: string | null;
7
+ status: 'pending' | 'committed' | 'blocked';
8
+ created_at: string;
9
+ committed_at: string | null;
10
+ message: string | null;
11
+ summary_path: string | null;
12
+ }
13
+ export interface PromotionRecord {
14
+ run_id: string;
15
+ target: PromotionTarget;
16
+ target_kind: PromotionRemoteTarget;
17
+ branch: string;
18
+ status: 'pending' | 'open' | 'merged' | 'closed' | 'blocked' | 'promoted';
19
+ created_at: string;
20
+ promoted_at: string | null;
21
+ summary_path: string | null;
22
+ remote: string | null;
23
+ target_ref: string | null;
24
+ pr_url: string | null;
25
+ pr_number: number | null;
26
+ reasons?: string[];
27
+ coverage_percent?: number | null;
28
+ }
29
+ export declare function commitRecordPath(projectRoot: string, runId: string): string;
30
+ export declare function promotionRecordPath(projectRoot: string, runId: string): string;
31
+ export declare function saveCommitRecord(projectRoot: string, runId: string, record: CommitRecord): void;
32
+ export declare function loadCommitRecord(projectRoot: string, runId: string): CommitRecord | null;
33
+ export declare function savePromotionRecord(projectRoot: string, runId: string, record: PromotionRecord): void;
34
+ export declare function loadPromotionRecord(projectRoot: string, runId: string): PromotionRecord | null;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.commitRecordPath = commitRecordPath;
7
+ exports.promotionRecordPath = promotionRecordPath;
8
+ exports.saveCommitRecord = saveCommitRecord;
9
+ exports.loadCommitRecord = loadCommitRecord;
10
+ exports.savePromotionRecord = savePromotionRecord;
11
+ exports.loadPromotionRecord = loadPromotionRecord;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ function runDir(projectRoot, runId) {
15
+ return path_1.default.join(projectRoot, '.oxe', 'runs', runId);
16
+ }
17
+ function saveJson(filePath, payload) {
18
+ fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
19
+ fs_1.default.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');
20
+ }
21
+ function loadJson(filePath) {
22
+ if (!fs_1.default.existsSync(filePath))
23
+ return null;
24
+ try {
25
+ return JSON.parse(fs_1.default.readFileSync(filePath, 'utf8'));
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ function commitRecordPath(projectRoot, runId) {
32
+ return path_1.default.join(runDir(projectRoot, runId), 'commit-record.json');
33
+ }
34
+ function promotionRecordPath(projectRoot, runId) {
35
+ return path_1.default.join(runDir(projectRoot, runId), 'promotion-record.json');
36
+ }
37
+ function saveCommitRecord(projectRoot, runId, record) {
38
+ saveJson(commitRecordPath(projectRoot, runId), record);
39
+ }
40
+ function loadCommitRecord(projectRoot, runId) {
41
+ return loadJson(commitRecordPath(projectRoot, runId));
42
+ }
43
+ function savePromotionRecord(projectRoot, runId, record) {
44
+ saveJson(promotionRecordPath(projectRoot, runId), record);
45
+ }
46
+ function loadPromotionRecord(projectRoot, runId) {
47
+ return loadJson(promotionRecordPath(projectRoot, runId));
48
+ }
@@ -1,3 +1,5 @@
1
1
  export * from './branch-manager';
2
2
  export * from './pr-manager';
3
3
  export * from './ci-checks';
4
+ export * from './delivery-records';
5
+ export * from './promotion-pipeline';
@@ -17,3 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./branch-manager"), exports);
18
18
  __exportStar(require("./pr-manager"), exports);
19
19
  __exportStar(require("./ci-checks"), exports);
20
+ __exportStar(require("./delivery-records"), exports);
21
+ __exportStar(require("./promotion-pipeline"), exports);
@@ -0,0 +1,63 @@
1
+ import type { PRManager } from './pr-manager';
2
+ import type { BranchManager } from './branch-manager';
3
+ import type { VerificationManifest, ResidualRiskLedger } from '../verification/verification-manifest';
4
+ import type { EvidenceCoverageSummary } from '../verification/verification-manifest';
5
+ import type { RunResult } from '../scheduler/scheduler';
6
+ import type { GateToken } from '../gate/gate-manager';
7
+ import { type CommitRecord, type PromotionRecord, type PromotionRemoteTarget } from './delivery-records';
8
+ export interface RunPRLink {
9
+ run_id: string;
10
+ branch: string;
11
+ pr_url: string | null;
12
+ pr_number: number | null;
13
+ status: 'pending' | 'open' | 'merged' | 'closed' | 'blocked';
14
+ created_at: string;
15
+ merged_at: string | null;
16
+ }
17
+ export interface PromotionOptions {
18
+ baseBranch?: string;
19
+ draftPR?: boolean;
20
+ autoMerge?: boolean;
21
+ mergeMethod?: 'merge' | 'squash' | 'rebase';
22
+ targetRef?: string;
23
+ remote?: string;
24
+ targetKind?: PromotionRemoteTarget;
25
+ minimumCoverage?: number;
26
+ }
27
+ export type MergeGateVerdict = 'approved' | 'blocked' | 'needs_review';
28
+ export interface MergeGateReport {
29
+ verdict: MergeGateVerdict;
30
+ reasons: string[];
31
+ blocking_risks: string[];
32
+ pending_gates: Array<{
33
+ gate_id: string;
34
+ scope: string;
35
+ work_item_id: string | null;
36
+ }>;
37
+ }
38
+ export declare class MergeGateEvaluator {
39
+ evaluate(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null, gates?: GateToken[], evidenceCoverage?: EvidenceCoverageSummary | null, minimumCoverage?: number): MergeGateReport;
40
+ }
41
+ export declare class PromotionPipeline {
42
+ private readonly projectRoot;
43
+ private readonly branchManager;
44
+ private readonly prManager;
45
+ private readonly gateEvaluator;
46
+ constructor(projectRoot: string, branchManager: BranchManager, prManager: PRManager, gateEvaluator?: MergeGateEvaluator);
47
+ private baseSummaryLines;
48
+ buildCommitSummary(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null, commitMessage?: string | null): string;
49
+ buildPromotionSummary(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null): string;
50
+ buildPRBody(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null): string;
51
+ recordLocalCommit(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null, options?: {
52
+ commitMessage?: string;
53
+ commitSha?: string | null;
54
+ summaryPath?: string | null;
55
+ }): CommitRecord;
56
+ promote(runResult: RunResult, manifest: VerificationManifest | null, riskLedger: ResidualRiskLedger | null, opts?: PromotionOptions, gates?: GateToken[], evidenceCoverage?: EvidenceCoverageSummary | null): Promise<PromotionRecord>;
57
+ loadCommitRecord(runId: string): CommitRecord | null;
58
+ loadPromotionRecord(runId: string): PromotionRecord | null;
59
+ savePRLink(runId: string, link: RunPRLink): void;
60
+ loadPRLink(runId: string): RunPRLink | null;
61
+ private asRunPRLink;
62
+ private safeCurrentCommit;
63
+ }
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PromotionPipeline = exports.MergeGateEvaluator = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const delivery_records_1 = require("./delivery-records");
10
+ class MergeGateEvaluator {
11
+ evaluate(runResult, manifest, riskLedger, gates = [], evidenceCoverage = null, minimumCoverage = 100) {
12
+ const reasons = [];
13
+ const blockingRisks = [];
14
+ const pendingGates = gates
15
+ .filter((gate) => gate.status === 'pending')
16
+ .map((gate) => ({
17
+ gate_id: gate.gate_id,
18
+ scope: gate.scope,
19
+ work_item_id: gate.work_item_id ?? null,
20
+ }));
21
+ if (runResult.failed.length > 0) {
22
+ reasons.push(`${runResult.failed.length} task(s) failed: ${runResult.failed.join(', ')}`);
23
+ }
24
+ if (runResult.blocked.length > 0) {
25
+ reasons.push(`${runResult.blocked.length} task(s) blocked: ${runResult.blocked.join(', ')}`);
26
+ }
27
+ if (manifest && !manifest.summary.all_passed) {
28
+ reasons.push(`Verification: ${manifest.summary.fail} check(s) failed, ${manifest.summary.error} error(s)`);
29
+ }
30
+ if (riskLedger) {
31
+ const critical = riskLedger.risks.filter((r) => r.severity === 'critical' || r.severity === 'high');
32
+ for (const risk of critical) {
33
+ blockingRisks.push(`[${risk.severity.toUpperCase()}] ${risk.description}`);
34
+ }
35
+ }
36
+ if (pendingGates.length > 0) {
37
+ reasons.push(`${pendingGates.length} pending gate(s)`);
38
+ }
39
+ if (evidenceCoverage && evidenceCoverage.coverage_percent < minimumCoverage) {
40
+ reasons.push(`Evidence coverage below threshold: ${evidenceCoverage.coverage_percent}%/${minimumCoverage}%`);
41
+ }
42
+ const hasBlockers = reasons.length > 0 || blockingRisks.length > 0;
43
+ const verdict = hasBlockers ? 'blocked' : 'approved';
44
+ return { verdict, reasons, blocking_risks: blockingRisks, pending_gates: pendingGates };
45
+ }
46
+ }
47
+ exports.MergeGateEvaluator = MergeGateEvaluator;
48
+ class PromotionPipeline {
49
+ constructor(projectRoot, branchManager, prManager, gateEvaluator = new MergeGateEvaluator()) {
50
+ this.projectRoot = projectRoot;
51
+ this.branchManager = branchManager;
52
+ this.prManager = prManager;
53
+ this.gateEvaluator = gateEvaluator;
54
+ }
55
+ baseSummaryLines(runResult, manifest, riskLedger) {
56
+ const lines = [];
57
+ lines.push(`**Run ID:** \`${runResult.run_id}\``);
58
+ lines.push(`**Status:** ${runResult.status}`);
59
+ lines.push(`**Completed:** ${runResult.completed.length} tasks`);
60
+ if (runResult.failed.length > 0) {
61
+ lines.push(`**Failed:** ${runResult.failed.join(', ')}`);
62
+ }
63
+ if (runResult.blocked.length > 0) {
64
+ lines.push(`**Blocked:** ${runResult.blocked.join(', ')}`);
65
+ }
66
+ if (manifest) {
67
+ lines.push('');
68
+ lines.push('## Verification');
69
+ lines.push(`- Total: ${manifest.summary.total}`);
70
+ lines.push(`- Pass: ${manifest.summary.pass}`);
71
+ lines.push(`- Fail: ${manifest.summary.fail}`);
72
+ lines.push(`- Skip: ${manifest.summary.skip}`);
73
+ }
74
+ if (riskLedger && riskLedger.risks.length > 0) {
75
+ lines.push('');
76
+ lines.push('## Residual Risks');
77
+ for (const risk of riskLedger.risks) {
78
+ lines.push(`- [${risk.severity.toUpperCase()}] ${risk.description}`);
79
+ if (risk.mitigation)
80
+ lines.push(` - Mitigation: ${risk.mitigation}`);
81
+ }
82
+ }
83
+ lines.push('');
84
+ lines.push('---');
85
+ lines.push('*Generated by OXE Runtime*');
86
+ return lines;
87
+ }
88
+ buildCommitSummary(runResult, manifest, riskLedger, commitMessage = null) {
89
+ const lines = ['## OXE Commit Summary', ''];
90
+ if (commitMessage)
91
+ lines.push(`**Commit message:** \`${commitMessage}\``, '');
92
+ lines.push(...this.baseSummaryLines(runResult, manifest, riskLedger));
93
+ return lines.join('\n');
94
+ }
95
+ buildPromotionSummary(runResult, manifest, riskLedger) {
96
+ const lines = ['## OXE Promotion Summary', '', ...this.baseSummaryLines(runResult, manifest, riskLedger)];
97
+ return lines.join('\n');
98
+ }
99
+ buildPRBody(runResult, manifest, riskLedger) {
100
+ return this.buildPromotionSummary(runResult, manifest, riskLedger);
101
+ }
102
+ recordLocalCommit(runResult, manifest, riskLedger, options = {}) {
103
+ const blocked = runResult.failed.length > 0 || runResult.blocked.length > 0;
104
+ const record = {
105
+ run_id: runResult.run_id,
106
+ branch: this.branchManager.currentBranch(),
107
+ commit_sha: options.commitSha ?? this.safeCurrentCommit(),
108
+ status: blocked ? 'blocked' : 'committed',
109
+ created_at: new Date().toISOString(),
110
+ committed_at: blocked ? null : new Date().toISOString(),
111
+ message: options.commitMessage ?? null,
112
+ summary_path: options.summaryPath ?? null,
113
+ };
114
+ (0, delivery_records_1.saveCommitRecord)(this.projectRoot, runResult.run_id, record);
115
+ return record;
116
+ }
117
+ async promote(runResult, manifest, riskLedger, opts = {}, gates = [], evidenceCoverage = null) {
118
+ const gateReport = this.gateEvaluator.evaluate(runResult, manifest, riskLedger, gates, evidenceCoverage, opts.minimumCoverage ?? 100);
119
+ const targetKind = opts.targetKind ?? 'pr_draft';
120
+ const link = {
121
+ run_id: runResult.run_id,
122
+ target: 'remote_promotion',
123
+ target_kind: targetKind,
124
+ branch: this.branchManager.currentBranch(),
125
+ status: 'pending',
126
+ created_at: new Date().toISOString(),
127
+ promoted_at: null,
128
+ summary_path: null,
129
+ remote: opts.remote ?? 'origin',
130
+ target_ref: opts.targetRef ?? opts.baseBranch ?? 'main',
131
+ pr_url: null,
132
+ pr_number: null,
133
+ reasons: gateReport.reasons,
134
+ coverage_percent: evidenceCoverage ? evidenceCoverage.coverage_percent : null,
135
+ };
136
+ if (gateReport.verdict === 'blocked') {
137
+ link.status = 'blocked';
138
+ (0, delivery_records_1.savePromotionRecord)(this.projectRoot, runResult.run_id, link);
139
+ this.savePRLink(runResult.run_id, this.asRunPRLink(link));
140
+ return link;
141
+ }
142
+ if (targetKind === 'branch_push') {
143
+ try {
144
+ this.branchManager.push(opts.remote ?? 'origin', link.branch, false);
145
+ link.status = 'promoted';
146
+ link.promoted_at = new Date().toISOString();
147
+ (0, delivery_records_1.savePromotionRecord)(this.projectRoot, runResult.run_id, link);
148
+ this.savePRLink(runResult.run_id, this.asRunPRLink(link));
149
+ return link;
150
+ }
151
+ catch {
152
+ link.status = 'blocked';
153
+ (0, delivery_records_1.savePromotionRecord)(this.projectRoot, runResult.run_id, link);
154
+ this.savePRLink(runResult.run_id, this.asRunPRLink(link));
155
+ return link;
156
+ }
157
+ }
158
+ const body = this.buildPromotionSummary(runResult, manifest, riskLedger);
159
+ const title = `oxe: run ${runResult.run_id} — ${runResult.completed.length} tasks`;
160
+ const prResult = this.prManager.createDraft({
161
+ title,
162
+ body,
163
+ base: opts.baseBranch ?? 'main',
164
+ draft: opts.draftPR !== false,
165
+ });
166
+ if (!prResult.success || !prResult.url) {
167
+ link.status = 'blocked';
168
+ (0, delivery_records_1.savePromotionRecord)(this.projectRoot, runResult.run_id, link);
169
+ this.savePRLink(runResult.run_id, this.asRunPRLink(link));
170
+ return link;
171
+ }
172
+ link.pr_url = prResult.url;
173
+ link.status = 'open';
174
+ link.promoted_at = new Date().toISOString();
175
+ (0, delivery_records_1.savePromotionRecord)(this.projectRoot, runResult.run_id, link);
176
+ this.savePRLink(runResult.run_id, this.asRunPRLink(link));
177
+ return link;
178
+ }
179
+ loadCommitRecord(runId) {
180
+ return (0, delivery_records_1.loadCommitRecord)(this.projectRoot, runId);
181
+ }
182
+ loadPromotionRecord(runId) {
183
+ return (0, delivery_records_1.loadPromotionRecord)(this.projectRoot, runId);
184
+ }
185
+ savePRLink(runId, link) {
186
+ const p = path_1.default.join(this.projectRoot, '.oxe', 'runs', runId, 'pr-link.json');
187
+ fs_1.default.mkdirSync(path_1.default.dirname(p), { recursive: true });
188
+ fs_1.default.writeFileSync(p, JSON.stringify(link, null, 2), 'utf8');
189
+ }
190
+ loadPRLink(runId) {
191
+ const p = path_1.default.join(this.projectRoot, '.oxe', 'runs', runId, 'pr-link.json');
192
+ if (!fs_1.default.existsSync(p))
193
+ return null;
194
+ try {
195
+ return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
196
+ }
197
+ catch {
198
+ const promotion = (0, delivery_records_1.loadPromotionRecord)(this.projectRoot, runId);
199
+ return promotion ? this.asRunPRLink(promotion) : null;
200
+ }
201
+ }
202
+ asRunPRLink(record) {
203
+ return {
204
+ run_id: record.run_id,
205
+ branch: record.branch,
206
+ pr_url: record.pr_url,
207
+ pr_number: record.pr_number,
208
+ status: record.target_kind === 'branch_push'
209
+ ? (record.status === 'blocked' ? 'blocked' : 'open')
210
+ : (record.status === 'promoted' ? 'open' : record.status),
211
+ created_at: record.created_at,
212
+ merged_at: record.status === 'merged' ? record.promoted_at : null,
213
+ };
214
+ }
215
+ safeCurrentCommit() {
216
+ try {
217
+ return this.branchManager.currentCommit();
218
+ }
219
+ catch {
220
+ return null;
221
+ }
222
+ }
223
+ }
224
+ exports.PromotionPipeline = PromotionPipeline;