agentic-orchestrator 0.1.25 → 0.1.26

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 (177) hide show
  1. package/agentic/orchestrator/defaults/policy.defaults.yaml +1 -0
  2. package/agentic/orchestrator/policy.yaml +1 -0
  3. package/agentic/orchestrator/schemas/policy.schema.json +4 -0
  4. package/agentic/orchestrator/schemas/policy.user.schema.json +4 -0
  5. package/apps/control-plane/src/application/services/activity-monitor-service.ts +42 -0
  6. package/apps/control-plane/src/application/services/collision-queue-service.ts +48 -0
  7. package/apps/control-plane/src/application/services/cost-tracking-service.ts +80 -0
  8. package/apps/control-plane/src/application/services/feature-deletion-service.ts +57 -0
  9. package/apps/control-plane/src/application/services/feature-lifecycle-service.ts +65 -0
  10. package/apps/control-plane/src/application/services/feature-state-service.ts +87 -0
  11. package/apps/control-plane/src/application/services/gate-selection-service.ts +28 -0
  12. package/apps/control-plane/src/application/services/gate-service.ts +148 -0
  13. package/apps/control-plane/src/application/services/issue-tracker-service.ts +28 -0
  14. package/apps/control-plane/src/application/services/lock-service.ts +88 -0
  15. package/apps/control-plane/src/application/services/merge-service.ts +63 -0
  16. package/apps/control-plane/src/application/services/notifier-service.ts +70 -0
  17. package/apps/control-plane/src/application/services/patch-service.ts +95 -0
  18. package/apps/control-plane/src/application/services/performance-analytics-service.ts +90 -0
  19. package/apps/control-plane/src/application/services/plan-service.ts +184 -0
  20. package/apps/control-plane/src/application/services/pr-monitor-service.ts +58 -0
  21. package/apps/control-plane/src/application/services/qa-index-service.ts +68 -0
  22. package/apps/control-plane/src/application/services/reactions-service.ts +77 -0
  23. package/apps/control-plane/src/application/services/reporting-service.ts +79 -0
  24. package/apps/control-plane/src/application/services/run-lease-service.ts +79 -0
  25. package/apps/control-plane/src/application/tools/tool-router.ts +76 -0
  26. package/apps/control-plane/src/mcp/tool-runtime.ts +4 -0
  27. package/apps/control-plane/src/providers/providers.ts +96 -0
  28. package/apps/control-plane/src/providers/worker-provider-factory.ts +4 -0
  29. package/apps/control-plane/src/supervisor/build-wave-executor.ts +4 -0
  30. package/apps/control-plane/src/supervisor/planning-wave-executor.ts +4 -0
  31. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +4 -0
  32. package/apps/control-plane/src/supervisor/run-coordinator.ts +4 -0
  33. package/apps/control-plane/src/supervisor/runtime.ts +4 -0
  34. package/apps/control-plane/src/supervisor/session-orchestrator.ts +4 -0
  35. package/apps/control-plane/test/dashboard-api.integration.spec.ts +310 -1
  36. package/apps/control-plane/test/dashboard-client.spec.ts +136 -1
  37. package/apps/control-plane/test/dashboard-live-feed.spec.ts +153 -0
  38. package/apps/control-plane/test/dashboard-ui-utils.spec.ts +132 -0
  39. package/apps/control-plane/test/mcp.spec.ts +96 -0
  40. package/apps/control-plane/test/tool-runtime.spec.ts +68 -0
  41. package/config/agentic/orchestrator/policy.yaml +1 -0
  42. package/dist/apps/control-plane/application/services/activity-monitor-service.d.ts +42 -0
  43. package/dist/apps/control-plane/application/services/activity-monitor-service.js +42 -0
  44. package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -1
  45. package/dist/apps/control-plane/application/services/collision-queue-service.d.ts +48 -0
  46. package/dist/apps/control-plane/application/services/collision-queue-service.js +48 -0
  47. package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -1
  48. package/dist/apps/control-plane/application/services/cost-tracking-service.d.ts +79 -0
  49. package/dist/apps/control-plane/application/services/cost-tracking-service.js +76 -0
  50. package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -1
  51. package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +57 -0
  52. package/dist/apps/control-plane/application/services/feature-deletion-service.js +57 -0
  53. package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
  54. package/dist/apps/control-plane/application/services/feature-lifecycle-service.d.ts +64 -0
  55. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +61 -0
  56. package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -1
  57. package/dist/apps/control-plane/application/services/feature-state-service.d.ts +86 -0
  58. package/dist/apps/control-plane/application/services/feature-state-service.js +83 -0
  59. package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -1
  60. package/dist/apps/control-plane/application/services/gate-selection-service.d.ts +28 -0
  61. package/dist/apps/control-plane/application/services/gate-selection-service.js +28 -0
  62. package/dist/apps/control-plane/application/services/gate-selection-service.js.map +1 -1
  63. package/dist/apps/control-plane/application/services/gate-service.d.ts +148 -0
  64. package/dist/apps/control-plane/application/services/gate-service.js +120 -0
  65. package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
  66. package/dist/apps/control-plane/application/services/issue-tracker-service.d.ts +28 -0
  67. package/dist/apps/control-plane/application/services/issue-tracker-service.js +28 -0
  68. package/dist/apps/control-plane/application/services/issue-tracker-service.js.map +1 -1
  69. package/dist/apps/control-plane/application/services/lock-service.d.ts +88 -0
  70. package/dist/apps/control-plane/application/services/lock-service.js +64 -0
  71. package/dist/apps/control-plane/application/services/lock-service.js.map +1 -1
  72. package/dist/apps/control-plane/application/services/merge-service.d.ts +62 -0
  73. package/dist/apps/control-plane/application/services/merge-service.js +59 -0
  74. package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
  75. package/dist/apps/control-plane/application/services/notifier-service.d.ts +70 -0
  76. package/dist/apps/control-plane/application/services/notifier-service.js +70 -0
  77. package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -1
  78. package/dist/apps/control-plane/application/services/patch-service.d.ts +94 -0
  79. package/dist/apps/control-plane/application/services/patch-service.js +91 -0
  80. package/dist/apps/control-plane/application/services/patch-service.js.map +1 -1
  81. package/dist/apps/control-plane/application/services/performance-analytics-service.d.ts +89 -0
  82. package/dist/apps/control-plane/application/services/performance-analytics-service.js +86 -0
  83. package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -1
  84. package/dist/apps/control-plane/application/services/plan-service.d.ts +287 -0
  85. package/dist/apps/control-plane/application/services/plan-service.js +207 -0
  86. package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
  87. package/dist/apps/control-plane/application/services/pr-monitor-service.d.ts +58 -0
  88. package/dist/apps/control-plane/application/services/pr-monitor-service.js +58 -0
  89. package/dist/apps/control-plane/application/services/pr-monitor-service.js.map +1 -1
  90. package/dist/apps/control-plane/application/services/qa-index-service.d.ts +67 -0
  91. package/dist/apps/control-plane/application/services/qa-index-service.js +64 -0
  92. package/dist/apps/control-plane/application/services/qa-index-service.js.map +1 -1
  93. package/dist/apps/control-plane/application/services/reactions-service.d.ts +76 -0
  94. package/dist/apps/control-plane/application/services/reactions-service.js +73 -0
  95. package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -1
  96. package/dist/apps/control-plane/application/services/reporting-service.d.ts +78 -0
  97. package/dist/apps/control-plane/application/services/reporting-service.js +75 -0
  98. package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
  99. package/dist/apps/control-plane/application/services/run-lease-service.d.ts +79 -0
  100. package/dist/apps/control-plane/application/services/run-lease-service.js +79 -0
  101. package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
  102. package/dist/apps/control-plane/application/tools/tool-router.d.ts +76 -0
  103. package/dist/apps/control-plane/application/tools/tool-router.js +62 -0
  104. package/dist/apps/control-plane/application/tools/tool-router.js.map +1 -1
  105. package/dist/apps/control-plane/mcp/tool-runtime.d.ts +3 -0
  106. package/dist/apps/control-plane/mcp/tool-runtime.js +3 -0
  107. package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -1
  108. package/dist/apps/control-plane/providers/providers.d.ts +88 -0
  109. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  110. package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +3 -0
  111. package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
  112. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +3 -0
  113. package/dist/apps/control-plane/supervisor/build-wave-executor.js +3 -0
  114. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  115. package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +3 -0
  116. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +3 -0
  117. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
  118. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +3 -0
  119. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +3 -0
  120. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  121. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +3 -0
  122. package/dist/apps/control-plane/supervisor/run-coordinator.js +3 -0
  123. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  124. package/dist/apps/control-plane/supervisor/runtime.d.ts +3 -0
  125. package/dist/apps/control-plane/supervisor/runtime.js +3 -0
  126. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  127. package/dist/apps/control-plane/supervisor/session-orchestrator.d.ts +3 -0
  128. package/dist/apps/control-plane/supervisor/session-orchestrator.js +3 -0
  129. package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -1
  130. package/package.json +1 -1
  131. package/packages/web-dashboard/src/app/analytics/page.tsx +451 -0
  132. package/packages/web-dashboard/src/app/api/analytics/route.ts +62 -0
  133. package/packages/web-dashboard/src/app/api/collisions/route.ts +63 -0
  134. package/packages/web-dashboard/src/app/api/features/[id]/cost/route.ts +29 -0
  135. package/packages/web-dashboard/src/app/api/features/[id]/review-brief/route.ts +31 -0
  136. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +5 -8
  137. package/packages/web-dashboard/src/app/api/features/[id]/test-index/route.ts +31 -0
  138. package/packages/web-dashboard/src/app/api/flaky/route.ts +20 -0
  139. package/packages/web-dashboard/src/app/api/policy/budget/route.ts +31 -0
  140. package/packages/web-dashboard/src/app/api/run/route.ts +162 -0
  141. package/packages/web-dashboard/src/app/api/status/route.ts +2 -5
  142. package/packages/web-dashboard/src/app/feature/[id]/page.tsx +112 -0
  143. package/packages/web-dashboard/src/app/page.tsx +379 -77
  144. package/packages/web-dashboard/src/components/agent-pipeline-stepper.tsx +100 -0
  145. package/packages/web-dashboard/src/components/dependency-chains.tsx +58 -0
  146. package/packages/web-dashboard/src/components/detail-panel.tsx +215 -5
  147. package/packages/web-dashboard/src/components/feature-card.tsx +5 -0
  148. package/packages/web-dashboard/src/components/feature-cost-panel.tsx +66 -0
  149. package/packages/web-dashboard/src/components/feature-list-view.tsx +336 -0
  150. package/packages/web-dashboard/src/components/gate-step-drilldown.tsx +92 -0
  151. package/packages/web-dashboard/src/components/kanban-board.tsx +3 -0
  152. package/packages/web-dashboard/src/components/live-event-feed.tsx +60 -0
  153. package/packages/web-dashboard/src/components/lock-resource-map.tsx +73 -0
  154. package/packages/web-dashboard/src/components/plan-revision-timeline.tsx +55 -0
  155. package/packages/web-dashboard/src/components/plan-risk-annotations.tsx +63 -0
  156. package/packages/web-dashboard/src/components/plan-scope-tree.tsx +285 -0
  157. package/packages/web-dashboard/src/components/qa-coverage-map.tsx +174 -0
  158. package/packages/web-dashboard/src/components/quick-launch-panel.tsx +70 -0
  159. package/packages/web-dashboard/src/components/review-brief-panel.tsx +75 -0
  160. package/packages/web-dashboard/src/components/run-health-panel.tsx +85 -0
  161. package/packages/web-dashboard/src/components/summary-bar.tsx +59 -2
  162. package/packages/web-dashboard/src/components/verification-signals.tsx +167 -0
  163. package/packages/web-dashboard/src/lib/analytics-utils.ts +3 -0
  164. package/packages/web-dashboard/src/lib/aop-client.ts +510 -11
  165. package/packages/web-dashboard/src/lib/api-envelope.ts +48 -0
  166. package/packages/web-dashboard/src/lib/authz-adapter.ts +33 -0
  167. package/packages/web-dashboard/src/lib/dashboard-utils.ts +304 -0
  168. package/packages/web-dashboard/src/lib/live-feed.ts +218 -0
  169. package/packages/web-dashboard/src/lib/policy-reader.ts +22 -0
  170. package/packages/web-dashboard/src/lib/types.ts +114 -0
  171. package/packages/web-dashboard/src/styles/dashboard.module.css +341 -1
  172. package/spec-files/{outstanding → completed}/agentic_orchestrator_dashboard_advanced_ux_spec.md +1 -1
  173. package/spec-files/outstanding/agentic_orchestrator_evidence_integrity_doctor_spec.md +561 -0
  174. package/spec-files/outstanding/agentic_orchestrator_kernel_simplification_spec.md +834 -0
  175. package/spec-files/outstanding/agentic_orchestrator_observability_integrity_diagnostics_spec.md +12 -5
  176. package/spec-files/outstanding/agentic_orchestrator_observability_replay_spec.md +442 -0
  177. package/spec-files/progress.md +174 -1
