@ai-sdlc/orchestrator 0.1.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 (203) hide show
  1. package/dist/adapters.d.ts +60 -0
  2. package/dist/adapters.js +160 -0
  3. package/dist/admission.d.ts +49 -0
  4. package/dist/admission.js +90 -0
  5. package/dist/analysis/analyzer.d.ts +10 -0
  6. package/dist/analysis/analyzer.js +67 -0
  7. package/dist/analysis/complexity-scorer.d.ts +24 -0
  8. package/dist/analysis/complexity-scorer.js +39 -0
  9. package/dist/analysis/context-builder.d.ts +14 -0
  10. package/dist/analysis/context-builder.js +79 -0
  11. package/dist/analysis/convention-detector.d.ts +9 -0
  12. package/dist/analysis/convention-detector.js +177 -0
  13. package/dist/analysis/dependency-parser.d.ts +17 -0
  14. package/dist/analysis/dependency-parser.js +167 -0
  15. package/dist/analysis/file-walker.d.ts +18 -0
  16. package/dist/analysis/file-walker.js +158 -0
  17. package/dist/analysis/hotspot-analyzer.d.ts +28 -0
  18. package/dist/analysis/hotspot-analyzer.js +85 -0
  19. package/dist/analysis/index.d.ts +13 -0
  20. package/dist/analysis/index.js +12 -0
  21. package/dist/analysis/pattern-detector.d.ts +10 -0
  22. package/dist/analysis/pattern-detector.js +86 -0
  23. package/dist/analysis/types.d.ts +94 -0
  24. package/dist/analysis/types.js +5 -0
  25. package/dist/audit-archival.d.ts +48 -0
  26. package/dist/audit-archival.js +72 -0
  27. package/dist/audit-export.d.ts +45 -0
  28. package/dist/audit-export.js +100 -0
  29. package/dist/audit-extended.d.ts +28 -0
  30. package/dist/audit-extended.js +38 -0
  31. package/dist/audit-scheduler.d.ts +32 -0
  32. package/dist/audit-scheduler.js +52 -0
  33. package/dist/audit-sqlite-sink.d.ts +11 -0
  34. package/dist/audit-sqlite-sink.js +51 -0
  35. package/dist/autonomy-tracker.d.ts +76 -0
  36. package/dist/autonomy-tracker.js +277 -0
  37. package/dist/check-runs.d.ts +37 -0
  38. package/dist/check-runs.js +72 -0
  39. package/dist/cli/commands/agents.d.ts +6 -0
  40. package/dist/cli/commands/agents.js +33 -0
  41. package/dist/cli/commands/complexity.d.ts +6 -0
  42. package/dist/cli/commands/complexity.js +35 -0
  43. package/dist/cli/commands/cost.d.ts +6 -0
  44. package/dist/cli/commands/cost.js +53 -0
  45. package/dist/cli/commands/dashboard.d.ts +9 -0
  46. package/dist/cli/commands/dashboard.js +50 -0
  47. package/dist/cli/commands/health.d.ts +6 -0
  48. package/dist/cli/commands/health.js +33 -0
  49. package/dist/cli/commands/init.d.ts +6 -0
  50. package/dist/cli/commands/init.js +127 -0
  51. package/dist/cli/commands/routing.d.ts +6 -0
  52. package/dist/cli/commands/routing.js +46 -0
  53. package/dist/cli/commands/run.d.ts +6 -0
  54. package/dist/cli/commands/run.js +36 -0
  55. package/dist/cli/commands/start.d.ts +6 -0
  56. package/dist/cli/commands/start.js +26 -0
  57. package/dist/cli/commands/status.d.ts +6 -0
  58. package/dist/cli/commands/status.js +34 -0
  59. package/dist/cli/dashboard-renderer.d.ts +24 -0
  60. package/dist/cli/dashboard-renderer.js +129 -0
  61. package/dist/cli/formatters/index.d.ts +6 -0
  62. package/dist/cli/formatters/index.js +18 -0
  63. package/dist/cli/formatters/json.d.ts +5 -0
  64. package/dist/cli/formatters/json.js +7 -0
  65. package/dist/cli/formatters/minimal.d.ts +5 -0
  66. package/dist/cli/formatters/minimal.js +36 -0
  67. package/dist/cli/formatters/table.d.ts +5 -0
  68. package/dist/cli/formatters/table.js +184 -0
  69. package/dist/cli/index.d.ts +6 -0
  70. package/dist/cli/index.js +35 -0
  71. package/dist/compliance-extended.d.ts +41 -0
  72. package/dist/compliance-extended.js +58 -0
  73. package/dist/config.d.ts +26 -0
  74. package/dist/config.js +66 -0
  75. package/dist/context-enrichment.d.ts +33 -0
  76. package/dist/context-enrichment.js +125 -0
  77. package/dist/cost-governance.d.ts +22 -0
  78. package/dist/cost-governance.js +106 -0
  79. package/dist/cost-tracker.d.ts +75 -0
  80. package/dist/cost-tracker.js +177 -0
  81. package/dist/defaults.d.ts +140 -0
  82. package/dist/defaults.js +218 -0
  83. package/dist/deploy/flyio-target.d.ts +19 -0
  84. package/dist/deploy/flyio-target.js +114 -0
  85. package/dist/deploy/index.d.ts +15 -0
  86. package/dist/deploy/index.js +11 -0
  87. package/dist/deploy/kubernetes-target.d.ts +25 -0
  88. package/dist/deploy/kubernetes-target.js +124 -0
  89. package/dist/deploy/metrics-collector.d.ts +31 -0
  90. package/dist/deploy/metrics-collector.js +75 -0
  91. package/dist/deploy/rollout-controller.d.ts +42 -0
  92. package/dist/deploy/rollout-controller.js +192 -0
  93. package/dist/deploy/rollout-types.d.ts +86 -0
  94. package/dist/deploy/rollout-types.js +5 -0
  95. package/dist/deploy/types.d.ts +47 -0
  96. package/dist/deploy/types.js +5 -0
  97. package/dist/deploy/vercel-target.d.ts +16 -0
  98. package/dist/deploy/vercel-target.js +115 -0
  99. package/dist/discovery.d.ts +26 -0
  100. package/dist/discovery.js +46 -0
  101. package/dist/episodic-enhanced.d.ts +88 -0
  102. package/dist/episodic-enhanced.js +212 -0
  103. package/dist/execute.d.ts +81 -0
  104. package/dist/execute.js +703 -0
  105. package/dist/fix-ci.d.ts +61 -0
  106. package/dist/fix-ci.js +380 -0
  107. package/dist/handoff-executor.d.ts +61 -0
  108. package/dist/handoff-executor.js +119 -0
  109. package/dist/index.d.ts +70 -0
  110. package/dist/index.js +87 -0
  111. package/dist/instrumented.d.ts +27 -0
  112. package/dist/instrumented.js +34 -0
  113. package/dist/logger.d.ts +17 -0
  114. package/dist/logger.js +37 -0
  115. package/dist/multi-repo/impact-analyzer.d.ts +22 -0
  116. package/dist/multi-repo/impact-analyzer.js +95 -0
  117. package/dist/multi-repo/index.d.ts +5 -0
  118. package/dist/multi-repo/index.js +4 -0
  119. package/dist/multi-repo/monorepo-detector.d.ts +16 -0
  120. package/dist/multi-repo/monorepo-detector.js +246 -0
  121. package/dist/multi-repo/service-map-builder.d.ts +24 -0
  122. package/dist/multi-repo/service-map-builder.js +235 -0
  123. package/dist/multi-repo/types.d.ts +54 -0
  124. package/dist/multi-repo/types.js +5 -0
  125. package/dist/notifications/index.d.ts +4 -0
  126. package/dist/notifications/index.js +4 -0
  127. package/dist/notifications/notification-router.d.ts +62 -0
  128. package/dist/notifications/notification-router.js +206 -0
  129. package/dist/notifications/slack-messenger.d.ts +26 -0
  130. package/dist/notifications/slack-messenger.js +69 -0
  131. package/dist/notifications/teams-messenger.d.ts +21 -0
  132. package/dist/notifications/teams-messenger.js +85 -0
  133. package/dist/notifications.d.ts +13 -0
  134. package/dist/notifications.js +15 -0
  135. package/dist/orchestration.d.ts +20 -0
  136. package/dist/orchestration.js +53 -0
  137. package/dist/orchestrator.d.ts +160 -0
  138. package/dist/orchestrator.js +372 -0
  139. package/dist/otel-exporter.d.ts +37 -0
  140. package/dist/otel-exporter.js +128 -0
  141. package/dist/plugin.d.ts +45 -0
  142. package/dist/plugin.js +8 -0
  143. package/dist/policy-evaluators.d.ts +40 -0
  144. package/dist/policy-evaluators.js +57 -0
  145. package/dist/process-escalation.d.ts +38 -0
  146. package/dist/process-escalation.js +129 -0
  147. package/dist/progressive-gates.d.ts +54 -0
  148. package/dist/progressive-gates.js +135 -0
  149. package/dist/provenance.d.ts +29 -0
  150. package/dist/provenance.js +61 -0
  151. package/dist/reconcilers.d.ts +28 -0
  152. package/dist/reconcilers.js +37 -0
  153. package/dist/runners/claude-code.d.ts +17 -0
  154. package/dist/runners/claude-code.js +200 -0
  155. package/dist/runners/codex.d.ts +19 -0
  156. package/dist/runners/codex.js +153 -0
  157. package/dist/runners/copilot-stub.d.ts +9 -0
  158. package/dist/runners/copilot-stub.js +15 -0
  159. package/dist/runners/copilot.d.ts +15 -0
  160. package/dist/runners/copilot.js +119 -0
  161. package/dist/runners/cursor-stub.d.ts +9 -0
  162. package/dist/runners/cursor-stub.js +15 -0
  163. package/dist/runners/cursor.d.ts +20 -0
  164. package/dist/runners/cursor.js +140 -0
  165. package/dist/runners/devin-stub.d.ts +9 -0
  166. package/dist/runners/devin-stub.js +15 -0
  167. package/dist/runners/generic-llm.d.ts +51 -0
  168. package/dist/runners/generic-llm.js +125 -0
  169. package/dist/runners/index.d.ts +8 -0
  170. package/dist/runners/index.js +7 -0
  171. package/dist/runners/runner-registry.d.ts +50 -0
  172. package/dist/runners/runner-registry.js +156 -0
  173. package/dist/runners/types.d.ts +59 -0
  174. package/dist/runners/types.js +7 -0
  175. package/dist/security.d.ts +51 -0
  176. package/dist/security.js +70 -0
  177. package/dist/shared.d.ts +134 -0
  178. package/dist/shared.js +284 -0
  179. package/dist/state/index.d.ts +4 -0
  180. package/dist/state/index.js +3 -0
  181. package/dist/state/schema.d.ts +16 -0
  182. package/dist/state/schema.js +264 -0
  183. package/dist/state/store.d.ts +109 -0
  184. package/dist/state/store.js +644 -0
  185. package/dist/state/types.d.ts +190 -0
  186. package/dist/state/types.js +5 -0
  187. package/dist/structured-logger.d.ts +20 -0
  188. package/dist/structured-logger.js +64 -0
  189. package/dist/task-decomposer.d.ts +61 -0
  190. package/dist/task-decomposer.js +265 -0
  191. package/dist/telemetry-extended.d.ts +24 -0
  192. package/dist/telemetry-extended.js +31 -0
  193. package/dist/types.d.ts +9 -0
  194. package/dist/types.js +7 -0
  195. package/dist/validate-agent-output.d.ts +30 -0
  196. package/dist/validate-agent-output.js +81 -0
  197. package/dist/validate-issue.d.ts +25 -0
  198. package/dist/validate-issue.js +102 -0
  199. package/dist/watch.d.ts +43 -0
  200. package/dist/watch.js +99 -0
  201. package/dist/webhook-manager.d.ts +38 -0
  202. package/dist/webhook-manager.js +66 -0
  203. package/package.json +59 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ai-sdlc health — validate config, state store, and adapter connectivity.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const healthCommand = new Command('health')
