@hongmaple0820/scale-engine 0.49.0 → 0.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/api/DashboardHttpConfig.d.ts +28 -0
  4. package/dist/api/DashboardHttpConfig.js +110 -0
  5. package/dist/api/DashboardHttpConfig.js.map +1 -0
  6. package/dist/api/cli.js +102 -11
  7. package/dist/api/cli.js.map +1 -1
  8. package/dist/api/http.d.ts +1 -0
  9. package/dist/api/http.js +50 -0
  10. package/dist/api/http.js.map +1 -0
  11. package/dist/artifact/types.d.ts +5 -0
  12. package/dist/artifact/types.js.map +1 -1
  13. package/dist/bootstrap/DependencyBootstrap.d.ts +1 -0
  14. package/dist/bootstrap/DependencyBootstrap.js +14 -3
  15. package/dist/bootstrap/DependencyBootstrap.js.map +1 -1
  16. package/dist/cli/cortexApplyCommand.d.ts +26 -0
  17. package/dist/cli/cortexApplyCommand.js +74 -0
  18. package/dist/cli/cortexApplyCommand.js.map +1 -0
  19. package/dist/cli/cortexCandidateCommands.d.ts +42 -0
  20. package/dist/cli/cortexCandidateCommands.js +119 -0
  21. package/dist/cli/cortexCandidateCommands.js.map +1 -0
  22. package/dist/cli/cortexCommands.d.ts +15 -0
  23. package/dist/cli/cortexCommands.js +57 -15
  24. package/dist/cli/cortexCommands.js.map +1 -1
  25. package/dist/cli/engineBootstrap.d.ts +1 -1
  26. package/dist/cli/engineBootstrap.js +2 -0
  27. package/dist/cli/engineBootstrap.js.map +1 -1
  28. package/dist/cli/evalCommands.js +1 -0
  29. package/dist/cli/evalCommands.js.map +1 -1
  30. package/dist/cli/phaseCommands.d.ts +28 -0
  31. package/dist/cli/phaseCommands.js +148 -9
  32. package/dist/cli/phaseCommands.js.map +1 -1
  33. package/dist/cli/runtimeSkillCommands.js +12 -2
  34. package/dist/cli/runtimeSkillCommands.js.map +1 -1
  35. package/dist/cli/shieldCommands.d.ts +1 -0
  36. package/dist/cli/shieldCommands.js +20 -7
  37. package/dist/cli/shieldCommands.js.map +1 -1
  38. package/dist/cli/workflowEvidenceCommands.d.ts +120 -0
  39. package/dist/cli/workflowEvidenceCommands.js +228 -2
  40. package/dist/cli/workflowEvidenceCommands.js.map +1 -1
  41. package/dist/cortex/AutoFixEventObservations.d.ts +11 -0
  42. package/dist/cortex/AutoFixEventObservations.js +72 -0
  43. package/dist/cortex/AutoFixEventObservations.js.map +1 -0
  44. package/dist/cortex/GateEvidenceObservations.d.ts +22 -0
  45. package/dist/cortex/GateEvidenceObservations.js +179 -0
  46. package/dist/cortex/GateEvidenceObservations.js.map +1 -0
  47. package/dist/cortex/GovernanceMetrics.d.ts +2 -0
  48. package/dist/cortex/GovernanceMetrics.js +112 -22
  49. package/dist/cortex/GovernanceMetrics.js.map +1 -1
  50. package/dist/cortex/InstinctApplicationRecorder.d.ts +28 -0
  51. package/dist/cortex/InstinctApplicationRecorder.js +145 -0
  52. package/dist/cortex/InstinctApplicationRecorder.js.map +1 -0
  53. package/dist/cortex/InstinctCandidateAudit.d.ts +3 -0
  54. package/dist/cortex/InstinctCandidateAudit.js +39 -0
  55. package/dist/cortex/InstinctCandidateAudit.js.map +1 -0
  56. package/dist/cortex/InstinctCandidateReview.d.ts +32 -0
  57. package/dist/cortex/InstinctCandidateReview.js +125 -0
  58. package/dist/cortex/InstinctCandidateReview.js.map +1 -0
  59. package/dist/cortex/InstinctExtractor.d.ts +1 -0
  60. package/dist/cortex/InstinctExtractor.js +24 -17
  61. package/dist/cortex/InstinctExtractor.js.map +1 -1
  62. package/dist/cortex/InstinctRuntimeEvidence.d.ts +14 -0
  63. package/dist/cortex/InstinctRuntimeEvidence.js +120 -0
  64. package/dist/cortex/InstinctRuntimeEvidence.js.map +1 -0
  65. package/dist/cortex/InstinctStore.d.ts +18 -3
  66. package/dist/cortex/InstinctStore.js +30 -9
  67. package/dist/cortex/InstinctStore.js.map +1 -1
  68. package/dist/cortex/SessionInjector.d.ts +1 -0
  69. package/dist/cortex/SessionInjector.js +15 -2
  70. package/dist/cortex/SessionInjector.js.map +1 -1
  71. package/dist/dashboard/DashboardServer.d.ts +79 -0
  72. package/dist/dashboard/DashboardServer.js +330 -6
  73. package/dist/dashboard/DashboardServer.js.map +1 -1
  74. package/dist/dashboard/spa/app.js +515 -0
  75. package/dist/dashboard/spa/components/DataTable.js +53 -0
  76. package/dist/dashboard/spa/components/EventStream.js +66 -0
  77. package/dist/dashboard/spa/components/LoadingState.js +39 -0
  78. package/dist/dashboard/spa/components/MetricCard.js +30 -0
  79. package/dist/dashboard/spa/components/Panel.js +27 -0
  80. package/dist/dashboard/spa/components/StatusBadge.js +51 -0
  81. package/dist/dashboard/spa/i18n.js +767 -0
  82. package/dist/dashboard/spa/index.html +463 -0
  83. package/dist/dashboard/spa/pages/costs.js +522 -0
  84. package/dist/dashboard/spa/pages/documents.js +540 -0
  85. package/dist/dashboard/spa/pages/knowledge.js +457 -0
  86. package/dist/dashboard/spa/pages/monitoring.js +361 -0
  87. package/dist/dashboard/spa/pages/overview.js +301 -0
  88. package/dist/dashboard/spa/pages/topology-renderers.js +251 -0
  89. package/dist/dashboard/spa/pages/topology.js +370 -0
  90. package/dist/dashboard/spa/pages/workflow-renderers.js +239 -0
  91. package/dist/dashboard/spa/pages/workflow.js +217 -0
  92. package/dist/env/EnvironmentDoctor.js +12 -7
  93. package/dist/env/EnvironmentDoctor.js.map +1 -1
  94. package/dist/eval/WorkflowEval.d.ts +9 -0
  95. package/dist/eval/WorkflowEval.js +348 -2
  96. package/dist/eval/WorkflowEval.js.map +1 -1
  97. package/dist/memory/MemoryBrain.d.ts +13 -0
  98. package/dist/memory/MemoryBrain.js +47 -0
  99. package/dist/memory/MemoryBrain.js.map +1 -1
  100. package/dist/memory/MemoryFabric.d.ts +1 -0
  101. package/dist/memory/MemoryFabric.js +12 -8
  102. package/dist/memory/MemoryFabric.js.map +1 -1
  103. package/dist/memory/MemoryLearning.d.ts +1 -0
  104. package/dist/memory/MemoryLearning.js +6 -3
  105. package/dist/memory/MemoryLearning.js.map +1 -1
  106. package/dist/memory/MemoryProviders.d.ts +8 -1
  107. package/dist/memory/MemoryProviders.js +143 -29
  108. package/dist/memory/MemoryProviders.js.map +1 -1
  109. package/dist/runtime/AiOsRuntime.d.ts +14 -1
  110. package/dist/runtime/AiOsRuntime.js +59 -3
  111. package/dist/runtime/AiOsRuntime.js.map +1 -1
  112. package/dist/runtime/RuntimeDoctor.js +3 -1
  113. package/dist/runtime/RuntimeDoctor.js.map +1 -1
  114. package/dist/runtime/RuntimeEvidenceLedger.d.ts +6 -0
  115. package/dist/runtime/RuntimeEvidenceLedger.js +52 -1
  116. package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -1
  117. package/dist/runtime/SessionLedger.d.ts +2 -0
  118. package/dist/runtime/SessionLedger.js +4 -0
  119. package/dist/runtime/SessionLedger.js.map +1 -1
  120. package/dist/setup/SetupVerification.js +53 -5
  121. package/dist/setup/SetupVerification.js.map +1 -1
  122. package/dist/shield/PolicyCompiler.js +73 -12
  123. package/dist/shield/PolicyCompiler.js.map +1 -1
  124. package/dist/shield/ProtectedPaths.js +4 -2
  125. package/dist/shield/ProtectedPaths.js.map +1 -1
  126. package/dist/skills/SkillCatalog.d.ts +2 -0
  127. package/dist/skills/SkillCatalog.js +8 -0
  128. package/dist/skills/SkillCatalog.js.map +1 -1
  129. package/dist/skills/SkillDoctor.d.ts +19 -2
  130. package/dist/skills/SkillDoctor.js +163 -13
  131. package/dist/skills/SkillDoctor.js.map +1 -1
  132. package/dist/tools/SafeCommandRunner.d.ts +1 -0
  133. package/dist/tools/SafeCommandRunner.js +1 -0
  134. package/dist/tools/SafeCommandRunner.js.map +1 -1
  135. package/dist/tools/ToolCapabilityRegistry.js +25 -3
  136. package/dist/tools/ToolCapabilityRegistry.js.map +1 -1
  137. package/dist/tools/ToolOrchestrator.js +21 -0
  138. package/dist/tools/ToolOrchestrator.js.map +1 -1
  139. package/dist/version.d.ts +1 -1
  140. package/dist/version.js +1 -1
  141. package/dist/workflow/AgentLoopReadiness.d.ts +103 -0
  142. package/dist/workflow/AgentLoopReadiness.js +371 -0
  143. package/dist/workflow/AgentLoopReadiness.js.map +1 -0
  144. package/dist/workflow/EcosystemReadinessGate.d.ts +46 -0
  145. package/dist/workflow/EcosystemReadinessGate.js +126 -0
  146. package/dist/workflow/EcosystemReadinessGate.js.map +1 -0
  147. package/dist/workflow/EngineeringStandards.js +48 -3
  148. package/dist/workflow/EngineeringStandards.js.map +1 -1
  149. package/dist/workflow/GateCatalog.js +9 -0
  150. package/dist/workflow/GateCatalog.js.map +1 -1
  151. package/dist/workflow/GovernanceTemplatePacks.js +2 -26
  152. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
  153. package/dist/workflow/GovernanceTemplates.js +8 -1
  154. package/dist/workflow/GovernanceTemplates.js.map +1 -1
  155. package/dist/workflow/ReleaseDeploymentLedger.d.ts +63 -0
  156. package/dist/workflow/ReleaseDeploymentLedger.js +154 -0
  157. package/dist/workflow/ReleaseDeploymentLedger.js.map +1 -0
  158. package/dist/workflow/ReviewAnalyzer.js +50 -3
  159. package/dist/workflow/ReviewAnalyzer.js.map +1 -1
  160. package/dist/workflow/SessionPreamble.d.ts +7 -0
  161. package/dist/workflow/SessionPreamble.js +48 -9
  162. package/dist/workflow/SessionPreamble.js.map +1 -1
  163. package/dist/workflow/VerificationCommands.d.ts +1 -0
  164. package/dist/workflow/VerificationCommands.js.map +1 -1
  165. package/dist/workflow/VerificationProfile.d.ts +5 -0
  166. package/dist/workflow/VerificationProfile.js +26 -0
  167. package/dist/workflow/VerificationProfile.js.map +1 -1
  168. package/dist/workflow/VerificationSchema.d.ts +3 -0
  169. package/dist/workflow/VerificationSchema.js +6 -0
  170. package/dist/workflow/VerificationSchema.js.map +1 -1
  171. package/dist/workflow/WorkflowEffectiveness.d.ts +97 -0
  172. package/dist/workflow/WorkflowEffectiveness.js +302 -0
  173. package/dist/workflow/WorkflowEffectiveness.js.map +1 -0
  174. package/dist/workflow/WorkflowEffectivenessRenderer.d.ts +2 -0
  175. package/dist/workflow/WorkflowEffectivenessRenderer.js +67 -0
  176. package/dist/workflow/WorkflowEffectivenessRenderer.js.map +1 -0
  177. package/dist/workflow/WorkflowEffectivenessScoring.d.ts +6 -0
  178. package/dist/workflow/WorkflowEffectivenessScoring.js +243 -0
  179. package/dist/workflow/WorkflowEffectivenessScoring.js.map +1 -0
  180. package/dist/workflow/gates/GateSystem.d.ts +16 -0
  181. package/dist/workflow/gates/GateSystem.js +208 -41
  182. package/dist/workflow/gates/GateSystem.js.map +1 -1
  183. package/dist/workflow/gates/MetaGovernanceGates.js +269 -8
  184. package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -1
  185. package/docs/reference/cli.md +2 -1
  186. package/docs/start/agent-governance-demo.md +1 -1
  187. package/docs/workflow/README.md +1 -1
  188. package/docs/workflow/templates/github-actions-scale-preflight.yml +4 -1
  189. package/package.json +6 -3
  190. package/scripts/workflow/run-vitest.mjs +123 -0
