@ai-sdlc/orchestrator 0.6.0 → 0.10.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 (209) hide show
  1. package/dist/__test-helpers/git-env.d.ts +40 -0
  2. package/dist/__test-helpers/git-env.js +73 -0
  3. package/dist/admission-composite.d.ts +89 -0
  4. package/dist/admission-composite.js +241 -0
  5. package/dist/admission-enrichment.d.ts +142 -0
  6. package/dist/admission-enrichment.js +341 -0
  7. package/dist/admission-hc.d.ts +81 -0
  8. package/dist/admission-hc.js +94 -0
  9. package/dist/admission-score.d.ts +109 -5
  10. package/dist/admission-score.js +90 -11
  11. package/dist/analysis/analyzer.js +3 -2
  12. package/dist/analysis/convention-detector.d.ts +85 -2
  13. package/dist/analysis/convention-detector.js +375 -70
  14. package/dist/analysis/diff-analyzer.d.ts +33 -0
  15. package/dist/analysis/diff-analyzer.js +122 -0
  16. package/dist/analysis/hotspot-analyzer.js +3 -1
  17. package/dist/analysis/index.d.ts +2 -1
  18. package/dist/analysis/index.js +2 -1
  19. package/dist/artifacts/index.d.ts +65 -0
  20. package/dist/artifacts/index.js +142 -0
  21. package/dist/backlog-adapter.d.ts +121 -0
  22. package/dist/backlog-adapter.js +438 -0
  23. package/dist/calibration.d.ts +43 -0
  24. package/dist/calibration.js +76 -0
  25. package/dist/cli/commands/agents.d.ts +24 -0
  26. package/dist/cli/commands/agents.js +66 -1
  27. package/dist/cli/commands/git-remote.d.ts +74 -0
  28. package/dist/cli/commands/git-remote.js +170 -0
  29. package/dist/cli/commands/health.d.ts +4 -0
  30. package/dist/cli/commands/health.js +13 -1
  31. package/dist/cli/commands/init-features.d.ts +208 -0
  32. package/dist/cli/commands/init-features.js +473 -0
  33. package/dist/cli/commands/init-templates.d.ts +104 -0
  34. package/dist/cli/commands/init-templates.js +399 -0
  35. package/dist/cli/commands/init.d.ts +48 -0
  36. package/dist/cli/commands/init.js +322 -23
  37. package/dist/cli/commands/mcp-setup.d.ts +31 -0
  38. package/dist/cli/commands/mcp-setup.js +78 -8
  39. package/dist/cli/formatters/table.js +15 -2
  40. package/dist/cli/index.d.ts +14 -1
  41. package/dist/cli/index.js +81 -20
  42. package/dist/cli/versions.d.ts +57 -0
  43. package/dist/cli/versions.js +128 -0
  44. package/dist/code-area-classifier.d.ts +21 -0
  45. package/dist/code-area-classifier.js +48 -0
  46. package/dist/config.d.ts +33 -1
  47. package/dist/config.js +78 -8
  48. package/dist/database/adapters/external.d.ts +24 -0
  49. package/dist/database/adapters/external.js +80 -0
  50. package/dist/database/adapters/neon.d.ts +41 -0
  51. package/dist/database/adapters/neon.js +98 -0
  52. package/dist/database/adapters/pg-snapshot-restore.d.ts +28 -0
  53. package/dist/database/adapters/pg-snapshot-restore.js +68 -0
  54. package/dist/database/adapters/sqlite-copy.d.ts +32 -0
  55. package/dist/database/adapters/sqlite-copy.js +145 -0
  56. package/dist/database/connection-injection.d.ts +35 -0
  57. package/dist/database/connection-injection.js +93 -0
  58. package/dist/database/index.d.ts +12 -0
  59. package/dist/database/index.js +23 -0
  60. package/dist/database/registry.d.ts +13 -0
  61. package/dist/database/registry.js +27 -0
  62. package/dist/database/topology.d.ts +52 -0
  63. package/dist/database/topology.js +44 -0
  64. package/dist/database/types.d.ts +89 -0
  65. package/dist/database/types.js +26 -0
  66. package/dist/design-authority.d.ts +53 -0
  67. package/dist/design-authority.js +84 -0
  68. package/dist/design-lookahead.d.ts +64 -0
  69. package/dist/design-lookahead.js +86 -0
  70. package/dist/design-quality-trend.d.ts +87 -0
  71. package/dist/design-quality-trend.js +190 -0
  72. package/dist/design-system-context.d.ts +46 -0
  73. package/dist/design-system-context.js +80 -0
  74. package/dist/design-system-correction-loop.d.ts +64 -0
  75. package/dist/design-system-correction-loop.js +128 -0
  76. package/dist/design-system-metrics.d.ts +61 -0
  77. package/dist/design-system-metrics.js +104 -0
  78. package/dist/design-system-stewardship.d.ts +22 -0
  79. package/dist/design-system-stewardship.js +85 -0
  80. package/dist/design-system-validation.d.ts +37 -0
  81. package/dist/design-system-validation.js +88 -0
  82. package/dist/dispatch/index.d.ts +4 -0
  83. package/dist/dispatch/index.js +4 -0
  84. package/dist/dispatch/merge-gate.d.ts +46 -0
  85. package/dist/dispatch/merge-gate.js +90 -0
  86. package/dist/dispatch/requeue.d.ts +57 -0
  87. package/dist/dispatch/requeue.js +131 -0
  88. package/dist/dispatch/worker-pool.d.ts +62 -0
  89. package/dist/dispatch/worker-pool.js +60 -0
  90. package/dist/execute.d.ts +40 -0
  91. package/dist/execute.js +188 -15
  92. package/dist/fix-ci.js +8 -1
  93. package/dist/fix-review.js +8 -1
  94. package/dist/harness/adapters/claude-code.d.ts +29 -0
  95. package/dist/harness/adapters/claude-code.js +191 -0
  96. package/dist/harness/adapters/codex.d.ts +25 -0
  97. package/dist/harness/adapters/codex.js +61 -0
  98. package/dist/harness/independence.d.ts +51 -0
  99. package/dist/harness/independence.js +67 -0
  100. package/dist/harness/index.d.ts +14 -0
  101. package/dist/harness/index.js +20 -0
  102. package/dist/harness/registry.d.ts +17 -0
  103. package/dist/harness/registry.js +31 -0
  104. package/dist/harness/types.d.ts +123 -0
  105. package/dist/harness/types.js +8 -0
  106. package/dist/harness/version-probe.d.ts +14 -0
  107. package/dist/harness/version-probe.js +123 -0
  108. package/dist/index.d.ts +30 -4
  109. package/dist/index.js +35 -2
  110. package/dist/models/classifier.d.ts +78 -0
  111. package/dist/models/classifier.js +277 -0
  112. package/dist/models/index.d.ts +3 -0
  113. package/dist/models/index.js +3 -0
  114. package/dist/models/registry.d.ts +97 -0
  115. package/dist/models/registry.js +173 -0
  116. package/dist/pillar-breakdown.d.ts +85 -0
  117. package/dist/pillar-breakdown.js +162 -0
  118. package/dist/priority.d.ts +5 -0
  119. package/dist/priority.js +18 -5
  120. package/dist/review-meta.d.ts +65 -0
  121. package/dist/review-meta.js +149 -0
  122. package/dist/review.d.ts +4 -0
  123. package/dist/review.js +12 -2
  124. package/dist/runners/claude-code-sdk.d.ts +31 -0
  125. package/dist/runners/claude-code-sdk.js +238 -0
  126. package/dist/runners/claude-code.d.ts +3 -0
  127. package/dist/runners/claude-code.js +30 -66
  128. package/dist/runners/codex.js +4 -1
  129. package/dist/runners/copilot.js +4 -1
  130. package/dist/runners/cursor.js +4 -1
  131. package/dist/runners/git-utils.d.ts +81 -0
  132. package/dist/runners/git-utils.js +201 -0
  133. package/dist/runners/index.d.ts +3 -0
  134. package/dist/runners/index.js +3 -0
  135. package/dist/runners/review-agent.d.ts +20 -0
  136. package/dist/runners/review-agent.js +171 -41
  137. package/dist/runners/runner-registry.js +10 -0
  138. package/dist/runners/sdk-review-runner.d.ts +65 -0
  139. package/dist/runners/sdk-review-runner.js +185 -0
  140. package/dist/runners/security-triage.d.ts +20 -4
  141. package/dist/runners/security-triage.js +39 -15
  142. package/dist/runners/types.d.ts +6 -0
  143. package/dist/runtime/attestations.d.ts +766 -0
  144. package/dist/runtime/attestations.js +1195 -0
  145. package/dist/runtime/git-env.d.ts +53 -0
  146. package/dist/runtime/git-env.js +60 -0
  147. package/dist/runtime/index.d.ts +7 -0
  148. package/dist/runtime/index.js +7 -0
  149. package/dist/runtime/parallelism-flag.d.ts +28 -0
  150. package/dist/runtime/parallelism-flag.js +39 -0
  151. package/dist/runtime/port-allocator.d.ts +32 -0
  152. package/dist/runtime/port-allocator.js +96 -0
  153. package/dist/runtime/worktree-pool.d.ts +86 -0
  154. package/dist/runtime/worktree-pool.js +204 -0
  155. package/dist/runtime/worktree.d.ts +25 -0
  156. package/dist/runtime/worktree.js +111 -0
  157. package/dist/sa-scoring/auto-calibrate.d.ts +69 -0
  158. package/dist/sa-scoring/auto-calibrate.js +107 -0
  159. package/dist/sa-scoring/c1-sa2-computable.d.ts +42 -0
  160. package/dist/sa-scoring/c1-sa2-computable.js +59 -0
  161. package/dist/sa-scoring/composite.d.ts +107 -0
  162. package/dist/sa-scoring/composite.js +139 -0
  163. package/dist/sa-scoring/depparse-client.d.ts +79 -0
  164. package/dist/sa-scoring/depparse-client.js +187 -0
  165. package/dist/sa-scoring/did-compiler.d.ts +122 -0
  166. package/dist/sa-scoring/did-compiler.js +286 -0
  167. package/dist/sa-scoring/drift-monitor.d.ts +84 -0
  168. package/dist/sa-scoring/drift-monitor.js +186 -0
  169. package/dist/sa-scoring/exemplar-bank.d.ts +78 -0
  170. package/dist/sa-scoring/exemplar-bank.js +154 -0
  171. package/dist/sa-scoring/feedback-store.d.ts +100 -0
  172. package/dist/sa-scoring/feedback-store.js +156 -0
  173. package/dist/sa-scoring/index.d.ts +71 -0
  174. package/dist/sa-scoring/index.js +158 -0
  175. package/dist/sa-scoring/layer1-deterministic.d.ts +115 -0
  176. package/dist/sa-scoring/layer1-deterministic.js +298 -0
  177. package/dist/sa-scoring/layer2-structural.d.ts +71 -0
  178. package/dist/sa-scoring/layer2-structural.js +151 -0
  179. package/dist/sa-scoring/layer3-llm.d.ts +86 -0
  180. package/dist/sa-scoring/layer3-llm.js +282 -0
  181. package/dist/sa-scoring/rescore-orchestrator.d.ts +52 -0
  182. package/dist/sa-scoring/rescore-orchestrator.js +47 -0
  183. package/dist/scheduling/burn-down.d.ts +27 -0
  184. package/dist/scheduling/burn-down.js +43 -0
  185. package/dist/scheduling/calibration.d.ts +42 -0
  186. package/dist/scheduling/calibration.js +150 -0
  187. package/dist/scheduling/index.d.ts +8 -0
  188. package/dist/scheduling/index.js +8 -0
  189. package/dist/scheduling/ledger.d.ts +59 -0
  190. package/dist/scheduling/ledger.js +216 -0
  191. package/dist/scheduling/off-peak.d.ts +27 -0
  192. package/dist/scheduling/off-peak.js +112 -0
  193. package/dist/scheduling/schedule-decision.d.ts +39 -0
  194. package/dist/scheduling/schedule-decision.js +89 -0
  195. package/dist/scheduling/tier-analysis.d.ts +47 -0
  196. package/dist/scheduling/tier-analysis.js +81 -0
  197. package/dist/scheduling/types.d.ts +140 -0
  198. package/dist/scheduling/types.js +11 -0
  199. package/dist/shared.d.ts +13 -0
  200. package/dist/shared.js +32 -0
  201. package/dist/state/schema.d.ts +5 -1
  202. package/dist/state/schema.js +223 -1
  203. package/dist/state/store.d.ts +55 -1
  204. package/dist/state/store.js +342 -7
  205. package/dist/state/types.d.ts +139 -0
  206. package/dist/types.d.ts +1 -1
  207. package/dist/validate-agent-output.js +4 -1
  208. package/dist/watch.js +6 -0
  209. package/package.json +3 -2