8
+ .description('Check orchestrator health')
9
+ .option('--state <path>', 'SQLite state database path')
10
+ .action(async (opts, cmd) => {
11
+ const globalOpts = cmd.parent?.opts() ?? {};
12
+ const format = globalOpts.format ?? 'table';
13
+ const orchestrator = new Orchestrator({
14
+ configDir: globalOpts.config,
15
+ statePath: opts.state,
16
+ });
17
+ try {
18
+ const result = await orchestrator.health();
19
+ console.log(formatOutput(format, {
20
+ type: 'health',
21
+ configValid: result.configValid,
22
+ stateStoreConnected: result.stateStoreConnected,
23
+ errors: result.errors,
24
+ }));
25
+ if (result.errors.length > 0) {
26
+ process.exitCode = 1;
27
+ }
28
+ }
29
+ finally {
30
+ orchestrator.close();
31
+ }
32
+ });
33
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc init — initialize a project with AI-SDLC config files.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const initCommand: Command;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1,127 @@
1
+ /**
2
+ * ai-sdlc init — initialize a project with AI-SDLC config files.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ const PIPELINE_YAML = `apiVersion: ai-sdlc.io/v1alpha1
8
+ kind: Pipeline
9
+ metadata:
10
+ name: default
11
+ spec:
12
+ stages:
13
+ - name: validate
14
+ type: gate
15
+ - name: code
16
+ type: agent
17
+ timeout: 30m
18
+ onFailure:
19
+ action: retry
20
+ maxRetries: 2
21
+ - name: review
22
+ type: gate
23
+ triggers:
24
+ - event: issue.labeled
25
+ filters:
26
+ - field: label
27
+ value: ai-sdlc
28
+ `;
29
+ const AGENT_ROLE_YAML = `apiVersion: ai-sdlc.io/v1alpha1
30
+ kind: AgentRole
31
+ metadata:
32
+ name: default-agent
33
+ spec:
34
+ role: developer
35
+ goal: Implement issue requirements with tests
36
+ tools:
37
+ - Edit
38
+ - Write
39
+ - Read
40
+ - Glob
41
+ - Grep
42
+ - Bash
43
+ constraints:
44
+ maxFilesPerChange: 15
45
+ requireTests: true
46
+ blockedPaths:
47
+ - .github/workflows/**
48
+ - .ai-sdlc/**
49
+ `;
50
+ const QUALITY_GATE_YAML = `apiVersion: ai-sdlc.io/v1alpha1
51
+ kind: QualityGate
52
+ metadata:
53
+ name: default-gates
54
+ spec:
55
+ gates:
56
+ - name: has-description
57
+ rule:
58
+ metric: description-length
59
+ operator: gt
60
+ threshold: 0
61
+ enforcement: mandatory
62
+ - name: has-acceptance-criteria
63
+ rule:
64
+ metric: has-acceptance-criteria
65
+ operator: gte
66
+ threshold: 1
67
+ enforcement: warning
68
+ `;
69
+ const AUTONOMY_POLICY_YAML = `apiVersion: ai-sdlc.io/v1alpha1
70
+ kind: AutonomyPolicy
71
+ metadata:
72
+ name: default-autonomy
73
+ spec:
74
+ levels:
75
+ - level: 0
76
+ name: supervised
77
+ permissions:
78
+ read: ["**"]
79
+ write: ["src/**", "test/**", "tests/**"]
80
+ execute: []
81
+ guardrails:
82
+ maxLinesPerPR: 300
83
+ blockedPaths:
84
+ - .github/workflows/**
85
+ - .ai-sdlc/**
86
+ promotionCriteria:
87
+ - metric: tasks-completed
88
+ threshold: 10
89
+ demotionTriggers:
90
+ - trigger: failed-test
91
+ threshold: 3
92
+ `;
93
+ export const initCommand = new Command('init')
94
+ .description('Initialize AI-SDLC configuration in the current project')
95
+ .option('--dry-run', 'Show what would be created without writing files')
96
+ .option('-d, --dir <path>', 'Config directory name', '.ai-sdlc')
97
+ .action(async (opts) => {
98
+ const configDir = join(process.cwd(), opts.dir ?? '.ai-sdlc');
99
+ const files = [
100
+ { name: 'pipeline.yaml', content: PIPELINE_YAML },
101
+ { name: 'agent-role.yaml', content: AGENT_ROLE_YAML },
102
+ { name: 'quality-gate.yaml', content: QUALITY_GATE_YAML },
103
+ { name: 'autonomy-policy.yaml', content: AUTONOMY_POLICY_YAML },
104
+ ];
105
+ if (opts.dryRun) {
106
+ console.log(`Would create ${configDir}/`);
107
+ for (const f of files) {
108
+ console.log(` ${f.name}`);
109
+ }
110
+ return;
111
+ }
112
+ if (!existsSync(configDir)) {
113
+ mkdirSync(configDir, { recursive: true });
114
+ }
115
+ for (const f of files) {
116
+ const path = join(configDir, f.name);
117
+ if (existsSync(path)) {
118
+ console.log(` skip ${f.name} (already exists)`);
119
+ }
120
+ else {
121
+ writeFileSync(path, f.content, 'utf-8');
122
+ console.log(` created ${f.name}`);
123
+ }
124
+ }
125
+ console.log(`\nAI-SDLC config initialized in ${configDir}/`);
126
+ });
127
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc routing [--last <duration>] — show routing distribution.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const routingCommand: Command;
6
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * ai-sdlc routing [--last <duration>] — show routing distribution.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const routingCommand = new Command('routing')
8
+ .description('Show routing decision distribution')
9
+ .option('--last <duration>', 'Time window (e.g. 7d, 30d)', '30d')
10
+ .option('--state <path>', 'SQLite state database path')
11
+ .action(async (opts, cmd) => {
12
+ const globalOpts = cmd.parent?.opts() ?? {};
13
+ const format = globalOpts.format ?? 'table';
14
+ const orchestrator = new Orchestrator({
15
+ configDir: globalOpts.config,
16
+ statePath: opts.state,
17
+ });
18
+ try {
19
+ const history = await orchestrator.routing({ limit: 200 });
20
+ // Parse --last duration
21
+ const durationMatch = opts.last?.match(/^(\d+)([dhm])$/);
22
+ let cutoff = 0;
23
+ if (durationMatch) {
24
+ const value = parseInt(durationMatch[1], 10);
25
+ const unit = durationMatch[2];
26
+ const ms = unit === 'd' ? value * 86400000 : unit === 'h' ? value * 3600000 : value * 60000;
27
+ cutoff = Date.now() - ms;
28
+ }
29
+ const filtered = cutoff > 0
30
+ ? history.filter((h) => h.decidedAt && new Date(h.decidedAt).getTime() >= cutoff)
31
+ : history;
32
+ console.log(formatOutput(format, {
33
+ type: 'routing',
34
+ duration: opts.last,
35
+ history: filtered,
36
+ }));
37
+ }
38
+ catch (err) {
39
+ console.error(err instanceof Error ? err.message : String(err));
40
+ process.exitCode = 1;
41
+ }
42
+ finally {
43
+ orchestrator.close();
44
+ }
45
+ });
46
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc run --issue <N> — execute the pipeline for a single issue.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const runCommand: Command;
6
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ai-sdlc run --issue <N> — execute the pipeline for a single issue.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const runCommand = new Command('run')
8
+ .description('Run the AI-SDLC pipeline for a specific issue')
9
+ .requiredOption('-i, --issue <number>', 'Issue number to process', parseInt)
10
+ .option('--state <path>', 'SQLite state database path')
11
+ .action(async (opts, cmd) => {
12
+ const globalOpts = cmd.parent?.opts() ?? {};
13
+ const format = globalOpts.format ?? 'table';
14
+ const orchestrator = new Orchestrator({
15
+ configDir: globalOpts.config,
16
+ statePath: opts.state,
17
+ });
18
+ try {
19
+ const result = await orchestrator.run(opts.issue);
20
+ console.log(formatOutput(format, {
21
+ type: 'run',
22
+ issueNumber: opts.issue,
23
+ prUrl: result.prUrl,
24
+ filesChanged: result.filesChanged.length,
25
+ promotionEligible: result.promotionEligible,
26
+ }));
27
+ }
28
+ catch (err) {
29
+ console.error(err instanceof Error ? err.message : String(err));
30
+ process.exitCode = 1;
31
+ }
32
+ finally {
33
+ orchestrator.close();
34
+ }
35
+ });
36
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc start — start watch mode with continuous reconciliation.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const startCommand: Command;
6
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ai-sdlc start — start watch mode with continuous reconciliation.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ export const startCommand = new Command('start')
7
+ .description('Start the AI-SDLC watch mode (continuous reconciliation)')
8
+ .option('--state <path>', 'SQLite state database path')
9
+ .action(async (opts, cmd) => {
10
+ const globalOpts = cmd.parent?.opts() ?? {};
11
+ const orchestrator = new Orchestrator({
12
+ configDir: globalOpts.config,
13
+ statePath: opts.state,
14
+ });
15
+ const handle = await orchestrator.start();
16
+ console.log('[ai-sdlc] Watch mode started. Press Ctrl+C to stop.');
17
+ const shutdown = () => {
18
+ console.log('\n[ai-sdlc] Shutting down...');
19
+ handle.stop();
20
+ orchestrator.close();
21
+ process.exit(0);
22
+ };
23
+ process.on('SIGINT', shutdown);
24
+ process.on('SIGTERM', shutdown);
25
+ });
26
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc status [--issue <N>] — show pipeline status.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const statusCommand: Command;
6
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ai-sdlc status [--issue <N>] — show pipeline status.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const statusCommand = new Command('status')
8
+ .description('Show pipeline status')
9
+ .option('-i, --issue <number>', 'Filter by issue number', parseInt)
10
+ .option('--state <path>', 'SQLite state database path')
11
+ .action(async (opts, cmd) => {
12
+ const globalOpts = cmd.parent?.opts() ?? {};
13
+ const format = globalOpts.format ?? 'table';
14
+ const orchestrator = new Orchestrator({
15
+ configDir: globalOpts.config,
16
+ statePath: opts.state,
17
+ });
18
+ try {
19
+ const result = await orchestrator.status(opts.issue);
20
+ console.log(formatOutput(format, {
21
+ type: 'status',
22
+ pipeline: result.config.pipeline?.metadata.name ?? 'none',
23
+ recentRuns: result.recentRuns,
24
+ }));
25
+ }
26
+ catch (err) {
27
+ console.error(err instanceof Error ? err.message : String(err));
28
+ process.exitCode = 1;
29
+ }
30
+ finally {
31
+ orchestrator.close();
32
+ }
33
+ });
34
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Dashboard renderer — pure render functions per panel (no I/O).
3
+ * Composes ANSI box-drawing characters for a TUI monitoring view.
4
+ *
5
+ * D1: Zero dependencies, unit-testable pure functions.
6
+ */
7
+ import type { AutonomyLedgerEntry } from '../state/types.js';
8
+ import type { CostSummary, BudgetStatus } from '../cost-tracker.js';
9
+ export interface DashboardData {
10
+ runs: Array<{
11
+ runId: string;
12
+ status: string;
13
+ startedAt?: string;
14
+ }>;
15
+ agents: AutonomyLedgerEntry[];
16
+ costSummary: CostSummary;
17
+ budgetStatus: BudgetStatus;
18
+ }
19
+ export declare function renderPipelinePanel(runs: DashboardData['runs'], width: number): string[];
20
+ export declare function renderAgentPanel(agents: DashboardData['agents'], width: number): string[];
21
+ export declare function renderCostPanel(summary: CostSummary, budget: BudgetStatus, width: number): string[];
22
+ export declare function renderHeaderPanel(width: number): string[];
23
+ export declare function renderDashboardFrame(data: DashboardData, width: number): string;
24
+ //# sourceMappingURL=dashboard-renderer.d.ts.map
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Dashboard renderer — pure render functions per panel (no I/O).
3
+ * Composes ANSI box-drawing characters for a TUI monitoring view.
4
+ *
5
+ * D1: Zero dependencies, unit-testable pure functions.
6
+ */
7
+ // ── Box drawing helpers ─────────────────────────────────────────
8
+ const BOX = {
9
+ topLeft: '\u250C',
10
+ topRight: '\u2510',
11
+ bottomLeft: '\u2514',
12
+ bottomRight: '\u2518',
13
+ horizontal: '\u2500',
14
+ vertical: '\u2502',
15
+ teeRight: '\u251C',
16
+ teeLeft: '\u2524',
17
+ };
18
+ function boxTop(width, title) {
19
+ if (title) {
20
+ const titleStr = ` ${title} `;
21
+ const remaining = width - 2 - titleStr.length;
22
+ return BOX.topLeft + titleStr + BOX.horizontal.repeat(Math.max(0, remaining)) + BOX.topRight;
23
+ }
24
+ return BOX.topLeft + BOX.horizontal.repeat(width - 2) + BOX.topRight;
25
+ }
26
+ function boxBottom(width) {
27
+ return BOX.bottomLeft + BOX.horizontal.repeat(width - 2) + BOX.bottomRight;
28
+ }
29
+ function boxLine(content, width) {
30
+ const padded = content.slice(0, width - 4).padEnd(width - 4);
31
+ return `${BOX.vertical} ${padded} ${BOX.vertical}`;
32
+ }
33
+ function boxSeparator(width) {
34
+ return BOX.teeRight + BOX.horizontal.repeat(width - 2) + BOX.teeLeft;
35
+ }
36
+ // ── Panel renderers ─────────────────────────────────────────────
37
+ export function renderPipelinePanel(runs, width) {
38
+ const lines = [];
39
+ lines.push(boxTop(width, 'Active Pipelines'));
40
+ if (runs.length === 0) {
41
+ lines.push(boxLine('No recent runs.', width));
42
+ }
43
+ else {
44
+ lines.push(boxLine('Run ID'.padEnd(24) + 'Status'.padEnd(12) + 'Started', width));
45
+ lines.push(boxSeparator(width));
46
+ for (const run of runs.slice(0, 5)) {
47
+ const started = run.startedAt?.split('T')[1]?.slice(0, 8) ?? '-';
48
+ lines.push(boxLine(run.runId.slice(0, 22).padEnd(24) + run.status.padEnd(12) + started, width));
49
+ }
50
+ }
51
+ lines.push(boxBottom(width));
52
+ return lines;
53
+ }
54
+ export function renderAgentPanel(agents, width) {
55
+ const lines = [];
56
+ lines.push(boxTop(width, 'Agents'));
57
+ if (agents.length === 0) {
58
+ lines.push(boxLine('No agents registered.', width));
59
+ }
60
+ else {
61
+ lines.push(boxLine('Agent'.padEnd(18) + 'Lvl'.padEnd(5) + 'Tasks'.padEnd(8) + 'Rate'.padEnd(8) + 'Last', width));
62
+ lines.push(boxSeparator(width));
63
+ for (const agent of agents.slice(0, 5)) {
64
+ const rate = agent.totalTasks > 0
65
+ ? `${Math.round((agent.successCount / agent.totalTasks) * 100)}%`
66
+ : '-';
67
+ const last = agent.lastTaskAt?.split('T')[0] ?? '-';
68
+ lines.push(boxLine(agent.agentName.slice(0, 16).padEnd(18) +
69
+ String(agent.currentLevel).padEnd(5) +
70
+ String(agent.totalTasks).padEnd(8) +
71
+ rate.padEnd(8) +
72
+ last, width));
73
+ }
74
+ }
75
+ lines.push(boxBottom(width));
76
+ return lines;
77
+ }
78
+ export function renderCostPanel(summary, budget, width) {
79
+ const lines = [];
80
+ lines.push(boxTop(width, 'Cost'));
81
+ lines.push(boxLine(`Total: $${summary.totalCostUsd.toFixed(2)} | Tokens: ${formatNumber(summary.totalTokens)} | Runs: ${summary.entryCount}`, width));
82
+ lines.push(boxLine(`Avg/run: $${summary.avgCostPerRun.toFixed(4)} | Budget: $${budget.budgetUsd} (${budget.utilizationPercent.toFixed(0)}% used)`, width));
83
+ // Budget bar
84
+ const barWidth = Math.max(10, width - 20);
85
+ const filled = Math.min(barWidth, Math.round((budget.utilizationPercent / 100) * barWidth));
86
+ const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
87
+ const budgetStatus = budget.overBudget ? ' OVER BUDGET!' : '';
88
+ lines.push(boxLine(`[${bar}]${budgetStatus}`, width));
89
+ // Cost by agent
90
+ if (Object.keys(summary.costByAgent).length > 0) {
91
+ lines.push(boxSeparator(width));
92
+ for (const [agent, cost] of Object.entries(summary.costByAgent).slice(0, 3)) {
93
+ lines.push(boxLine(` ${agent.padEnd(16)} $${cost.toFixed(4)}`, width));
94
+ }
95
+ }
96
+ lines.push(boxBottom(width));
97
+ return lines;
98
+ }
99
+ export function renderHeaderPanel(width) {
100
+ const now = new Date().toLocaleString();
101
+ return [boxTop(width, 'AI-SDLC Dashboard'), boxLine(`Updated: ${now}`, width), boxBottom(width)];
102
+ }
103
+ // ── Composer ─────────────────────────────────────────────────────
104
+ export function renderDashboardFrame(data, width) {
105
+ const panelWidth = Math.max(40, width);
106
+ const allLines = [];
107
+ allLines.push(...renderHeaderPanel(panelWidth));
108
+ allLines.push('');
109
+ allLines.push(...renderPipelinePanel(data.runs, panelWidth));
110
+ allLines.push('');
111
+ allLines.push(...renderAgentPanel(data.agents, panelWidth));
112
+ allLines.push('');
113
+ allLines.push(...renderCostPanel(data.costSummary, data.budgetStatus, panelWidth));
114
+ // Pad to fill terminal height to avoid artifacts
115
+ const termHeight = process.stdout.rows || 40;
116
+ while (allLines.length < termHeight - 1) {
117
+ allLines.push('');
118
+ }
119
+ return allLines.join('\n');
120
+ }
121
+ // ── Utilities ───────────────────────────────────────────────────
122
+ function formatNumber(n) {
123
+ if (n >= 1_000_000)
124
+ return `${(n / 1_000_000).toFixed(1)}M`;
125
+ if (n >= 1_000)
126
+ return `${(n / 1_000).toFixed(1)}K`;
127
+ return String(n);
128
+ }
129
+ //# sourceMappingURL=dashboard-renderer.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Output formatter factory — routes to table, json, or minimal.
3
+ */
4
+ export type FormatType = 'table' | 'json' | 'minimal';
5
+ export declare function formatOutput(format: string, data: Record<string, unknown>): string;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Output formatter factory — routes to table, json, or minimal.
3
+ */
4
+ import { formatTable } from './table.js';
5
+ import { formatJson } from './json.js';
6
+ import { formatMinimal } from './minimal.js';
7
+ export function formatOutput(format, data) {
8
+ switch (format) {
9
+ case 'json':
10
+ return formatJson(data);
11
+ case 'minimal':
12
+ return formatMinimal(data);
13
+ case 'table':
14
+ default:
15
+ return formatTable(data);
16
+ }
17
+ }
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * JSON output formatter — machine-readable JSON output.
3
+ */
4
+ export declare function formatJson(data: Record<string, unknown>): string;
5
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * JSON output formatter — machine-readable JSON output.
3
+ */
4
+ export function formatJson(data) {
5
+ return JSON.stringify(data, null, 2);
6
+ }
7
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Minimal output formatter — single-line output for scripting.
3
+ */
4
+ export declare function formatMinimal(data: Record<string, unknown>): string;
5
+ //# sourceMappingURL=minimal.d.ts.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Minimal output formatter — single-line output for scripting.
3
+ */
4
+ export function formatMinimal(data) {
5
+ const type = data.type;
6
+ switch (type) {
7
+ case 'run':
8
+ return `PR: ${data.prUrl} (${data.filesChanged} files)`;
9
+ case 'status':
10
+ return `Pipeline: ${data.pipeline} | Runs: ${data.recentRuns.length}`;
11
+ case 'health': {
12
+ const ok = data.configValid && data.errors.length === 0;
13
+ return ok ? 'OK' : `UNHEALTHY: ${data.errors.join('; ')}`;
14
+ }
15
+ case 'agents': {
16
+ const agents = data.agents;
17
+ return `Agents: ${agents.length}`;
18
+ }
19
+ case 'routing': {
20
+ const history = data.history;
21
+ return `Routing decisions: ${history.length} (last ${data.duration ?? '30d'})`;
22
+ }
23
+ case 'complexity': {
24
+ const profile = data.profile;
25
+ return `Complexity: ${profile.score}/10 | ${profile.filesCount} files | ${profile.modulesCount} modules`;
26
+ }
27
+ case 'cost': {
28
+ const summary = data.summary;
29
+ const budget = data.budget;
30
+ return `Cost: $${summary.totalCostUsd.toFixed(2)} | Budget: ${budget.utilizationPercent.toFixed(0)}% used | Runs: ${summary.entryCount}`;
31
+ }
32
+ default:
33
+ return JSON.stringify(data);
34
+ }
35
+ }
36
+ //# sourceMappingURL=minimal.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Table output formatter — human-readable tabular output.
3
+ */
4
+ export declare function formatTable(data: Record<string, unknown>): string;
5
+ //# sourceMappingURL=table.d.ts.map