@@ -171,6 +171,7 @@ cleanup:
171
171
  dashboard:
172
172
  enabled: true
173
173
  port: 3000
174
+ quick_launch: false
174
175
  notifications:
175
176
  enabled: false
176
177
  channels:
@@ -193,6 +193,7 @@ rbac:
193
193
  dashboard:
194
194
  enabled: true
195
195
  port: 3000
196
+ quick_launch: false
196
197
  reactions:
197
198
  gate_failed:
198
199
  enabled: true
@@ -496,6 +496,10 @@
496
496
  "minimum": 1,
497
497
  "maximum": 65535,
498
498
  "description": "Port the dashboard HTTP server listens on."
499
+ },
500
+ "quick_launch": {
501
+ "type": "boolean",
502
+ "description": "Enables dashboard quick-launch feature creation flow (`POST /api/run`)."
499
503
  }
500
504
  }
501
505
  },
@@ -71,6 +71,10 @@
71
71
  "minimum": 1,
72
72
  "maximum": 65535,
73
73
  "description": "Port the dashboard HTTP server listens on."
74
+ },
75
+ "quick_launch": {
76
+ "type": "boolean",
77
+ "description": "Enable dashboard quick-launch feature initialization flow."
74
78
  }
75
79
  }
76
80
  },
@@ -42,6 +42,36 @@ type ActivityFrontMatter = FeatureStateFrontMatter & {
42
42
 
43
43
  const DEFAULT_IDLE_THRESHOLD_MS = 300_000;
44
44
 
45
+ /**
46
+ * Monitors feature activity and detects stuck agents.
47
+ *
48
+ * ## Responsibilities
49
+ * - Track last activity timestamp per feature
50
+ * - Detect idle/stuck agents based on threshold
51
+ * - Notify when agents are stuck
52
+ * - Persist activity state to feature metadata
53
+ *
54
+ * ## Dependencies
55
+ * - {@link SupervisorToolCaller} - for tool invocation
56
+ * - {@link NotifierService} - for stuck agent notifications
57
+ * - Operation ledger - for activity tracking
58
+ *
59
+ * ## Key Methods
60
+ * - `getActivityState()` - get current activity snapshot
61
+ * - `checkAndNotifyStuck()` - check if stuck and notify
62
+ *
63
+ * ## Error Conditions
64
+ * - Activity persistence failures are logged but don't block
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const monitor = new ActivityMonitorService({ toolCaller, notifier });
69
+ * const state = await monitor.getActivityState('my_feature');
70
+ * if (state.state === 'idle') {
71
+ * await monitor.checkAndNotifyStuck('my_feature');
72
+ * }
73
+ * ```
74
+ */
45
75
  export class ActivityMonitorService {
46
76
  private readonly toolCaller: SupervisorToolCaller;
47
77
  private readonly operationLedger:
@@ -152,6 +182,12 @@ export class ActivityMonitorService {
152
182
  }
153
183
  }
154
184
 
185
+ /**
186
+ * Gets current activity snapshot for a feature.
187
+ *
188
+ * @param featureId - feature identifier
189
+ * @returns Activity snapshot with state and last event timestamp
190
+ */
155
191
  async getActivityState(featureId: string): Promise<ActivitySnapshot> {
156
192
  const response = await this.toolCaller.callTool<FeatureStatePayload>(
157
193
  'orchestrator',
@@ -169,6 +205,12 @@ export class ActivityMonitorService {
169
205
  };
170
206
  }
171
207
 
208
+ /**
209
+ * Checks if agent is stuck and sends notification.
210
+ *
211
+ * @param featureId - feature identifier
212
+ * @returns True if stuck notification was sent
213
+ */
172
214
  async checkAndNotifyStuck(featureId: string): Promise<boolean> {
173
215
  const snapshot = await this.getActivityState(featureId);
174
216
  await this.persistSnapshot(featureId, snapshot);
@@ -59,6 +59,37 @@ export interface CollisionQueueServicePort {
59
59
  ): Promise<{ data: { feature_id: string; accepted: boolean; plan_version: number } }>;
60
60
  }
61
61
 
62
+ /**
63
+ * Manages blocked feature queue and collision re-drive.
64
+ *
65
+ * ## Responsibilities
66
+ * - Add features to blocked queue when collisions detected
67
+ * - Re-drive queue when locks released or plans updated
68
+ * - Retry plan submission for unblocked features
69
+ * - Remove resolved entries from queue
70
+ *
71
+ * ## Dependencies
72
+ * Depends on {@link CollisionQueueServicePort} for:
73
+ * - Index and state operations
74
+ * - Plan submission
75
+ * - Lock primitives
76
+ *
77
+ * ## Key Methods
78
+ * - `reDriveBlockedQueue()` - retry blocked features
79
+ * - `processSingleQueueEntry()` - process one queue entry
80
+ * - `clearQueueEntry()` - remove entry from queue
81
+ *
82
+ * ## Error Conditions
83
+ * - PLAN_COLLISION - collision still exists
84
+ * - LOCK_NOT_HELD - required locks not available
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const queueService = new CollisionQueueService(port);
89
+ * const result = await queueService.reDriveBlockedQueue();
90
+ * console.log(`Retried: ${result.data.retried}, Still blocked: ${result.data.still_blocked}`);
91
+ * ```
92
+ */
62
93
  export class CollisionQueueService {
63
94
  private readonly port: CollisionQueueServicePort;
64
95
 
@@ -157,6 +188,17 @@ export class CollisionQueueService {
157
188
  }
158
189
  }
159
190
 
191
+ /**
192
+ * Re-drives blocked queue to retry unblocked features.
193
+ *
194
+ * @returns Result with processed/retried/still_blocked counts
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * const result = await queueService.reDriveBlockedQueue();
199
+ * console.log(`Retried: ${result.data.retried}`);
200
+ * ```
201
+ */
160
202
  async reDriveBlockedQueue(): Promise<{
161
203
  data: { processed: number; retried: number; still_blocked: number };
162
204
  }> {
@@ -219,6 +261,12 @@ export class CollisionQueueService {
219
261
  });
220
262
  }
221
263
 
264
+ /**
265
+ * Removes entry from blocked queue.
266
+ *
267
+ * @param featureId - feature identifier
268
+ * @returns Success response
269
+ */
222
270
  async clearQueueEntry(featureId: string): Promise<{ data: { removed: boolean } }> {
223
271
  return await this.port.withIndexLock(async () => {
224
272
  const index = await this.port.readIndex();
@@ -1,5 +1,9 @@
1
1
  import { atomicWriteJson, nowIso, readJson } from '../../core/fs.js';
2
2
 
3
+ /**
4
+ * @fileoverview Cost tracking and budget enforcement service.
5
+ */
6
+
3
7
  export interface FeatureCost {
4
8
  feature_id: string;
5
9
  tokens_used: number;
@@ -25,6 +29,39 @@ export interface CostTrackingServicePort {
25
29
  getPolicySnapshot(): Record<string, unknown>;
26
30
  }
27
31
 
32
+ /**
33
+ * Manages cost tracking and budget enforcement.
34
+ *
35
+ * ## Responsibilities
36
+ * - Record token usage and API costs per feature
37
+ * - Enforce per_feature_limit_usd budget
38
+ * - Aggregate costs by provider/model
39
+ * - Pause features exceeding budget
40
+ *
41
+ * ## Dependencies
42
+ * Depends on {@link CostTrackingServicePort} for:
43
+ * - Cost file path resolution
44
+ * - Policy budget configuration
45
+ *
46
+ * ## Key Methods
47
+ * - `recordCost()` - record cost entry
48
+ * - `getFeatureCost()` - retrieve accumulated costs
49
+ * - `checkBudget()` - enforce budget threshold
50
+ *
51
+ * ## Error Conditions
52
+ * - BUDGET_EXCEEDED - feature cost exceeds policy limit
53
+ * - FILE_NOT_FOUND - cost file does not exist
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const costService = new CostTrackingService(port);
58
+ * await costService.recordCost('my_feature', { tokens: 1000, cost_usd: 0.02 });
59
+ * const costs = await costService.getFeatureCost('my_feature');
60
+ * ```
61
+ *
62
+ * ## Cost Format
63
+ * cost.json: { entries: [{ timestamp, tokens, cost_usd, provider, model }], total_usd }
64
+ */
28
65
  export class CostTrackingService {
29
66
  private readonly port: CostTrackingServicePort;
30
67
 
@@ -32,6 +69,18 @@ export class CostTrackingService {
32
69
  this.port = port;
33
70
  }
34
71
 
72
+ /**
73
+ * Retrieves accumulated costs for a feature.
74
+ *
75
+ * @param featureId - feature identifier
76
+ * @returns Cost summary with entries and total
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const costs = await costService.getFeatureCost('my_feature');
81
+ * console.log(costs.total_cost_usd);
82
+ * ```
83
+ */
35
84
  async getFeatureCost(featureId: string): Promise<FeatureCost> {
36
85
  const existing = await readJson<FeatureCost>(this.port.featureCostPath(featureId), null);
37
86
  return (
@@ -44,6 +93,23 @@ export class CostTrackingService {
44
93
  );
45
94
  }
46
95
 
96
+ /**
97
+ * Records a cost entry for a feature.
98
+ *
99
+ * @param featureId - feature identifier
100
+ * @param entry - cost entry with tokens, USD amount, provider, model
101
+ * @returns Success response
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * await costService.recordCost('my_feature', {
106
+ * tokens: 1000,
107
+ * cost_usd: 0.02,
108
+ * provider: 'claude',
109
+ * model: 'claude-3-5-sonnet-20241022'
110
+ * });
111
+ * ```
112
+ */
47
113
  async recordCost(
48
114
  featureId: string,
49
115
  tokensDelta: number,
@@ -60,6 +126,20 @@ export class CostTrackingService {
60
126
  return updated;
61
127
  }
62
128
 
129
+ /**
130
+ * Checks if feature is within budget limits.
131
+ *
132
+ * @param featureId - feature identifier
133
+ * @returns Budget check result with over_budget and alert flags
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const check = await costService.checkBudget('my_feature');
138
+ * if (check.over_budget) {
139
+ * console.log('Budget exceeded!');
140
+ * }
141
+ * ```
142
+ */
63
143
  async checkBudget(featureId: string): Promise<BudgetCheckResult> {
64
144
  const policy = this.port.getPolicySnapshot();
65
145
  const budgetPolicy = (
@@ -155,6 +155,41 @@ export interface FeatureDeletionServicePort {
155
155
  locksRelease(resource: string, featureId: string): Promise<unknown>;
156
156
  }
157
157
 
158
+ /**
159
+ * Manages feature deletion and cleanup.
160
+ *
161
+ * ## Responsibilities
162
+ * - Delete feature artifacts (state, plan, logs, evidence)
163
+ * - Remove worktree and branch (optional)
164
+ * - Clean up index references
165
+ * - Release held locks
166
+ * - Remove runtime session assignments
167
+ *
168
+ * ## Dependencies
169
+ * Depends on {@link FeatureDeletionServicePort} for:
170
+ * - File operations
171
+ * - Git operations
172
+ * - Index and run-lease updates
173
+ * - Lock release
174
+ *
175
+ * ## Key Methods
176
+ * - `featureDelete()` - delete feature with configurable cleanup
177
+ *
178
+ * ## Error Conditions
179
+ * - FILE_NOT_FOUND - feature does not exist
180
+ * - RUN_ALREADY_ACTIVE - cannot delete during active run
181
+ * - GIT_ERROR - worktree/branch removal failed
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const deletionService = new FeatureDeletionService(port);
186
+ * await deletionService.featureDelete('my_feature', {
187
+ * dry_run: false,
188
+ * remove_worktree: true,
189
+ * remove_branch: 'safe'
190
+ * });
191
+ * ```
192
+ */
158
193
  export class FeatureDeletionService {
159
194
  private readonly port: FeatureDeletionServicePort;
160
195
 
@@ -162,6 +197,28 @@ export class FeatureDeletionService {
162
197
  this.port = port;
163
198
  }
164
199
 
200
+ /**
201
+ * Deletes feature artifacts with configurable cleanup options.
202
+ *
203
+ * @param featureId - feature identifier
204
+ * @param options - deletion options (dry_run, remove_worktree, remove_branch)
205
+ * @returns Deletion result with cleanup summary
206
+ * @throws FILE_NOT_FOUND - feature does not exist
207
+ * @throws RUN_ALREADY_ACTIVE - cannot delete during active run
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * // Preview deletion
212
+ * await deletionService.featureDelete('my_feature', { dry_run: true });
213
+ *
214
+ * // Execute deletion with worktree cleanup
215
+ * await deletionService.featureDelete('my_feature', {
216
+ * dry_run: false,
217
+ * remove_worktree: true,
218
+ * remove_branch: 'safe'
219
+ * });
220
+ * ```
221
+ */
165
222
  async featureDelete(
166
223
  featureId: string | null,
167
224
  options: DeleteOptions = {},
@@ -24,6 +24,10 @@ function normalizeRepoPathForState(repoRoot: string, absolutePath: string): stri
24
24
  return relative;
25
25
  }
26
26
 
27
+ /**
28
+ * @fileoverview Feature initialization and lifecycle management service.
29
+ */
30
+
27
31
  export interface FeatureLifecycleServicePort {
28
32
  getRepoRoot(): string;
29
33
  getFeaturesDir(): string;
@@ -45,6 +49,41 @@ export interface FeatureLifecycleServicePort {
45
49
  evidenceLatest(featureId: string): Promise<{ data: { latest?: unknown | null } }>;
46
50
  }
47
51
 
52
+ /**
53
+ * Manages feature initialization and lifecycle.
54
+ *
55
+ * ## Responsibilities
56
+ * - Discover canonical feature specs
57
+ * - Initialize feature directories and state.md
58
+ * - Create feature branches and worktrees
59
+ * - Validate feature IDs
60
+ * - Handle spec ingestion (canonical and non-canonical)
61
+ *
62
+ * ## Dependencies
63
+ * Depends on {@link FeatureLifecycleServicePort} for:
64
+ * - File operations and path resolution
65
+ * - Index updates
66
+ * - State/plan/evidence access
67
+ *
68
+ * ## Key Methods
69
+ * - `featureDiscoverSpecs()` - discover canonical spec files
70
+ * - `featureInit()` - initialize feature folder and state
71
+ * - `featureGetContext()` - return spec + state + plan + evidence bundle
72
+ * - `featureLogAppend()` - append timestamped log entry
73
+ *
74
+ * ## Error Conditions
75
+ * - FEATURE_ALREADY_EXISTS - feature already initialized
76
+ * - INVALID_FEATURE_ID - feature ID format invalid
77
+ * - FILE_NOT_FOUND - spec or state file missing
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const lifecycleService = new FeatureLifecycleService(port);
82
+ * const specs = await lifecycleService.featureDiscoverSpecs();
83
+ * await lifecycleService.featureInit('my_feature');
84
+ * const context = await lifecycleService.featureGetContext('my_feature');
85
+ * ```
86
+ */
48
87
  export class FeatureLifecycleService {
49
88
  private readonly port: FeatureLifecycleServicePort;
50
89
 
@@ -52,6 +91,11 @@ export class FeatureLifecycleService {
52
91
  this.port = port;
53
92
  }
54
93
 
94
+ /**
95
+ * Discovers canonical feature spec files.
96
+ *
97
+ * @returns Array of discovered specs with feature_id and path
98
+ */
55
99
  async featureDiscoverSpecs(): Promise<{
56
100
  data: { specs: Array<{ feature_id: string; spec_path: string }> };
57
101
  }> {
@@ -81,6 +125,13 @@ export class FeatureLifecycleService {
81
125
  return { data: { specs: discovered } };
82
126
  }
83
127
 
128
+ /**
129
+ * Initializes feature folder, state, branch, and worktree.
130
+ *
131
+ * @param featureId - feature identifier
132
+ * @returns Initialization result
133
+ * @throws FEATURE_ALREADY_EXISTS - feature already initialized
134
+ */
84
135
  async featureInit(featureId: string | null): Promise<{
85
136
  data: { feature_id: string | null; initialized: boolean; worktree_path: string };
86
137
  }> {
@@ -135,6 +186,12 @@ export class FeatureLifecycleService {
135
186
  };
136
187
  }
137
188
 
189
+ /**
190
+ * Returns complete feature context bundle.
191
+ *
192
+ * @param featureId - feature identifier
193
+ * @returns Context bundle with spec, state, plan, evidence, QA index
194
+ */
138
195
  async featureGetContext(featureId: string): Promise<{
139
196
  data: {
140
197
  feature_id: string;
@@ -163,6 +220,14 @@ export class FeatureLifecycleService {
163
220
  };
164
221
  }
165
222
 
223
+ /**
224
+ * Appends timestamped entry to feature decision log.
225
+ *
226
+ * @param featureId - feature identifier
227
+ * @param note - log entry content
228
+ * @param context - actor context
229
+ * @returns Success response
230
+ */
166
231
  async featureLogAppend(
167
232
  featureId: string,
168
233
  note: string,
@@ -40,12 +40,58 @@ function readVersion(frontMatter: AnyRecord): number {
40
40
  return 0;
41
41
  }
42
42
 
43
+ /**
44
+ * @fileoverview Feature state persistence and version management service.
45
+ */
46
+
43
47
  export interface FeatureStateServicePort {
44
48
  withFeatureLock<T>(featureId: string, operation: () => Promise<T>): Promise<T>;
45
49
  readState(featureId: string): Promise<StateReadResult>;
46
50
  writeState(featureId: string, frontMatter: AnyRecord, body?: string): Promise<void>;
47
51
  }
48
52
 
53
+ /**
54
+ * Manages feature state persistence with version control.
55
+ *
56
+ * ## Responsibilities
57
+ * - Read/write state.md files (YAML front matter + markdown body)
58
+ * - Parse and validate front matter
59
+ * - Enforce optimistic concurrency via version guards
60
+ * - Atomic state updates with file locking
61
+ *
62
+ * ## Dependencies
63
+ * Depends on {@link FeatureStateServicePort} for:
64
+ * - File operations and state path resolution
65
+ * - Feature-level locking primitives
66
+ *
67
+ * ## Key Methods
68
+ * - `featureStateGet()` - read parsed state
69
+ * - `featureStatePatch()` - update state with version guard
70
+ * - `updateState()` - internal atomic update with custom updater
71
+ *
72
+ * ## Error Conditions
73
+ * - FILE_NOT_FOUND - state file does not exist
74
+ * - VERSION_CONFLICT - concurrent state update detected
75
+ * - INVALID_STATE_TRANSITION - illegal status transition
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const stateService = new FeatureStateService(port);
80
+ * const state = await stateService.featureStateGet('my_feature');
81
+ * await stateService.featureStatePatch('my_feature', { status: 'building' }, 1);
82
+ * ```
83
+ *
84
+ * ## State Format
85
+ * ```markdown
86
+ * ---
87
+ * feature_id: my_feature
88
+ * version: 5
89
+ * status: building
90
+ * ---
91
+ * # Feature State
92
+ * Body content...
93
+ * ```
94
+ */
49
95
  export class FeatureStateService {
50
96
  private readonly port: FeatureStateServicePort;
51
97
 
@@ -53,6 +99,19 @@ export class FeatureStateService {
53
99
  this.port = port;
54
100
  }
55
101
 
102
+ /**
103
+ * Updates feature state atomically with version guard.
104
+ *
105
+ * Internal method used by public state operations. Acquires feature lock,
106
+ * validates version, applies updater function, and writes merged state.
107
+ *
108
+ * @param featureId - feature identifier
109
+ * @param expectedVersion - expected current version (null = no check)
110
+ * @param updater - function returning state updates
111
+ * @returns Updated state frontmatter
112
+ * @throws VERSION_CONFLICT - version mismatch
113
+ * @throws INVALID_STATE_TRANSITION - illegal status transition
114
+ */
56
115
  async updateState(
57
116
  featureId: string,
58
117
  expectedVersion: number | null,
@@ -99,6 +158,19 @@ export class FeatureStateService {
99
158
  });
100
159
  }
101
160
 
161
+ /**
162
+ * Reads and parses feature state.
163
+ *
164
+ * @param featureId - feature identifier
165
+ * @returns Parsed state with frontmatter and body
166
+ * @throws FILE_NOT_FOUND - state file does not exist
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const state = await stateService.featureStateGet('my_feature');
171
+ * console.log(state.data.frontMatter.status);
172
+ * ```
173
+ */
102
174
  async featureStateGet(
103
175
  featureId: string,
104
176
  ): Promise<{ data: { front_matter: AnyRecord; body: string } }> {
@@ -111,6 +183,21 @@ export class FeatureStateService {
111
183
  };
112
184
  }
113
185
 
186
+ /**
187
+ * Updates feature state with partial updates and version guard.
188
+ *
189
+ * @param featureId - feature identifier
190
+ * @param updates - partial state updates
191
+ * @param expectedVersion - expected current version
192
+ * @returns Updated state
193
+ * @throws VERSION_CONFLICT - version mismatch
194
+ * @throws INVALID_STATE_TRANSITION - illegal status transition
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * await stateService.featureStatePatch('my_feature', { status: 'building' }, 1);
199
+ * ```
200
+ */
114
201
  async featureStatePatch(
115
202
  featureId: string,
116
203
  expectedVersion: number | null,
@@ -54,6 +54,34 @@ export interface CanonicalizedPlanInput {
54
54
  findings: GateSelectionFinding[];
55
55
  }
56
56
 
57
+ /**
58
+ * Manages gate profile selection and resolution.
59
+ *
60
+ * ## Responsibilities
61
+ * - Select gate profile based on feature state
62
+ * - Resolve profile/mode configuration
63
+ * - Apply policy defaults and fallbacks
64
+ * - Auto-heal invalid state profiles
65
+ *
66
+ * ## Dependencies
67
+ * Depends on {@link GateSelectionServicePort} for:
68
+ * - Gates configuration
69
+ * - Policy snapshot
70
+ *
71
+ * ## Key Methods
72
+ * - `resolveProfileAndMode()` - resolve profile/mode configuration
73
+ * - `selectGateProfile()` - select profile from state or policy
74
+ * - `isAutoHealInvalidStateProfileEnabled()` - check auto-heal policy
75
+ *
76
+ * ## Error Conditions
77
+ * - INVALID_ARGUMENT - unknown profile or mode
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const gateSelection = new GateSelectionService(port);
82
+ * const resolved = gateSelection.resolveProfileAndMode('fast', 'fast');
83
+ * ```
84
+ */
57
85
  export class GateSelectionService {
58
86
  private readonly port: GateSelectionServicePort;
59
87