@@ -22,6 +22,8 @@ import { JudgePromptStore, LlmJudge } from '../review/LlmJudge.js';
22
22
  import { JsonLlmClient } from '../review/JsonLlmClient.js';
23
23
  import { FreshContextVerifier } from '../review/FreshContextVerifier.js';
24
24
  import { TaskMetricsStore } from '../workflow/TaskMetricsStore.js';
25
+ import { ReleaseDeploymentLedger } from '../workflow/ReleaseDeploymentLedger.js';
26
+ import { recordRuntimeInstinctApplications } from '../cortex/InstinctApplicationRecorder.js';
25
27
  import { appendVerificationArtifact, checkTaskArtifactCompleteness, scaffoldTaskArtifacts } from '../workflow/TaskArtifactScaffolder.js';
26
28
  import { createWorkflowGuidance, renderWorkflowGuidance } from '../workflow/WorkflowGuidance.js';
27
29
  import { blockingWorkflowOpenTasks, removeWorkflowOpenTask } from '../workflow/WorkflowOpenTasks.js';
@@ -62,6 +64,7 @@ function validateReviewEvidence(ids) {
62
64
  const reviewStore = new ReviewStore(SCALE_DIR);
63
65
  const missing = [];
64
66
  const failed = [];
67
+ const records = [];
65
68
  for (const id of ids ?? []) {
66
69
  const record = reviewStore.getReview(id);
67
70
  if (!record) {
@@ -69,9 +72,14 @@ function validateReviewEvidence(ids) {
69
72
  }
70
73
  else if (!record.passed) {
71
74
  failed.push(id);
75
+ records.push(record);
76
+ }
77
+ else {
78
+ records.push(record);
72
79
  }
73
80
  }
74
- return { ok: (ids?.length ?? 0) > 0 && missing.length === 0 && failed.length === 0, missing, failed };
81
+ const latest = records.sort((a, b) => b.createdAt - a.createdAt)[0];
82
+ return { ok: (ids?.length ?? 0) > 0 && missing.length === 0 && latest?.passed === true, missing, failed };
75
83
  }
76
84
  function getValidatedReviewRecords(ids) {
77
85
  const reviewStore = new ReviewStore(SCALE_DIR);
@@ -326,6 +334,50 @@ async function recordVerificationMetric(options) {
326
334
  metricsStore.writeMarkdownReport(PROJECT_DIR);
327
335
  return record;
328
336
  }
337
+ async function recordShipDeployment(options) {
338
+ const version = optionalString(options.args['deploy-version']) ?? readPackageVersion(PROJECT_DIR);
339
+ const completedAt = optionalString(options.args['deployed-at']);
340
+ const commitTimestamp = await resolveCommitTimestamp(options.commitHash);
341
+ const notes = [
342
+ `task=${options.taskId}`,
343
+ options.taskTitle ? `title=${options.taskTitle}` : undefined,
344
+ options.taskPayload.verificationEvidenceIds?.length ? `verificationEvidence=${options.taskPayload.verificationEvidenceIds.join(',')}` : undefined,
345
+ options.taskPayload.reviewEvidenceIds?.length ? `reviewEvidence=${options.taskPayload.reviewEvidenceIds.join(',')}` : undefined,
346
+ ].filter((value) => Boolean(value)).join('; ');
347
+ return new ReleaseDeploymentLedger(SCALE_DIR).record({
348
+ service: optionalString(options.args['deploy-service']) ?? 'scale-engine',
349
+ environment: optionalString(options.args['deploy-environment']) ?? 'production',
350
+ status: 'succeeded',
351
+ version,
352
+ commitSha: options.commitHash,
353
+ commitTimestamp,
354
+ completedAt,
355
+ source: 'ship',
356
+ notes,
357
+ });
358
+ }
359
+ function optionalString(value) {
360
+ const normalized = typeof value === 'string' ? value.trim() : '';
361
+ return normalized ? normalized : undefined;
362
+ }
363
+ function readPackageVersion(projectDir) {
364
+ const pkgPath = join(projectDir, 'package.json');
365
+ if (!existsSync(pkgPath))
366
+ return undefined;
367
+ try {
368
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
369
+ return optionalString(pkg.version);
370
+ }
371
+ catch {
372
+ return undefined;
373
+ }
374
+ }
375
+ async function resolveCommitTimestamp(commitHash) {
376
+ const result = await runGit(['show', '-s', '--format=%cI', commitHash]);
377
+ if (result.exitCode !== 0)
378
+ return undefined;
379
+ return optionalString(result.stdout);
380
+ }
329
381
  // Helper: Generate spec markdown file
330
382
  function generateSpecMarkdown(id, title, payload, status = 'FROZEN') {
331
383
  return `# Spec: ${title}
@@ -1295,7 +1347,12 @@ export const phaseVerify = defineCommand({
1295
1347
  !boundaryBlocked &&
1296
1348
  !workflowOpenTasksBlocked;
1297
1349
  let transitionResult = null;
1298
- if (completionEligible) {
1350
+ const alreadyCompleted = task.status === 'COMPLETED';
1351
+ if (completionEligible && alreadyCompleted) {
1352
+ if (!args.json)
1353
+ console.log('\n FSM: already COMPLETED');
1354
+ }
1355
+ else if (completionEligible) {
1299
1356
  const completeResult = await fsm.canTransition(args['task-id'], 'complete');
1300
1357
  if (!completeResult.allowed) {
1301
1358
  if (!args.json) {
@@ -1337,7 +1394,7 @@ export const phaseVerify = defineCommand({
1337
1394
  else if (!args.json && workflowOpenTasksBlocked) {
1338
1395
  console.log('\n Workflow open tasks blocked completion - finish required workflow commands first');
1339
1396
  }
1340
- const passed = completionEligible && (transitionResult?.success ?? false);
1397
+ const passed = completionEligible && (alreadyCompleted || (transitionResult?.success ?? false));
1341
1398
  if (passed) {
1342
1399
  workflowState = workflowWriter.updateCurrentState({
1343
1400
  openTasks: removeWorkflowOpenTask(workflowState.openTasks, 'verification'),
@@ -1402,6 +1459,12 @@ export const phaseVerify = defineCommand({
1402
1459
  artifactCheck,
1403
1460
  finalGateStatus: metricGateStatus,
1404
1461
  });
1462
+ const cortexInstinctApplications = recordRuntimeInstinctApplications({
1463
+ projectDir: PROJECT_DIR,
1464
+ scaleDir: SCALE_DIR,
1465
+ phase: 'verify',
1466
+ success: passed,
1467
+ });
1405
1468
  // P0 (Decision C1): soft-map the Spec's verificationSurface against evidence.
1406
1469
  // Unmapped items are reported as warnings only — never blocking in P0.
1407
1470
  // (`spec`, `boundaryEnforcement` and `constraintCoverage` were resolved
@@ -1445,6 +1508,7 @@ export const phaseVerify = defineCommand({
1445
1508
  blocked: skillInstallationBlocked,
1446
1509
  },
1447
1510
  metric: metricRecord,
1511
+ cortexInstinctApplications,
1448
1512
  verificationSurfaceCoverage: surfaceCoverage,
1449
1513
  boundaryEnforcement,
1450
1514
  constraintCoverage,
@@ -1464,6 +1528,9 @@ export const phaseVerify = defineCommand({
1464
1528
  console.log(` ${line}`);
1465
1529
  if (metricRecord)
1466
1530
  console.log(` Metrics: ${metricRecord.taskId} ${metricRecord.finalGateStatus} (fix iterations: ${metricRecord.fixIterations})`);
1531
+ if (cortexInstinctApplications.recorded.length > 0) {
1532
+ console.log(` Cortex instincts: ${cortexInstinctApplications.recorded.length} outcome(s) recorded`);
1533
+ }
1467
1534
  if (artifactCheck && !artifactCheck.complete) {
1468
1535
  console.log(` Artifact gaps: ${artifactCheck.missing.length} missing, ${artifactCheck.incomplete.length} incomplete`);
1469
1536
  }
@@ -1525,7 +1592,13 @@ function readUntrackedFileAsDiff(path) {
1525
1592
  return '';
1526
1593
  }
1527
1594
  }
1528
- async function reviewGitChanges(taskPayload) {
1595
+ function normalizeMaxDiffFiles(value) {
1596
+ const parsed = Number.parseInt(String(value ?? ''), 10);
1597
+ if (!Number.isFinite(parsed) || parsed <= 0)
1598
+ return 200;
1599
+ return Math.min(parsed, 1000);
1600
+ }
1601
+ async function reviewGitChanges(taskPayload, maxDiffFiles = 200) {
1529
1602
  const status = await runGit(['status', '--short']);
1530
1603
  const untracked = await runGit(['ls-files', '--others', '--exclude-standard']);
1531
1604
  let statusOutput = mergeUntrackedFilesIntoStatus(status.stdout, untracked.stdout);
@@ -1548,7 +1621,7 @@ async function reviewGitChanges(taskPayload) {
1548
1621
  const verificationEvidence = getVerificationEvidenceSummary(taskPayload?.verificationEvidenceIds);
1549
1622
  const changedFiles = analyzeReview({ statusOutput, diffs: [], taskPayload, verificationEvidence }).changedFiles;
1550
1623
  const diffs = [];
1551
- for (const file of changedFiles.slice(0, 50)) {
1624
+ for (const file of changedFiles.slice(0, maxDiffFiles)) {
1552
1625
  if (file.status === '??') {
1553
1626
  diffs.push({ file: file.path, text: readUntrackedFileAsDiff(file.path) });
1554
1627
  }
@@ -1787,6 +1860,7 @@ export const phaseReview = defineCommand({
1787
1860
  brand: { type: 'string', description: 'Brand theme for HTML output (vercel/stripe/notion/linear/github)' },
1788
1861
  judge: { type: 'boolean', default: true, description: 'Run the advisory LLM-as-Judge spec-conformance check (P1.4)' },
1789
1862
  mode: { type: 'string', default: 'ai-self', description: 'Review mode: ai-self (default) | fresh-subagent | hybrid (P2.2)' },
1863
+ 'max-diff-files': { type: 'string', default: '200', description: 'Maximum changed files whose diffs are scanned during deterministic review' },
1790
1864
  json: { type: 'boolean', default: false },
1791
1865
  },
1792
1866
  async run({ args }) {
@@ -1803,7 +1877,7 @@ export const phaseReview = defineCommand({
1803
1877
  }
1804
1878
  taskPayload = task.payload;
1805
1879
  }
1806
- const review = await reviewGitChanges(taskPayload);
1880
+ const review = await reviewGitChanges(taskPayload, normalizeMaxDiffFiles(args['max-diff-files']));
1807
1881
  const karpathyContext = deriveReviewKarpathyContext(review, taskPayload);
1808
1882
  const karpathyResult = workflowEngine.checkKarpathy(karpathyContext);
1809
1883
  const karpathyReport = {
@@ -1960,6 +2034,11 @@ export const phaseShip = defineCommand({
1960
2034
  message: { type: 'string', alias: 'm', description: 'Commit message' },
1961
2035
  'no-commit': { type: 'boolean', default: false, description: 'Skip git commit' },
1962
2036
  'skip-commit': { type: 'boolean', default: false, description: 'Skip git commit' },
2037
+ 'record-deployment': { type: 'boolean', default: false, description: 'Record a deployment event after a successful ship commit' },
2038
+ 'deploy-service': { type: 'string', default: 'scale-engine', description: 'Deployment service name' },
2039
+ 'deploy-environment': { type: 'string', default: 'production', description: 'Deployment environment name' },
2040
+ 'deploy-version': { type: 'string', description: 'Deployment version override' },
2041
+ 'deployed-at': { type: 'string', description: 'Deployment completion timestamp override' },
1963
2042
  json: { type: 'boolean', default: false },
1964
2043
  },
1965
2044
  async run({ args }) {
@@ -2036,10 +2115,12 @@ export const phaseShip = defineCommand({
2036
2115
  process.exit(1);
2037
2116
  }
2038
2117
  // Git operations
2118
+ const skipCommit = shouldSkipCommit(args['skip-commit']);
2039
2119
  let commitHash = null;
2040
2120
  let stagedFiles = [];
2041
2121
  let workspaceBoundary = null;
2042
- if (!shouldSkipCommit(args['skip-commit'])) {
2122
+ let deploymentRecord = null;
2123
+ if (!skipCommit) {
2043
2124
  const commitMessage = args.message ?? `feat: ${task.title ?? args['task-id']}`;
2044
2125
  try {
2045
2126
  workspaceBoundary = await validateWorkspaceShipBoundary();
@@ -2070,7 +2151,11 @@ export const phaseShip = defineCommand({
2070
2151
  }
2071
2152
  }
2072
2153
  else {
2073
- commitHash = result.stdout.split('\n')[0]; // First line contains hash
2154
+ const head = await runGit(['rev-parse', 'HEAD']);
2155
+ if (head.exitCode !== 0 || !head.stdout.trim()) {
2156
+ throw new Error(head.stderr || 'git rev-parse HEAD failed after commit');
2157
+ }
2158
+ commitHash = head.stdout.trim();
2074
2159
  }
2075
2160
  }
2076
2161
  catch (e) {
@@ -2083,7 +2168,10 @@ export const phaseShip = defineCommand({
2083
2168
  if (task.parents.length > 0) {
2084
2169
  const planId = task.parents[0];
2085
2170
  try {
2086
- await fsm.transition(planId, 'complete', { actor: { kind: 'system', component: 'phase-ship' } });
2171
+ const plan = await store.get(planId);
2172
+ if (plan?.status !== 'DONE') {
2173
+ await fsm.transition(planId, 'complete', { actor: { kind: 'system', component: 'phase-ship' } });
2174
+ }
2087
2175
  }
2088
2176
  catch (e) {
2089
2177
  console.error("Warning: Plan completion transition failed:", e.message);
@@ -2098,6 +2186,46 @@ export const phaseShip = defineCommand({
2098
2186
  const shipSurfaceCoverage = shipSpec?.payload.verificationSurface?.length
2099
2187
  ? computeSurfaceCoverage(shipSpec.payload.verificationSurface, shipSignals)
2100
2188
  : undefined;
2189
+ if (isTruthyFlag(args['record-deployment'])) {
2190
+ if (!commitHash) {
2191
+ process.stderr.write('\nDeployment recording requires a new ship commit. Re-run without --no-commit/--skip-commit, or record a real deployment explicitly with scale workflow deploy record.\n\n');
2192
+ process.exit(1);
2193
+ }
2194
+ try {
2195
+ deploymentRecord = await recordShipDeployment({
2196
+ taskId: args['task-id'],
2197
+ taskTitle: task.title,
2198
+ taskPayload: payload,
2199
+ commitHash,
2200
+ args,
2201
+ });
2202
+ }
2203
+ catch (error) {
2204
+ process.stderr.write(`\nDeployment record failed: ${error.message}\n`);
2205
+ process.exit(1);
2206
+ }
2207
+ }
2208
+ const cortexInstinctApplications = recordRuntimeInstinctApplications({
2209
+ projectDir: PROJECT_DIR,
2210
+ scaleDir: SCALE_DIR,
2211
+ phase: 'ship',
2212
+ success: true,
2213
+ });
2214
+ const shippedAt = Date.now();
2215
+ const shipMode = skipCommit
2216
+ ? 'no-commit'
2217
+ : commitHash
2218
+ ? 'commit'
2219
+ : 'commit-skipped';
2220
+ const shippedPayload = {
2221
+ ...payload,
2222
+ shipPassed: true,
2223
+ shippedAt,
2224
+ shipMode,
2225
+ shipCommitHash: commitHash ?? undefined,
2226
+ shipDeploymentRecordId: deploymentRecord?.id,
2227
+ };
2228
+ await store.update(task.id, { payload: shippedPayload });
2101
2229
  // === WorkflowEngine Integration ===
2102
2230
  // Generate HonestDelivery report
2103
2231
  if (!args.json) {
@@ -2108,6 +2236,11 @@ export const phaseShip = defineCommand({
2108
2236
  console.log(` - Status: COMPLETED`);
2109
2237
  if (commitHash)
2110
2238
  console.log(` - Commit: ${commitHash}`);
2239
+ if (deploymentRecord)
2240
+ process.stdout.write(` - Deployment evidence: ${deploymentRecord.id}\n`);
2241
+ if (cortexInstinctApplications.recorded.length > 0) {
2242
+ console.log(` - Cortex instinct outcomes: ${cortexInstinctApplications.recorded.length}`);
2243
+ }
2111
2244
  if (stagedFiles.length)
2112
2245
  console.log(` - Files committed: ${stagedFiles.length}`);
2113
2246
  console.log('');
@@ -2148,7 +2281,10 @@ export const phaseShip = defineCommand({
2148
2281
  reviewEvidenceIds: payload.reviewEvidenceIds ?? [],
2149
2282
  reviewValidation,
2150
2283
  commitHash,
2284
+ deploymentRecord,
2151
2285
  stagedFiles,
2286
+ shippedAt,
2287
+ shipMode,
2152
2288
  workspaceBoundary: workspaceBoundary ? {
2153
2289
  topology: workspaceBoundary.report?.topology.topology ?? null,
2154
2290
  configured: workspaceBoundary.report?.topology.configured ?? false,
@@ -2157,6 +2293,7 @@ export const phaseShip = defineCommand({
2157
2293
  blockers: workspaceBoundary.blockers,
2158
2294
  warnings: workspaceBoundary.warnings,
2159
2295
  } : null,
2296
+ cortexInstinctApplications,
2160
2297
  verificationSurfaceCoverage: shipSurfaceCoverage,
2161
2298
  };
2162
2299
  if (args.json)
@@ -2166,6 +2303,8 @@ export const phaseShip = defineCommand({
2166
2303
  console.log('\nTask COMPLETED: ' + args['task-id']);
2167
2304
  if (commitHash)
2168
2305
  console.log(' Commit: ' + commitHash);
2306
+ if (deploymentRecord)
2307
+ process.stdout.write(' Deployment evidence: ' + deploymentRecord.id + '\n');
2169
2308
  console.log('\nDone. Feature shipped.\n');
2170
2309
  }
2171
2310
  },