@@ -27,6 +27,13 @@ export class StateStore {
27
27
  return new StateStore(pathOrDb);
28
28
  }
29
29
  migrate() {
30
+ // Each migration runs atomically: DDL + schema_version insert in one
31
+ // transaction so a crash mid-migration can't leave the DB in a
32
+ // half-applied state where the version row lies about actual schema.
33
+ const applyMigration = this.db.transaction((migration) => {
34
+ this.db.exec(migration.sql);
35
+ this.db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(migration.version);
36
+ });
30
37
  // Check current schema version
31
38
  try {
32
39
  const row = this.db.prepare('SELECT MAX(version) as v FROM schema_version').get();
@@ -35,16 +42,14 @@ export class StateStore {
35
42
  return;
36
43
  for (const migration of MIGRATIONS) {
37
44
  if (migration.version > (current ?? 0)) {
38
- this.db.exec(migration.sql);
39
- this.db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(migration.version);
45
+ applyMigration(migration);
40
46
  }
41
47
  }
42
48
  }
43
49
  catch {
44
50
  // Table doesn't exist yet — run all migrations
45
51
  for (const migration of MIGRATIONS) {
46
- this.db.exec(migration.sql);
47
- this.db.prepare('INSERT INTO schema_version (version) VALUES (?)').run(migration.version);
52
+ applyMigration(migration);
48
53
  }
49
54
  }
50
55
  }
@@ -316,10 +321,10 @@ export class StateStore {
316
321
  // ── Cost Ledger ────────────────────────────────────────────────
317
322
  saveCostEntry(entry) {
318
323
  const stmt = this.db.prepare(`
319
- INSERT INTO cost_ledger (run_id, agent_name, pipeline_type, model, input_tokens, output_tokens, total_tokens, cost_usd, issue_id, issue_number, pr_number, stage_name, cache_read_tokens)
320
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
324
+ INSERT INTO cost_ledger (run_id, agent_name, pipeline_type, model, model_alias, input_tokens, output_tokens, total_tokens, cost_usd, shadow_cost_usd, issue_id, issue_number, pr_number, stage_name, cache_read_tokens)
325
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
321
326
  `);
322
- const result = stmt.run(entry.runId, entry.agentName, entry.pipelineType, entry.model ?? null, entry.inputTokens ?? 0, entry.outputTokens ?? 0, entry.totalTokens ?? 0, entry.costUsd ?? 0, entry.issueId ?? null, entry.issueNumber ?? null, entry.prNumber ?? null, entry.stageName ?? null, entry.cacheReadTokens ?? 0);
327
+ const result = stmt.run(entry.runId, entry.agentName, entry.pipelineType, entry.model ?? null, entry.modelAlias ?? null, entry.inputTokens ?? 0, entry.outputTokens ?? 0, entry.totalTokens ?? 0, entry.costUsd ?? 0, entry.shadowCostUsd ?? null, entry.issueId ?? null, entry.issueNumber ?? null, entry.prNumber ?? null, entry.stageName ?? null, entry.cacheReadTokens ?? 0);
323
328
  return Number(result.lastInsertRowid);
324
329
  }
325
330
  getCostEntries(opts) {
@@ -361,10 +366,12 @@ export class StateStore {
361
366
  agentName: row.agent_name,
362
367
  pipelineType: row.pipeline_type,
363
368
  model: row.model,
369
+ modelAlias: row.model_alias,
364
370
  inputTokens: row.input_tokens,
365
371
  outputTokens: row.output_tokens,
366
372
  totalTokens: row.total_tokens,
367
373
  costUsd: row.cost_usd,
374
+ shadowCostUsd: row.shadow_cost_usd,
368
375
  issueId: row.issue_id,
369
376
  issueNumber: row.issue_number,
370
377
  prNumber: row.pr_number,
@@ -833,6 +840,334 @@ export class StateStore {
833
840
  .prepare(`UPDATE pattern_proposals SET status = ?, reviewed_at = datetime('now'), reviewer_reason = ? WHERE id = ?`)
834
841
  .run(status, reason ?? null, id);
835
842
  }
843
+ // ── Design System Governance (RFC-0006) ───────────────────────────
844
+ insertDesignTokenEvent(record) {
845
+ const result = this.db
846
+ .prepare(`INSERT INTO design_token_events (binding_name, event_type, tokens_affected, diff_json, actor, pipeline_run_id, design_review_decision)
847
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
848
+ .run(record.bindingName, record.eventType, record.tokensAffected ?? 0, record.diffJson ?? null, record.actor ?? null, record.pipelineRunId ?? null, record.designReviewDecision ?? null);
849
+ return result.lastInsertRowid;
850
+ }
851
+ getDesignTokenEvents(bindingName, limit = 50) {
852
+ return this.db
853
+ .prepare(`SELECT * FROM design_token_events WHERE binding_name = ? ORDER BY created_at DESC LIMIT ?`)
854
+ .all(bindingName, limit);
855
+ }
856
+ insertDesignReviewEvent(record) {
857
+ const result = this.db
858
+ .prepare(`INSERT INTO design_review_events (binding_name, pr_number, component_name, reviewer, decision, categories_json, actionable_notes)
859
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
860
+ .run(record.bindingName, record.prNumber ?? null, record.componentName ?? null, record.reviewer, record.decision, record.categoriesJson ?? null, record.actionableNotes ?? null);
861
+ return result.lastInsertRowid;
862
+ }
863
+ getDesignReviewEvents(bindingName, limit = 50) {
864
+ return this.db
865
+ .prepare(`SELECT * FROM design_review_events WHERE binding_name = ? ORDER BY created_at DESC LIMIT ?`)
866
+ .all(bindingName, limit);
867
+ }
868
+ insertTokenComplianceSnapshot(record) {
869
+ const result = this.db
870
+ .prepare(`INSERT INTO token_compliance_history (binding_name, coverage_percent, violations_count) VALUES (?, ?, ?)`)
871
+ .run(record.bindingName, record.coveragePercent, record.violationsCount);
872
+ return result.lastInsertRowid;
873
+ }
874
+ getTokenComplianceHistory(bindingName, limit = 50) {
875
+ return this.db
876
+ .prepare(`SELECT * FROM token_compliance_history WHERE binding_name = ? ORDER BY scanned_at DESC LIMIT ?`)
877
+ .all(bindingName, limit);
878
+ }
879
+ insertVisualRegressionResult(record) {
880
+ const result = this.db
881
+ .prepare(`INSERT INTO visual_regression_results (binding_name, story_name, viewport, diff_percentage, approved, approver, baseline_url, current_url)
882
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
883
+ .run(record.bindingName, record.storyName, record.viewport ?? null, record.diffPercentage, record.approved ? 1 : 0, record.approver ?? null, record.baselineUrl ?? null, record.currentUrl ?? null);
884
+ return result.lastInsertRowid;
885
+ }
886
+ getVisualRegressionResults(bindingName, limit = 50) {
887
+ return this.db
888
+ .prepare(`SELECT * FROM visual_regression_results WHERE binding_name = ? ORDER BY created_at DESC LIMIT ?`)
889
+ .all(bindingName, limit);
890
+ }
891
+ insertUsabilitySimulationResult(record) {
892
+ const result = this.db
893
+ .prepare(`INSERT INTO usability_simulation_results (binding_name, story_name, persona_id, task_id, completed, actions_taken, expected_actions, efficiency, findings_json)
894
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
895
+ .run(record.bindingName, record.storyName, record.personaId ?? null, record.taskId ?? null, record.completed ? 1 : 0, record.actionsTaken ?? null, record.expectedActions ?? null, record.efficiency ?? null, record.findingsJson ?? null);
896
+ return result.lastInsertRowid;
897
+ }
898
+ getUsabilitySimulationResults(bindingName, limit = 50) {
899
+ return this.db
900
+ .prepare(`SELECT * FROM usability_simulation_results WHERE binding_name = ? ORDER BY created_at DESC LIMIT ?`)
901
+ .all(bindingName, limit);
902
+ }
903
+ // ── PPA Triad Integration (RFC-0008) ─────────────────────────────────
904
+ insertDidCompiledArtifact(record) {
905
+ const result = this.db
906
+ .prepare(`INSERT INTO did_compiled_artifacts (did_name, namespace, source_hash, scope_lists_json, constraint_rules_json, anti_pattern_lists_json, measurable_signals_json, bm25_corpus_blob, principle_corpora_blob)
907
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
908
+ .run(record.didName, record.namespace ?? null, record.sourceHash, record.scopeListsJson ?? null, record.constraintRulesJson ?? null, record.antiPatternListsJson ?? null, record.measurableSignalsJson ?? null, record.bm25CorpusBlob ?? null, record.principleCorporaBlob ?? null);
909
+ return Number(result.lastInsertRowid);
910
+ }
911
+ getLatestDidCompiledArtifact(didName) {
912
+ const row = this.db
913
+ .prepare(`SELECT * FROM did_compiled_artifacts WHERE did_name = ? ORDER BY compiled_at DESC, id DESC LIMIT 1`)
914
+ .get(didName);
915
+ return row ? this.mapDidCompiledArtifact(row) : undefined;
916
+ }
917
+ getDidCompiledArtifactByHash(didName, sourceHash) {
918
+ const row = this.db
919
+ .prepare(`SELECT * FROM did_compiled_artifacts WHERE did_name = ? AND source_hash = ? ORDER BY compiled_at DESC, id DESC LIMIT 1`)
920
+ .get(didName, sourceHash);
921
+ return row ? this.mapDidCompiledArtifact(row) : undefined;
922
+ }
923
+ mapDidCompiledArtifact(row) {
924
+ return {
925
+ id: row.id,
926
+ didName: row.did_name,
927
+ namespace: row.namespace,
928
+ sourceHash: row.source_hash,
929
+ scopeListsJson: row.scope_lists_json,
930
+ constraintRulesJson: row.constraint_rules_json,
931
+ antiPatternListsJson: row.anti_pattern_lists_json,
932
+ measurableSignalsJson: row.measurable_signals_json,
933
+ bm25CorpusBlob: row.bm25_corpus_blob,
934
+ principleCorporaBlob: row.principle_corpora_blob,
935
+ compiledAt: row.compiled_at,
936
+ };
937
+ }
938
+ recordDidScoringEvent(record) {
939
+ const result = this.db
940
+ .prepare(`INSERT INTO did_scoring_events (did_name, issue_number, sa_dimension, phase, layer1_result_json, layer2_result_json, layer3_result_json, composite_score, phase_weights_json)
941
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
942
+ .run(record.didName, record.issueNumber, record.saDimension, record.phase, record.layer1ResultJson ?? null, record.layer2ResultJson ?? null, record.layer3ResultJson ?? null, record.compositeScore ?? null, record.phaseWeightsJson ?? null);
943
+ return Number(result.lastInsertRowid);
944
+ }
945
+ getDidScoringEvents(opts) {
946
+ const conditions = [];
947
+ const params = [];
948
+ if (opts?.didName) {
949
+ conditions.push('did_name = ?');
950
+ params.push(opts.didName);
951
+ }
952
+ if (opts?.issueNumber !== undefined) {
953
+ conditions.push('issue_number = ?');
954
+ params.push(opts.issueNumber);
955
+ }
956
+ if (opts?.saDimension) {
957
+ conditions.push('sa_dimension = ?');
958
+ params.push(opts.saDimension);
959
+ }
960
+ if (opts?.since) {
961
+ conditions.push('created_at >= ?');
962
+ params.push(opts.since);
963
+ }
964
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
965
+ const limit = opts?.limit ?? 100;
966
+ params.push(limit);
967
+ const rows = this.db
968
+ .prepare(`SELECT * FROM did_scoring_events ${where} ORDER BY created_at DESC, id DESC LIMIT ?`)
969
+ .all(...params);
970
+ return rows.map((r) => ({
971
+ id: r.id,
972
+ didName: r.did_name,
973
+ issueNumber: r.issue_number,
974
+ saDimension: r.sa_dimension,
975
+ phase: r.phase,
976
+ layer1ResultJson: r.layer1_result_json,
977
+ layer2ResultJson: r.layer2_result_json,
978
+ layer3ResultJson: r.layer3_result_json,
979
+ compositeScore: r.composite_score,
980
+ phaseWeightsJson: r.phase_weights_json,
981
+ createdAt: r.created_at,
982
+ }));
983
+ }
984
+ recordDidFeedback(record) {
985
+ const result = this.db
986
+ .prepare(`INSERT INTO did_feedback_events (did_name, issue_number, dimension, signal, principal, category, structural_score, llm_score, composite_score, notes)
987
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
988
+ .run(record.didName, record.issueNumber, record.dimension, record.signal, record.principal ?? null, record.category ?? null, record.structuralScore ?? null, record.llmScore ?? null, record.compositeScore ?? null, record.notes ?? null);
989
+ return Number(result.lastInsertRowid);
990
+ }
991
+ getDidFeedbackEvents(opts) {
992
+ const conditions = [];
993
+ const params = [];
994
+ if (opts?.didName) {
995
+ conditions.push('did_name = ?');
996
+ params.push(opts.didName);
997
+ }
998
+ if (opts?.issueNumber !== undefined) {
999
+ conditions.push('issue_number = ?');
1000
+ params.push(opts.issueNumber);
1001
+ }
1002
+ if (opts?.signal) {
1003
+ conditions.push('signal = ?');
1004
+ params.push(opts.signal);
1005
+ }
1006
+ if (opts?.dimension) {
1007
+ conditions.push('dimension = ?');
1008
+ params.push(opts.dimension);
1009
+ }
1010
+ if (opts?.since) {
1011
+ conditions.push('created_at >= ?');
1012
+ params.push(opts.since);
1013
+ }
1014
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
1015
+ const limit = opts?.limit ?? 500;
1016
+ params.push(limit);
1017
+ const rows = this.db
1018
+ .prepare(`SELECT * FROM did_feedback_events ${where} ORDER BY created_at DESC, id DESC LIMIT ?`)
1019
+ .all(...params);
1020
+ return rows.map((r) => ({
1021
+ id: r.id,
1022
+ didName: r.did_name,
1023
+ issueNumber: r.issue_number,
1024
+ dimension: r.dimension,
1025
+ signal: r.signal,
1026
+ principal: r.principal,
1027
+ category: r.category,
1028
+ structuralScore: r.structural_score,
1029
+ llmScore: r.llm_score,
1030
+ compositeScore: r.composite_score,
1031
+ notes: r.notes,
1032
+ createdAt: r.created_at,
1033
+ }));
1034
+ }
1035
+ recordDesignChange(record) {
1036
+ const result = this.db
1037
+ .prepare(`INSERT INTO design_change_events (did_name, change_id, change_type, status, payload_json)
1038
+ VALUES (?, ?, ?, ?, ?)`)
1039
+ .run(record.didName, record.changeId, record.changeType, record.status, record.payloadJson);
1040
+ return Number(result.lastInsertRowid);
1041
+ }
1042
+ getDesignChangeEvents(opts) {
1043
+ const conditions = [];
1044
+ const params = [];
1045
+ if (opts?.didName) {
1046
+ conditions.push('did_name = ?');
1047
+ params.push(opts.didName);
1048
+ }
1049
+ if (opts?.changeId) {
1050
+ conditions.push('change_id = ?');
1051
+ params.push(opts.changeId);
1052
+ }
1053
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
1054
+ const limit = opts?.limit ?? 100;
1055
+ params.push(limit);
1056
+ const rows = this.db
1057
+ .prepare(`SELECT * FROM design_change_events ${where} ORDER BY emitted_at DESC, id DESC LIMIT ?`)
1058
+ .all(...params);
1059
+ return rows.map((r) => ({
1060
+ id: r.id,
1061
+ didName: r.did_name,
1062
+ changeId: r.change_id,
1063
+ changeType: r.change_type,
1064
+ status: r.status,
1065
+ payloadJson: r.payload_json,
1066
+ emittedAt: r.emitted_at,
1067
+ }));
1068
+ }
1069
+ insertCodeAreaMetrics(record) {
1070
+ const result = this.db
1071
+ .prepare(`INSERT INTO code_area_metrics (code_area, defect_density, churn_rate, pr_rejection_rate, code_acceptance_rate, has_frontend_components, design_metrics_json, data_point_count, window_start, window_end)
1072
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1073
+ .run(record.codeArea, record.defectDensity ?? null, record.churnRate ?? null, record.prRejectionRate ?? null, record.codeAcceptanceRate ?? null, record.hasFrontendComponents ? 1 : 0, record.designMetricsJson ?? null, record.dataPointCount ?? 0, record.windowStart ?? null, record.windowEnd ?? null);
1074
+ return Number(result.lastInsertRowid);
1075
+ }
1076
+ /**
1077
+ * Get the most recent metrics snapshot for a code area.
1078
+ * `since` filters to rows where `computed_at >= since`.
1079
+ */
1080
+ getCodeAreaMetrics(codeArea, opts) {
1081
+ const conditions = ['code_area = ?'];
1082
+ const params = [codeArea];
1083
+ if (opts?.since) {
1084
+ conditions.push('computed_at >= ?');
1085
+ params.push(opts.since);
1086
+ }
1087
+ const row = this.db
1088
+ .prepare(`SELECT * FROM code_area_metrics WHERE ${conditions.join(' AND ')} ORDER BY computed_at DESC, id DESC LIMIT 1`)
1089
+ .get(...params);
1090
+ return row ? this.mapCodeAreaMetrics(row) : undefined;
1091
+ }
1092
+ getCodeAreaMetricsHistory(codeArea, opts) {
1093
+ const conditions = ['code_area = ?'];
1094
+ const params = [codeArea];
1095
+ if (opts?.since) {
1096
+ conditions.push('computed_at >= ?');
1097
+ params.push(opts.since);
1098
+ }
1099
+ const limit = opts?.limit ?? 100;
1100
+ params.push(limit);
1101
+ const rows = this.db
1102
+ .prepare(`SELECT * FROM code_area_metrics WHERE ${conditions.join(' AND ')} ORDER BY computed_at DESC, id DESC LIMIT ?`)
1103
+ .all(...params);
1104
+ return rows.map((r) => this.mapCodeAreaMetrics(r));
1105
+ }
1106
+ mapCodeAreaMetrics(row) {
1107
+ return {
1108
+ id: row.id,
1109
+ codeArea: row.code_area,
1110
+ defectDensity: row.defect_density,
1111
+ churnRate: row.churn_rate,
1112
+ prRejectionRate: row.pr_rejection_rate,
1113
+ codeAcceptanceRate: row.code_acceptance_rate,
1114
+ hasFrontendComponents: Boolean(row.has_frontend_components),
1115
+ designMetricsJson: row.design_metrics_json,
1116
+ dataPointCount: row.data_point_count,
1117
+ windowStart: row.window_start,
1118
+ windowEnd: row.window_end,
1119
+ computedAt: row.computed_at,
1120
+ };
1121
+ }
1122
+ upsertDesignLookaheadNotification(record) {
1123
+ const result = this.db
1124
+ .prepare(`INSERT INTO design_lookahead_notifications (issue_number, pillar_breakdown_json)
1125
+ VALUES (?, ?)
1126
+ ON CONFLICT(issue_number) DO UPDATE SET
1127
+ last_notified_at = datetime('now'),
1128
+ pillar_breakdown_json = COALESCE(excluded.pillar_breakdown_json, pillar_breakdown_json)`)
1129
+ .run(record.issueNumber, record.pillarBreakdownJson ?? null);
1130
+ return Number(result.lastInsertRowid);
1131
+ }
1132
+ getDesignLookaheadNotification(issueNumber) {
1133
+ const row = this.db
1134
+ .prepare(`SELECT * FROM design_lookahead_notifications WHERE issue_number = ?`)
1135
+ .get(issueNumber);
1136
+ if (!row)
1137
+ return undefined;
1138
+ return {
1139
+ id: row.id,
1140
+ issueNumber: row.issue_number,
1141
+ firstNotifiedAt: row.first_notified_at,
1142
+ lastNotifiedAt: row.last_notified_at,
1143
+ pillarBreakdownJson: row.pillar_breakdown_json,
1144
+ };
1145
+ }
1146
+ // ── SA Phase Weights (RFC-0008 §B.8 AISDLC-66) ──────────────────────
1147
+ upsertSaPhaseWeights(record) {
1148
+ this.db
1149
+ .prepare(`INSERT INTO sa_phase_weights (dimension, w_structural, w_llm, calibrated_at)
1150
+ VALUES (?, ?, ?, datetime('now'))
1151
+ ON CONFLICT(dimension) DO UPDATE SET
1152
+ w_structural = excluded.w_structural,
1153
+ w_llm = excluded.w_llm,
1154
+ calibrated_at = excluded.calibrated_at`)
1155
+ .run(record.dimension, record.wStructural, record.wLlm);
1156
+ }
1157
+ getSaPhaseWeights(dimension) {
1158
+ const row = this.db
1159
+ .prepare(`SELECT * FROM sa_phase_weights WHERE dimension = ?`)
1160
+ .get(dimension);
1161
+ if (!row)
1162
+ return undefined;
1163
+ return {
1164
+ id: row.id,
1165
+ dimension: row.dimension,
1166
+ wStructural: row.w_structural,
1167
+ wLlm: row.w_llm,
1168
+ calibratedAt: row.calibrated_at,
1169
+ };
1170
+ }
836
1171
  close() {
837
1172
  this.db.close();
838
1173
  }
@@ -113,11 +113,16 @@ export interface CostLedgerEntry {
113
113
  runId: string;
114
114
  agentName: string;
115
115
  pipelineType: string;
116
+ /** Resolved physical model ID (e.g., 'claude-sonnet-4-6'). RFC-0010 §11.4. */
116
117
  model?: string;
118
+ /** Original alias used in pipeline YAML before resolution (e.g., 'sonnet'). RFC-0010 §11.4. */
119
+ modelAlias?: string;
117
120
  inputTokens?: number;
118
121
  outputTokens?: number;
119
122
  totalTokens?: number;
120
123
  costUsd?: number;
124
+ /** Informational shadow cost (what this work would have cost on pay-per-token); does NOT decrement costBudget. RFC-0010 §14.10. */
125
+ shadowCostUsd?: number;
121
126
  issueId?: string;
122
127
  issueNumber?: number;
123
128
  prNumber?: number;
@@ -239,4 +244,138 @@ export interface PatternProposal {
239
244
  reviewerReason?: string;
240
245
  createdAt?: string;
241
246
  }
247
+ export interface DesignTokenEventRecord {
248
+ id?: number;
249
+ bindingName: string;
250
+ eventType: 'changed' | 'deleted' | 'breaking';
251
+ tokensAffected?: number;
252
+ diffJson?: string;
253
+ actor?: string;
254
+ pipelineRunId?: string;
255
+ designReviewDecision?: string;
256
+ createdAt?: string;
257
+ }
258
+ export interface DesignReviewEventRecord {
259
+ id?: number;
260
+ bindingName: string;
261
+ prNumber?: number;
262
+ componentName?: string;
263
+ reviewer: string;
264
+ decision: 'approved' | 'rejected' | 'approved-with-comments';
265
+ categoriesJson?: string;
266
+ actionableNotes?: string;
267
+ createdAt?: string;
268
+ }
269
+ export interface TokenComplianceRecord {
270
+ id?: number;
271
+ bindingName: string;
272
+ coveragePercent: number;
273
+ violationsCount: number;
274
+ scannedAt?: string;
275
+ }
276
+ export interface VisualRegressionResultRecord {
277
+ id?: number;
278
+ bindingName: string;
279
+ storyName: string;
280
+ viewport?: number;
281
+ diffPercentage: number;
282
+ approved?: boolean;
283
+ approver?: string;
284
+ baselineUrl?: string;
285
+ currentUrl?: string;
286
+ createdAt?: string;
287
+ }
288
+ export interface UsabilitySimulationResultRecord {
289
+ id?: number;
290
+ bindingName: string;
291
+ storyName: string;
292
+ personaId?: string;
293
+ taskId?: string;
294
+ completed?: boolean;
295
+ actionsTaken?: number;
296
+ expectedActions?: number;
297
+ efficiency?: number;
298
+ findingsJson?: string;
299
+ createdAt?: string;
300
+ }
301
+ export interface DidCompiledArtifactRecord {
302
+ id?: number;
303
+ didName: string;
304
+ namespace?: string;
305
+ sourceHash: string;
306
+ scopeListsJson?: string;
307
+ constraintRulesJson?: string;
308
+ antiPatternListsJson?: string;
309
+ measurableSignalsJson?: string;
310
+ bm25CorpusBlob?: Buffer;
311
+ principleCorporaBlob?: Buffer;
312
+ compiledAt?: string;
313
+ }
314
+ export type SaDimension = 'SA-1' | 'SA-2';
315
+ export type SaPhase = '1' | '2a' | '2b' | '2c' | '3';
316
+ export interface DidScoringEventRecord {
317
+ id?: number;
318
+ didName: string;
319
+ issueNumber: number;
320
+ saDimension: SaDimension;
321
+ phase: SaPhase;
322
+ layer1ResultJson?: string;
323
+ layer2ResultJson?: string;
324
+ layer3ResultJson?: string;
325
+ compositeScore?: number;
326
+ phaseWeightsJson?: string;
327
+ createdAt?: string;
328
+ }
329
+ export type FeedbackSignal = 'accept' | 'dismiss' | 'escalate' | 'override';
330
+ export interface DidFeedbackEventRecord {
331
+ id?: number;
332
+ didName: string;
333
+ issueNumber: number;
334
+ dimension: SaDimension;
335
+ signal: FeedbackSignal;
336
+ principal?: string;
337
+ category?: string;
338
+ structuralScore?: number;
339
+ llmScore?: number;
340
+ compositeScore?: number;
341
+ notes?: string;
342
+ createdAt?: string;
343
+ }
344
+ export interface DesignChangeEventRecord {
345
+ id?: number;
346
+ didName: string;
347
+ changeId: string;
348
+ changeType: string;
349
+ status: string;
350
+ payloadJson: string;
351
+ emittedAt?: string;
352
+ }
353
+ export interface CodeAreaMetricsRecord {
354
+ id?: number;
355
+ codeArea: string;
356
+ defectDensity?: number;
357
+ churnRate?: number;
358
+ prRejectionRate?: number;
359
+ codeAcceptanceRate?: number;
360
+ hasFrontendComponents?: boolean;
361
+ designMetricsJson?: string;
362
+ dataPointCount?: number;
363
+ windowStart?: string;
364
+ windowEnd?: string;
365
+ computedAt?: string;
366
+ }
367
+ export interface DesignLookaheadNotificationRecord {
368
+ id?: number;
369
+ issueNumber: number;
370
+ firstNotifiedAt?: string;
371
+ lastNotifiedAt?: string;
372
+ pillarBreakdownJson?: string;
373
+ }
374
+ export interface SaPhaseWeightsRecord {
375
+ id?: number;
376
+ dimension: SaDimension;
377
+ wStructural: number;
378
+ wLlm: number;
379
+ calibratedAt?: string;
380
+ }
242
381
  //# sourceMappingURL=types.d.ts.map
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Ensures all reference types are accessible through the orchestrator package
4
4
  * for downstream consumers without direct reference dependency.
5
5
  */
6
- export type { ApiVersion, Metadata, Condition, SecretRef, MetricCondition, Duration, Resource, TriggerFilter, Trigger, Provider, RoutingStrategy, ComplexityThreshold, Routing, Stage, PipelineSpec, PipelinePhase, PipelineStatus, Pipeline, AgentConstraints, HandoffContractRef, Handoff, SkillExample, Skill, AgentCard, AgentRoleSpec, AgentRoleStatus, AgentRole, GateScope, MetricRule, ToolRule, ReviewerRule, DocumentationRule, ProvenanceRule, ExpressionRule, GateRule, EnforcementLevel, Override, RetryPolicy, Evaluation, Gate, QualityGateSpec, QualityGateStatus, QualityGate, Permissions, ApprovalRequirement, Guardrails, MonitoringLevel, AutonomyLevel, PromotionCriteria, DemotionTrigger, AgentAutonomyStatus, AutonomyPolicySpec, AutonomyPolicyStatus, AutonomyPolicy, AdapterInterface, HealthCheck, AdapterBindingSpec, AdapterBindingStatus, AdapterBinding, AnyResource, ResourceKind, PriorityPolicy, PriorityDimensionConfig, PriorityDimensionsConfig, PriorityCalibrationConfig, PriorityAdaptersConfig, ValidationError, } from '@ai-sdlc/reference';
6
+ export type { ApiVersion, Metadata, Condition, SecretRef, MetricCondition, Duration, Resource, TriggerFilter, Trigger, Provider, RoutingStrategy, ComplexityThreshold, Routing, Stage, PipelineSpec, PipelinePhase, PipelineStatus, Pipeline, AgentConstraints, HandoffContractRef, Handoff, SkillExample, Skill, AgentCard, AgentRoleSpec, AgentRoleStatus, AgentRole, GateScope, MetricRule, ToolRule, ReviewerRule, DocumentationRule, ProvenanceRule, ExpressionRule, GateRule, EnforcementLevel, Override, RetryPolicy, Evaluation, Gate, QualityGateSpec, QualityGateStatus, QualityGate, Permissions, ApprovalRequirement, Guardrails, MonitoringLevel, AutonomyLevel, PromotionCriteria, DemotionTrigger, AgentAutonomyStatus, AutonomyPolicySpec, AutonomyPolicyStatus, AutonomyPolicy, AdapterInterface, HealthCheck, AdapterBindingSpec, AdapterBindingStatus, AdapterBinding, DesignToolAuthority, TokenFormat, TokenVersionPolicy, ConflictResolution, SyncDirection, OnTimeout, TokenPlatform, DesignReviewScope, DesignReviewAlwaysOn, DesignReviewCondition, AuthorityBlock, ChangeApproval, Stewardship, TokenSource, TokenSyncConfig, TokenConfig, CatalogSource, CatalogDiscovery, CatalogConfig, VisualRegressionProviderConfig, VisualRegressionConfig, HardcodedRule, CoverageThreshold, ComplianceConfig, DesignReviewTriggerCondition, DesignReviewTriggerConditions, DesignReviewConfig, DesignSystemBindingSpec, TokenSyncStatus, CatalogHealthStatus, TokenComplianceStatus, DesignReviewStatus, DesignSystemBindingStatus, DesignSystemBinding, AnyResource, ResourceKind, PriorityPolicy, PriorityDimensionConfig, PriorityDimensionsConfig, PriorityCalibrationConfig, PriorityAdaptersConfig, DesignSystemPermissions, DesignReviewRequirement, StageConstraints, ContextStrategy, ContextStrategyOverride, ComponentCreationPolicy, AgentDesignSystemConfig, DesignTokenComplianceRule, VisualRegressionRule, StoryCompletenessRule, DesignReviewDecision, DesignReviewFeedbackCategory, DesignReviewRating, DesignReviewFeedback, DesignReviewGateRule, ValidationError, } from '@ai-sdlc/reference';
7
7
  export type { GateVerdict, DemotionResult, ComplexityFactor, AuthorizationContext, AuthorizationResult, AuthIdentity, AuthenticationResult, Authenticator, MutatingGateContext, ExpressionEvaluator, ExpressionVerdict, LLMEvaluationDimension, LLMEvaluationResult, LLMGateVerdict, } from '@ai-sdlc/reference';
8
8
  export type { AgentExecutionState, HandoffValidationError, SchemaResolver, SchemaValidationError, MemoryTier, MemoryEntry, WorkingMemory, ShortTermMemory, LongTermMemory, SharedMemory, EpisodicMemory, } from '@ai-sdlc/reference';
9
9
  //# sourceMappingURL=types.d.ts.map
@@ -4,6 +4,7 @@
4
4
  * Pure validation module with no side effects (fully testable).
5
5
  */
6
6
  import { execFile } from 'node:child_process';
7
+ import { cleanGitEnv } from './runtime/git-env.js';
7
8
  /**
8
9
  * Match a file path against a blocked-path pattern.
9
10
  * Supports simple glob suffixes: `foo/**` matches anything under `foo/`.
@@ -52,8 +53,10 @@ export async function validateAgentOutput(ctx) {
52
53
  }
53
54
  // 3. Max lines per PR
54
55
  if (ctx.guardrails.maxLinesPerPR !== undefined) {
56
+ // cleanGitEnv() prevents leaked GIT_DIR from binding this call to a
57
+ // parent process's git repo (AISDLC-72).
55
58
  const stdout = await new Promise((resolve, reject) => {
56
- execFile('git', ['diff', '--stat', 'HEAD~1'], { cwd: ctx.workDir }, (err, out) => {
59
+ execFile('git', ['diff', '--stat', 'HEAD~1'], { cwd: ctx.workDir, env: cleanGitEnv() }, (err, out) => {
57
60
  if (err)
58
61
  reject(err);
59
62
  else
package/dist/watch.js CHANGED
@@ -41,6 +41,12 @@ export function startWatch(options = {}) {
41
41
  try {
42
42
  await executePipeline(issueId, {
43
43
  ...options.executeOptions,
44
+ // Pass the dispatcher-selected pipeline so executePipeline doesn't
45
+ // re-load from disk and pick the wrong one in multi-pipeline configs
46
+ // (RFC-0010 dual workflow). Without this, an enqueued backlog
47
+ // pipeline silently downgrades to pipeline.yaml's branching/PR
48
+ // templates.
49
+ pipelineOverride: pipeline,
44
50
  });
45
51
  const result = { type: 'success' };
46
52
  options.onReconcile?.(pipeline.metadata.name, result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdlc/orchestrator",
3
- "version": "0.6.0",
3
+ "version": "0.10.0",
4
4
  "description": "AI-SDLC Orchestrator — long-running runtime that drives issues through the complete SDLC with AI agents",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -42,10 +42,11 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
+ "@inquirer/prompts": "^7.0.0",
45
46
  "better-sqlite3": "^11.0.0",
46
47
  "commander": "^12.0.0",
47
48
  "yaml": "^2.7.0",
48
- "@ai-sdlc/reference": "0.6.0"
49
+ "@ai-sdlc/reference": "0.10.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/better-sqlite3": "^7.6.0",