agentic-orchestrator 0.1.26 → 0.1.28

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 (172) hide show
  1. package/AGENTS.md +2 -2
  2. package/CLAUDE.md +2 -2
  3. package/README.md +47 -14
  4. package/agentic/orchestrator/agents.yaml +13 -0
  5. package/agentic/orchestrator/policy.yaml +3 -0
  6. package/agentic/orchestrator/schemas/agents.schema.json +76 -0
  7. package/agentic/orchestrator/schemas/policy.schema.json +16 -0
  8. package/agentic/orchestrator/schemas/policy.user.schema.json +16 -0
  9. package/agentic/orchestrator/schemas/state.schema.json +53 -0
  10. package/apps/control-plane/src/application/configuration-service.ts +181 -0
  11. package/apps/control-plane/src/application/kernel-tool-wiring.ts +292 -0
  12. package/apps/control-plane/src/application/services/checkpoint-service.ts +523 -0
  13. package/apps/control-plane/src/application/services/feature-send-message-service.ts +132 -0
  14. package/apps/control-plane/src/application/services/patch-service.ts +29 -5
  15. package/apps/control-plane/src/application/services/repo-operations-service.ts +276 -0
  16. package/apps/control-plane/src/application/services/worktree-watchdog-service.ts +156 -0
  17. package/apps/control-plane/src/cli/cli-argument-parser.ts +12 -0
  18. package/apps/control-plane/src/cli/help-command-handler.ts +17 -0
  19. package/apps/control-plane/src/cli/init-command-handler.ts +31 -0
  20. package/apps/control-plane/src/cli/resume-command-handler.ts +31 -4
  21. package/apps/control-plane/src/cli/rollback-command-handler.ts +217 -0
  22. package/apps/control-plane/src/cli/run-command-handler.ts +8 -0
  23. package/apps/control-plane/src/cli/types.ts +3 -0
  24. package/apps/control-plane/src/core/kernel-types.ts +55 -0
  25. package/apps/control-plane/src/core/kernel.ts +61 -878
  26. package/apps/control-plane/src/core/tool-caller.ts +10 -0
  27. package/apps/control-plane/src/core/utils/field-readers.ts +38 -0
  28. package/apps/control-plane/src/core/utils/index-normalizer.ts +119 -0
  29. package/apps/control-plane/src/core/utils/path-normalizers.ts +22 -0
  30. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +15 -0
  31. package/apps/control-plane/src/providers/api-worker-provider.ts +14 -12
  32. package/apps/control-plane/src/providers/cli-worker-provider.ts +82 -12
  33. package/apps/control-plane/src/providers/providers.ts +45 -24
  34. package/apps/control-plane/src/providers/worker-provider-factory.ts +36 -1
  35. package/apps/control-plane/src/supervisor/run-coordinator.ts +91 -36
  36. package/apps/control-plane/src/supervisor/runtime.ts +107 -1
  37. package/apps/control-plane/src/supervisor/types.ts +9 -0
  38. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +253 -14
  39. package/apps/control-plane/test/checkpoint-service.spec.ts +537 -0
  40. package/apps/control-plane/test/cli-helpers.spec.ts +28 -0
  41. package/apps/control-plane/test/cli.unit.spec.ts +52 -0
  42. package/apps/control-plane/test/configuration-service.spec.ts +466 -0
  43. package/apps/control-plane/test/dashboard-api.integration.spec.ts +537 -0
  44. package/apps/control-plane/test/dashboard-client.spec.ts +233 -0
  45. package/apps/control-plane/test/feature-send-message-service.spec.ts +314 -0
  46. package/apps/control-plane/test/init-wizard.spec.ts +35 -0
  47. package/apps/control-plane/test/path-normalizers.spec.ts +41 -0
  48. package/apps/control-plane/test/repo-operations-service.spec.ts +339 -0
  49. package/apps/control-plane/test/resume-command.spec.ts +33 -0
  50. package/apps/control-plane/test/review-workspace-logic.spec.ts +130 -0
  51. package/apps/control-plane/test/rollback-command.spec.ts +208 -0
  52. package/apps/control-plane/test/run-coordinator.spec.ts +119 -0
  53. package/apps/control-plane/test/worker-decision-loop.spec.ts +209 -0
  54. package/apps/control-plane/test/worker-provider-adapters.spec.ts +102 -0
  55. package/apps/control-plane/test/worker-provider-factory.spec.ts +14 -0
  56. package/apps/control-plane/test/worktree-watchdog-service.spec.ts +147 -0
  57. package/config/agentic/orchestrator/agents.yaml +13 -0
  58. package/dist/apps/control-plane/application/configuration-service.d.ts +19 -0
  59. package/dist/apps/control-plane/application/configuration-service.js +123 -0
  60. package/dist/apps/control-plane/application/configuration-service.js.map +1 -0
  61. package/dist/apps/control-plane/application/kernel-tool-wiring.d.ts +39 -0
  62. package/dist/apps/control-plane/application/kernel-tool-wiring.js +38 -0
  63. package/dist/apps/control-plane/application/kernel-tool-wiring.js.map +1 -0
  64. package/dist/apps/control-plane/application/services/checkpoint-service.d.ts +84 -0
  65. package/dist/apps/control-plane/application/services/checkpoint-service.js +367 -0
  66. package/dist/apps/control-plane/application/services/checkpoint-service.js.map +1 -0
  67. package/dist/apps/control-plane/application/services/feature-send-message-service.d.ts +25 -0
  68. package/dist/apps/control-plane/application/services/feature-send-message-service.js +105 -0
  69. package/dist/apps/control-plane/application/services/feature-send-message-service.js.map +1 -0
  70. package/dist/apps/control-plane/application/services/patch-service.d.ts +6 -0
  71. package/dist/apps/control-plane/application/services/patch-service.js +11 -2
  72. package/dist/apps/control-plane/application/services/patch-service.js.map +1 -1
  73. package/dist/apps/control-plane/application/services/repo-operations-service.d.ts +70 -0
  74. package/dist/apps/control-plane/application/services/repo-operations-service.js +213 -0
  75. package/dist/apps/control-plane/application/services/repo-operations-service.js.map +1 -0
  76. package/dist/apps/control-plane/application/services/worktree-watchdog-service.d.ts +23 -0
  77. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js +119 -0
  78. package/dist/apps/control-plane/application/services/worktree-watchdog-service.js.map +1 -0
  79. package/dist/apps/control-plane/cli/cli-argument-parser.js +12 -0
  80. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  81. package/dist/apps/control-plane/cli/help-command-handler.js +17 -0
  82. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  83. package/dist/apps/control-plane/cli/init-command-handler.js +23 -0
  84. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  85. package/dist/apps/control-plane/cli/resume-command-handler.js +25 -5
  86. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
  87. package/dist/apps/control-plane/cli/rollback-command-handler.d.ts +6 -0
  88. package/dist/apps/control-plane/cli/rollback-command-handler.js +177 -0
  89. package/dist/apps/control-plane/cli/rollback-command-handler.js.map +1 -0
  90. package/dist/apps/control-plane/cli/run-command-handler.js +7 -1
  91. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  92. package/dist/apps/control-plane/cli/types.d.ts +3 -0
  93. package/dist/apps/control-plane/cli/types.js +1 -0
  94. package/dist/apps/control-plane/cli/types.js.map +1 -1
  95. package/dist/apps/control-plane/core/configuration-service.d.ts +25 -0
  96. package/dist/apps/control-plane/core/configuration-service.js +130 -0
  97. package/dist/apps/control-plane/core/configuration-service.js.map +1 -0
  98. package/dist/apps/control-plane/core/kernel-tool-wiring.d.ts +50 -0
  99. package/dist/apps/control-plane/core/kernel-tool-wiring.js +44 -0
  100. package/dist/apps/control-plane/core/kernel-tool-wiring.js.map +1 -0
  101. package/dist/apps/control-plane/core/kernel-types.d.ts +48 -0
  102. package/dist/apps/control-plane/core/kernel-types.js +2 -0
  103. package/dist/apps/control-plane/core/kernel-types.js.map +1 -0
  104. package/dist/apps/control-plane/core/kernel.d.ts +17 -48
  105. package/dist/apps/control-plane/core/kernel.js +44 -539
  106. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  107. package/dist/apps/control-plane/core/tool-caller.d.ts +10 -0
  108. package/dist/apps/control-plane/core/utils/error-normalizer.d.ts +2 -0
  109. package/dist/apps/control-plane/core/utils/error-normalizer.js +51 -0
  110. package/dist/apps/control-plane/core/utils/error-normalizer.js.map +1 -0
  111. package/dist/apps/control-plane/core/utils/field-readers.d.ts +9 -0
  112. package/dist/apps/control-plane/core/utils/field-readers.js +30 -0
  113. package/dist/apps/control-plane/core/utils/field-readers.js.map +1 -0
  114. package/dist/apps/control-plane/core/utils/index-normalizer.d.ts +7 -0
  115. package/dist/apps/control-plane/core/utils/index-normalizer.js +92 -0
  116. package/dist/apps/control-plane/core/utils/index-normalizer.js.map +1 -0
  117. package/dist/apps/control-plane/core/utils/path-normalizers.d.ts +2 -0
  118. package/dist/apps/control-plane/core/utils/path-normalizers.js +17 -0
  119. package/dist/apps/control-plane/core/utils/path-normalizers.js.map +1 -0
  120. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +13 -1
  121. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  122. package/dist/apps/control-plane/providers/api-worker-provider.d.ts +4 -13
  123. package/dist/apps/control-plane/providers/api-worker-provider.js +10 -0
  124. package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -1
  125. package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +11 -13
  126. package/dist/apps/control-plane/providers/cli-worker-provider.js +64 -0
  127. package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -1
  128. package/dist/apps/control-plane/providers/providers.d.ts +31 -24
  129. package/dist/apps/control-plane/providers/providers.js +10 -0
  130. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  131. package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +11 -0
  132. package/dist/apps/control-plane/providers/worker-provider-factory.js +20 -1
  133. package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
  134. package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +3 -0
  135. package/dist/apps/control-plane/supervisor/run-coordinator.js +81 -33
  136. package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
  137. package/dist/apps/control-plane/supervisor/runtime.d.ts +8 -1
  138. package/dist/apps/control-plane/supervisor/runtime.js +90 -0
  139. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  140. package/dist/apps/control-plane/supervisor/types.d.ts +11 -0
  141. package/dist/apps/control-plane/supervisor/types.js.map +1 -1
  142. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +21 -1
  143. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +207 -13
  144. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  145. package/package.json +1 -1
  146. package/packages/web-dashboard/package.json +2 -0
  147. package/packages/web-dashboard/src/app/analytics/page.tsx +83 -2
  148. package/packages/web-dashboard/src/app/api/actions/route.ts +92 -1
  149. package/packages/web-dashboard/src/app/api/analytics/route.ts +5 -2
  150. package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/[checkpointId]/diff/route.ts +43 -0
  151. package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/compare/route.ts +45 -0
  152. package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/stream/route.ts +170 -0
  153. package/packages/web-dashboard/src/app/api/features/[id]/file-diff/route.ts +144 -0
  154. package/packages/web-dashboard/src/app/api/features/[id]/log-stream/route.ts +167 -0
  155. package/packages/web-dashboard/src/app/api/features/[id]/raw-logs/[filename]/route.ts +65 -0
  156. package/packages/web-dashboard/src/app/api/features/[id]/raw-logs/route.ts +63 -0
  157. package/packages/web-dashboard/src/app/api/features/[id]/timeline/route.ts +60 -0
  158. package/packages/web-dashboard/src/app/feature/[id]/page.tsx +32 -11
  159. package/packages/web-dashboard/src/app/globals.css +2 -0
  160. package/packages/web-dashboard/src/components/detail-panel.tsx +483 -0
  161. package/packages/web-dashboard/src/components/review-workspace.tsx +1162 -0
  162. package/packages/web-dashboard/src/lib/aop-client.ts +725 -0
  163. package/packages/web-dashboard/src/lib/review-contracts.ts +182 -0
  164. package/packages/web-dashboard/src/lib/review-workspace-logic.ts +64 -0
  165. package/packages/web-dashboard/src/lib/types.ts +131 -0
  166. package/packages/web-dashboard/src/styles/dashboard.module.css +333 -0
  167. package/spec-files/completed/agentic_orchestrator_execution_mode_spec.md +1905 -0
  168. package/spec-files/outstanding/agentic_orchestrator_runtime_inspection_spec.md +940 -0
  169. package/spec-files/outstanding/execution_mode_critical_review.md +355 -0
  170. package/spec-files/outstanding/shadow_workspace_implementation_spec.md +1271 -0
  171. package/spec-files/outstanding/shadow_workspace_spec_summary.md +222 -0
  172. package/spec-files/progress.md +269 -1
@@ -0,0 +1,940 @@
1
+ # Feature Spec: Runtime File Inspection (AOP Dashboard)
2
+
3
+ > Purpose: Enable direct inspection of `.aop/runtime` artifacts (Operation Ledger and Worker Events) through the dashboard with time-sorted, formatted views per feature.
4
+
5
+ **Version:** 1.0
6
+ **Date:** 2026-03-05
7
+ **Status:** Outstanding
8
+ **Roadmap Mapping:** M46
9
+ **Depends On:** M45 (Dashboard Advanced UX)
10
+
11
+ ---
12
+
13
+ ## 0. Scope and Standards
14
+
15
+ ### 0.1 Primary User Job
16
+
17
+ **Operator/Debugger Job:** Understand what happened during a feature run by inspecting:
18
+
19
+ - Operation Ledger: idempotent tool invocations with request/response payloads
20
+ - Worker Events: agent lifecycle events (started, completed, failed, timeout)
21
+
22
+ **Key Questions This Feature Answers:**
23
+
24
+ 1. What tools were called for this feature and what were the results?
25
+ 2. When did the agent start/stop/fail/timeout?
26
+ 3. What was the sequence of events leading to a failure?
27
+ 4. Were there any retries or duplicate operations?
28
+
29
+ ### 0.2 UX Principles
30
+
31
+ 1. **Time-first ordering:** All events sorted by timestamp (newest first by default)
32
+ 2. **Progressive disclosure:** Raw JSON collapsed by default, formatted summary visible
33
+ 3. **Feature-scoped:** Filter to single feature ID, not global view
34
+ 4. **Read-only:** No mutation of runtime files through UI
35
+ 5. **Performance-bounded:** Limit display to last N events, paginate if needed
36
+
37
+ ### 0.3 Quality Standards
38
+
39
+ - TypeScript strict mode passes
40
+ - ESLint zero warnings
41
+ - Coverage >= 90% for new code
42
+ - API response time < 200ms for typical feature (< 100 events)
43
+ - Graceful degradation when files are large (> 1000 events)
44
+ - Must pass `npm run verify` checks
45
+
46
+ ---
47
+
48
+ ## 1. Runtime File Structure
49
+
50
+ ### 1.1 Run ID Tracking in Feature State
51
+
52
+ **Schema Change Required:** Add `run_history` field to `state.schema.json`
53
+
54
+ **Location:** `.aop/features/<feature_id>/state.md` (YAML frontmatter)
55
+
56
+ **New Field:**
57
+
58
+ ```yaml
59
+ run_history:
60
+ - run_id: 'run:8efe99b2-bba0-473a-ad2e-22c54153fdd8'
61
+ started_at: '2026-03-05T22:24:39.635Z'
62
+ ended_at: '2026-03-05T23:00:09.599Z'
63
+ status: 'failed'
64
+ - run_id: 'run:69c36d92-3255-435a-806a-6425461e5aa8'
65
+ started_at: '2026-03-05T06:05:12.123Z'
66
+ ended_at: '2026-03-05T06:07:17.975Z'
67
+ status: 'completed'
68
+ ```
69
+
70
+ **Schema Definition:**
71
+
72
+ ```json
73
+ {
74
+ "run_history": {
75
+ "type": "array",
76
+ "description": "Time-sorted list of run IDs associated with this feature (newest first). Updated by supervisor on run start/end.",
77
+ "items": {
78
+ "type": "object",
79
+ "required": ["run_id", "started_at"],
80
+ "properties": {
81
+ "run_id": {
82
+ "type": "string",
83
+ "description": "Run ID from runtime_sessions"
84
+ },
85
+ "started_at": {
86
+ "type": "string",
87
+ "format": "date-time",
88
+ "description": "When this run started working on this feature"
89
+ },
90
+ "ended_at": {
91
+ "type": "string",
92
+ "format": "date-time",
93
+ "description": "When this run stopped working on this feature (null if still active)"
94
+ },
95
+ "status": {
96
+ "type": "string",
97
+ "enum": ["active", "completed", "failed", "timeout"],
98
+ "description": "Final status of this run for this feature"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ **Update Behavior:**
107
+
108
+ - **On feature.init:** Create `run_history` with current run_id, status `active`
109
+ - **On supervisor start:** Append current run_id to `run_history` if not already present
110
+ - **On supervisor stop/complete:** Update latest run_history entry with `ended_at` and final `status`
111
+ - **On feature.delete:** Archive run_history before deletion (optional)
112
+
113
+ ### 1.2 Operation Ledger Files
114
+
115
+ **Location:** `.aop/runtime/operation-ledger/run:<run_id>.json`
116
+
117
+ **Structure:**
118
+
119
+ ```json
120
+ {
121
+ "run_id": "run:69c36d92-3255-435a-806a-6425461e5aa8",
122
+ "updated_at": "2026-03-05T06:07:17.975Z",
123
+ "operations": {
124
+ "<operation_id>": {
125
+ "operation_id": "feature_delete__my_feature__uuid",
126
+ "tool_name": "feature.delete",
127
+ "request_hash": "sha256...",
128
+ "response": {
129
+ "ok": true,
130
+ "data": { ... }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ **Key Fields:**
138
+
139
+ - `operation_id`: Unique ID for idempotency tracking
140
+ - `tool_name`: MCP tool invoked (e.g., `feature.init`, `plan.submit`, `gates.run`)
141
+ - `request_hash`: SHA256 of request payload
142
+ - `response`: Full tool response with `ok` and `data`/`error`
143
+
144
+ ### 1.3 Worker Events Files
145
+
146
+ **Location:** `.aop/runtime/worker-events/run:<run_id>.jsonl`
147
+
148
+ **Structure:** JSONL (one JSON object per line)
149
+
150
+ ```json
151
+ {"ts":"2026-03-05T22:24:39.635Z","run_id":"run:8efe99b2...","feature_id":"my_feature","role":"planner","phase":"execution","event_type":"worker_started","output_types":[],"patch_count":0,"plan_submission_count":0,"request_count":0,"note_count":0,"valid":true,"error_code":null,"provider":"claude","model":"local-default","watchdog_reason":null,"signal":null}
152
+ {"ts":"2026-03-05T22:25:17.441Z","run_id":"run:8efe99b2...","feature_id":"my_feature","role":"planner","phase":"execution","event_type":"worker_completed","output_types":["PLAN_SUBMISSION"],"patch_count":0,"plan_submission_count":1,"request_count":0,"note_count":0,"valid":true,"error_code":null,"provider":"claude","model":"local-default","watchdog_reason":null,"signal":null}
153
+ ```
154
+
155
+ **Key Fields:**
156
+
157
+ - `ts`: ISO 8601 timestamp
158
+ - `feature_id`: Feature this event belongs to
159
+ - `role`: Agent role (`planner`, `builder`, `qa`)
160
+ - `event_type`: `worker_started`, `worker_completed`, `worker_failed`, `worker_timeout`
161
+ - `valid`: Boolean indicating success/failure
162
+ - `error_code`: Error code if `valid=false`
163
+ - `watchdog_reason`: Timeout/failure reason
164
+
165
+ ---
166
+
167
+ ## 2. API Contract
168
+
169
+ ### 2.1 Operation Ledger Endpoint
170
+
171
+ **Route:** `GET /api/runtime/operations`
172
+
173
+ **Query Parameters:**
174
+
175
+ - `feature_id` (required): Feature ID to filter operations
176
+ - `run_id` (optional): Specific run ID (defaults to latest from `run_history`)
177
+ - `project` (optional): Project name for multi-project setups
178
+ - `limit` (optional, default 100): Max operations to return
179
+ - `offset` (optional, default 0): Pagination offset
180
+
181
+ **Run ID Resolution:**
182
+
183
+ 1. If `run_id` provided, use it directly
184
+ 2. Else read `.aop/features/<feature_id>/state.md`
185
+ 3. Extract `run_history[0].run_id` (latest run)
186
+ 4. If `run_history` is empty or missing, return `run_not_found`
187
+
188
+ **Response Envelope:**
189
+
190
+ ```typescript
191
+ {
192
+ ok: true,
193
+ data: {
194
+ run_id: string;
195
+ feature_id: string;
196
+ updated_at: string;
197
+ run_info: {
198
+ started_at: string;
199
+ ended_at: string | null;
200
+ status: 'active' | 'completed' | 'failed' | 'timeout';
201
+ };
202
+ operations: Array<{
203
+ operation_id: string;
204
+ tool_name: string;
205
+ request_hash: string;
206
+ timestamp: string; // extracted from operation_id or response
207
+ response: {
208
+ ok: boolean;
209
+ data?: unknown;
210
+ error?: {
211
+ code: string;
212
+ message: string;
213
+ details?: unknown;
214
+ };
215
+ };
216
+ }>;
217
+ total_count: number;
218
+ has_more: boolean;
219
+ },
220
+ metadata: {
221
+ source: 'runtime_ledger';
222
+ }
223
+ }
224
+ ```
225
+
226
+ **Error Codes:**
227
+
228
+ - `feature_not_found`: Feature ID not found in index
229
+ - `run_not_found`: No run_history found for feature
230
+ - `ledger_not_found`: Operation ledger file missing for run_id
231
+ - `ledger_parse_error`: JSON parse failure
232
+
233
+ ### 2.2 Worker Events Endpoint
234
+
235
+ **Route:** `GET /api/runtime/events`
236
+
237
+ **Query Parameters:**
238
+
239
+ - `feature_id` (required): Feature ID to filter events
240
+ - `run_id` (optional): Specific run ID (defaults to latest from `run_history`)
241
+ - `project` (optional): Project name for multi-project setups
242
+ - `limit` (optional, default 100): Max events to return
243
+ - `offset` (optional, default 0): Pagination offset
244
+ - `event_type` (optional): Filter by event type (comma-separated)
245
+ - `role` (optional): Filter by role (comma-separated)
246
+
247
+ **Run ID Resolution:**
248
+
249
+ 1. If `run_id` provided, use it directly
250
+ 2. Else read `.aop/features/<feature_id>/state.md`
251
+ 3. Extract `run_history[0].run_id` (latest run)
252
+ 4. If `run_history` is empty or missing, return `run_not_found`
253
+
254
+ **Response Envelope:**
255
+
256
+ ```typescript
257
+ {
258
+ ok: true,
259
+ data: {
260
+ run_id: string;
261
+ feature_id: string;
262
+ run_info: {
263
+ started_at: string;
264
+ ended_at: string | null;
265
+ status: 'active' | 'completed' | 'failed' | 'timeout';
266
+ };
267
+ events: Array<{
268
+ ts: string;
269
+ run_id: string;
270
+ feature_id: string;
271
+ role: string;
272
+ phase: string;
273
+ event_type: string;
274
+ output_types: string[];
275
+ patch_count: number;
276
+ plan_submission_count: number;
277
+ request_count: number;
278
+ note_count: number;
279
+ valid: boolean;
280
+ error_code: string | null;
281
+ provider: string;
282
+ model: string;
283
+ watchdog_reason: string | null;
284
+ signal: string | null;
285
+ exit_code?: number;
286
+ timeout_ms?: number;
287
+ elapsed_ms?: number;
288
+ }>;
289
+ total_count: number;
290
+ has_more: boolean;
291
+ },
292
+ metadata: {
293
+ source: 'runtime_events';
294
+ }
295
+ }
296
+ ```
297
+
298
+ **Error Codes:**
299
+
300
+ - `feature_not_found`: Feature ID not found in index
301
+ - `run_not_found`: No run_history found for feature
302
+ - `events_not_found`: Worker events file missing for run_id
303
+ - `events_parse_error`: JSONL parse failure
304
+
305
+ ### 2.3 Run History Endpoint (New)
306
+
307
+ **Route:** `GET /api/runtime/runs`
308
+
309
+ **Query Parameters:**
310
+
311
+ - `feature_id` (required): Feature ID to get run history
312
+ - `project` (optional): Project name for multi-project setups
313
+
314
+ **Response Envelope:**
315
+
316
+ ```typescript
317
+ {
318
+ ok: true,
319
+ data: {
320
+ feature_id: string;
321
+ runs: Array<{
322
+ run_id: string;
323
+ started_at: string;
324
+ ended_at: string | null;
325
+ status: 'active' | 'completed' | 'failed' | 'timeout';
326
+ has_operations: boolean;
327
+ has_events: boolean;
328
+ }>;
329
+ },
330
+ metadata: {
331
+ source: 'feature_state';
332
+ }
333
+ }
334
+ ```
335
+
336
+ **Purpose:** Allow UI to show run selector dropdown with all historical runs for a feature
337
+
338
+ **Error Codes:**
339
+
340
+ - `feature_not_found`: Feature ID not found in index
341
+ - `state_not_found`: Feature state file missing
342
+ - `state_parse_error`: YAML parse failure
343
+
344
+ ---
345
+
346
+ ## 3. UI Components
347
+
348
+ ### 3.1 Runtime Inspector Panel (New Component)
349
+
350
+ **File:** `packages/web-dashboard/src/components/runtime-inspector.tsx`
351
+
352
+ **Location:** Appears in Feature Detail Panel (right side) as a new tab
353
+
354
+ **Tabs:**
355
+
356
+ 1. **Operations** - Operation Ledger view
357
+ 2. **Events** - Worker Events view
358
+
359
+ **Run Selector:**
360
+
361
+ - Dropdown at top of panel showing all runs from `run_history`
362
+ - Format: `Run <short_id> - <started_at> - <status>`
363
+ - Default: Latest run (index 0)
364
+ - Fetches from `GET /api/runtime/runs?feature_id=<id>`
365
+
366
+ **Default State:**
367
+
368
+ - Operations tab selected
369
+ - Latest run selected
370
+ - Last 50 operations shown
371
+ - Newest first (reverse chronological)
372
+ - Raw JSON collapsed
373
+
374
+ **Interaction:**
375
+
376
+ - Select run from dropdown → refetch operations/events for that run
377
+ - Click operation row to expand/collapse JSON
378
+ - Copy button for operation_id and request_hash
379
+ - Filter by tool_name (dropdown)
380
+ - Filter by success/failure (toggle)
381
+ - Pagination controls at bottom
382
+
383
+ ### 3.2 Operations List View
384
+
385
+ **Requirements:**
386
+
387
+ **Summary Row (Always Visible):**
388
+
389
+ ```
390
+ [Icon] tool_name | timestamp | status_badge | expand_icon
391
+ ```
392
+
393
+ **Status Badge:**
394
+
395
+ - ✅ Success (green) - `response.ok === true`
396
+ - ❌ Failed (red) - `response.ok === false`
397
+ - ⚠️ Partial (yellow) - `response.ok === true` but `response.data` contains warnings
398
+
399
+ **Expanded View:**
400
+
401
+ ```
402
+ Operation ID: <operation_id> [Copy]
403
+ Request Hash: <request_hash> [Copy]
404
+ Tool: <tool_name>
405
+ Timestamp: <formatted_timestamp>
406
+
407
+ Response:
408
+ <formatted_json_with_syntax_highlighting>
409
+ ```
410
+
411
+ **Formatting:**
412
+
413
+ - Use `JSON.stringify(response, null, 2)` for readability
414
+ - Syntax highlighting for JSON (optional, use `<pre>` with CSS if no library)
415
+ - Max height 400px with scroll for large responses
416
+
417
+ ### 3.3 Events Timeline View
418
+
419
+ **Requirements:**
420
+
421
+ **Timeline Row (Always Visible):**
422
+
423
+ ```
424
+ [timestamp] [role_badge] [event_type_icon] event_type | duration | status
425
+ ```
426
+
427
+ **Role Badge:**
428
+
429
+ - 🎯 Planner (blue)
430
+ - 🔨 Builder (orange)
431
+ - ✅ QA (green)
432
+
433
+ **Event Type Icons:**
434
+
435
+ - ▶️ `worker_started`
436
+ - ✅ `worker_completed`
437
+ - ❌ `worker_failed`
438
+ - ⏱️ `worker_timeout`
439
+
440
+ **Duration Calculation:**
441
+
442
+ - For `worker_completed`/`worker_failed`/`worker_timeout`: show `elapsed_ms` if present
443
+ - For `worker_started`: calculate duration to next event for same role
444
+
445
+ **Expanded View:**
446
+
447
+ ```
448
+ Timestamp: <formatted_timestamp>
449
+ Run ID: <run_id>
450
+ Feature: <feature_id>
451
+ Role: <role>
452
+ Phase: <phase>
453
+ Event Type: <event_type>
454
+ Valid: <valid>
455
+ Error Code: <error_code>
456
+ Provider: <provider>
457
+ Model: <model>
458
+ Watchdog Reason: <watchdog_reason>
459
+ Signal: <signal>
460
+ Exit Code: <exit_code>
461
+ Timeout: <timeout_ms>ms
462
+ Elapsed: <elapsed_ms>ms
463
+
464
+ Output Types: <output_types.join(', ')>
465
+ Patch Count: <patch_count>
466
+ Plan Submissions: <plan_submission_count>
467
+ Requests: <request_count>
468
+ Notes: <note_count>
469
+ ```
470
+
471
+ ### 3.4 Filter Controls
472
+
473
+ **Operations Filters:**
474
+
475
+ - Tool Name (dropdown, multi-select)
476
+ - Status (Success/Failed/All)
477
+ - Time Range (Last Hour/Last Day/All)
478
+
479
+ **Events Filters:**
480
+
481
+ - Role (Planner/Builder/QA/All)
482
+ - Event Type (Started/Completed/Failed/Timeout/All)
483
+ - Valid Only (toggle)
484
+ - Time Range (Last Hour/Last Day/All)
485
+
486
+ **Filter Persistence:**
487
+
488
+ - Store in URL query params
489
+ - Restore on page load
490
+ - Clear filters button
491
+
492
+ ---
493
+
494
+ ## 4. Implementation Details
495
+
496
+ ### 4.0 Schema and State Management Changes
497
+
498
+ **File:** `agentic/orchestrator/schemas/state.schema.json`
499
+
500
+ **Add to properties:**
501
+
502
+ ```json
503
+ {
504
+ "run_history": {
505
+ "type": "array",
506
+ "description": "Time-sorted list of run IDs associated with this feature (newest first). Updated by supervisor on run start/end.",
507
+ "default": [],
508
+ "items": {
509
+ "type": "object",
510
+ "required": ["run_id", "started_at"],
511
+ "additionalProperties": false,
512
+ "properties": {
513
+ "run_id": {
514
+ "type": "string",
515
+ "pattern": "^run:[a-f0-9-]+$",
516
+ "description": "Run ID from runtime_sessions"
517
+ },
518
+ "started_at": {
519
+ "type": "string",
520
+ "format": "date-time",
521
+ "description": "When this run started working on this feature"
522
+ },
523
+ "ended_at": {
524
+ "type": ["string", "null"],
525
+ "format": "date-time",
526
+ "description": "When this run stopped working on this feature (null if still active)"
527
+ },
528
+ "status": {
529
+ "type": "string",
530
+ "enum": ["active", "completed", "failed", "timeout"],
531
+ "description": "Final status of this run for this feature"
532
+ }
533
+ }
534
+ }
535
+ }
536
+ }
537
+ ```
538
+
539
+ **File:** `apps/control-plane/src/application/services/feature-state-service.ts`
540
+
541
+ **Changes:**
542
+
543
+ - Add `appendRunHistory(featureId, runId, startedAt)` method
544
+ - Add `updateRunHistory(featureId, runId, endedAt, status)` method
545
+ - Ensure run_history is sorted newest-first on write
546
+
547
+ **File:** `apps/control-plane/src/supervisor/runtime.ts`
548
+
549
+ **Changes:**
550
+
551
+ - On feature start: Call `featureStateService.appendRunHistory(featureId, this.runId, new Date().toISOString())`
552
+ - On feature complete/fail: Call `featureStateService.updateRunHistory(featureId, this.runId, new Date().toISOString(), status)`
553
+ - On recovery: Check if current run_id exists in run_history, append if missing
554
+
555
+ **Migration Strategy:**
556
+
557
+ - Existing features without run_history: Initialize as empty array `[]`
558
+ - No data loss: run_history is additive only
559
+ - Backward compatible: Old state files without run_history still validate (default: `[]`)
560
+
561
+ ### 4.1 Backend Implementation
562
+
563
+ **File:** `packages/web-dashboard/src/app/api/runtime/runs/route.ts` (New)
564
+
565
+ **Logic:**
566
+
567
+ 1. Resolve `feature_id` and `project` from query params
568
+ 2. Read `.aop/features/<feature_id>/state.md`
569
+ 3. Parse YAML frontmatter to extract `run_history`
570
+ 4. For each run, check if ledger/events files exist
571
+ 5. Return formatted response with run list
572
+
573
+ **File:** `packages/web-dashboard/src/app/api/runtime/operations/route.ts`
574
+
575
+ **Logic:**
576
+
577
+ 1. Resolve `feature_id` and `project` from query params
578
+ 2. If `run_id` provided, use it; else read state.md and extract `run_history[0].run_id`
579
+ 3. If no run_history, return `run_not_found`
580
+ 4. Read `.aop/runtime/operation-ledger/run:<run_id>.json`
581
+ 5. Parse JSON and extract operations
582
+ 6. Filter operations by `feature_id` (check operation_id contains feature_id)
583
+ 7. Sort by timestamp (extract from operation_id or use file `updated_at`)
584
+ 8. Apply pagination (limit/offset)
585
+ 9. Return formatted response with run_info from run_history
586
+
587
+ **File:** `packages/web-dashboard/src/app/api/runtime/events/route.ts`
588
+
589
+ **Logic:**
590
+
591
+ 1. Resolve `feature_id` and `project` from query params
592
+ 2. If `run_id` provided, use it; else read state.md and extract `run_history[0].run_id`
593
+ 3. If no run_history, return `run_not_found`
594
+ 4. Read `.aop/runtime/worker-events/run:<run_id>.jsonl`
595
+ 5. Parse JSONL (split by newline, parse each line as JSON)
596
+ 6. Filter events by `feature_id`
597
+ 7. Apply filters (event_type, role, valid)
598
+ 8. Sort by `ts` (descending for newest first)
599
+ 9. Apply pagination (limit/offset)
600
+ 10. Return formatted response with run_info from run_history
601
+
602
+ **Error Handling:**
603
+
604
+ - Catch file read errors → return `ledger_not_found` or `events_not_found`
605
+ - Catch JSON parse errors → return `ledger_parse_error` or `events_parse_error`
606
+ - Handle missing run_history → return `run_not_found`
607
+ - Handle large files (> 10MB) → return `file_too_large` with suggestion to use CLI
608
+
609
+ ### 4.2 Frontend Implementation
610
+
611
+ **File:** `packages/web-dashboard/src/components/runtime-inspector.tsx`
612
+
613
+ **State Management:**
614
+
615
+ ```typescript
616
+ interface RuntimeInspectorState {
617
+ activeTab: 'operations' | 'events';
618
+ selectedRunId: string | null;
619
+ runs: RunHistoryEntry[];
620
+ operations: Operation[];
621
+ events: WorkerEvent[];
622
+ loading: boolean;
623
+ error: string | null;
624
+ filters: {
625
+ toolName?: string[];
626
+ status?: 'success' | 'failed' | 'all';
627
+ eventType?: string[];
628
+ role?: string[];
629
+ validOnly?: boolean;
630
+ timeRange?: 'hour' | 'day' | 'all';
631
+ };
632
+ pagination: {
633
+ limit: number;
634
+ offset: number;
635
+ totalCount: number;
636
+ hasMore: boolean;
637
+ };
638
+ expandedIds: Set<string>;
639
+ }
640
+
641
+ interface RunHistoryEntry {
642
+ run_id: string;
643
+ started_at: string;
644
+ ended_at: string | null;
645
+ status: 'active' | 'completed' | 'failed' | 'timeout';
646
+ has_operations: boolean;
647
+ has_events: boolean;
648
+ }
649
+ ```
650
+
651
+ **Hooks:**
652
+
653
+ - `useRunHistory(featureId)` - Fetch run history list
654
+ - `useRuntimeOperations(featureId, runId, filters, pagination)` - Fetch operations
655
+ - `useRuntimeEvents(featureId, runId, filters, pagination)` - Fetch events
656
+ - `useExpandedState()` - Manage expanded/collapsed rows
657
+
658
+ **Component Lifecycle:**
659
+
660
+ 1. Mount → fetch run history
661
+ 2. Run history loaded → select latest run (index 0)
662
+ 3. Run selected → fetch operations/events for that run
663
+ 4. Run selector change → refetch operations/events
664
+
665
+ **Performance:**
666
+
667
+ - Virtualize lists if > 100 items (use `react-window` or similar)
668
+ - Debounce filter changes (300ms)
669
+ - Cancel in-flight requests on run/filter change
670
+ - Cache responses per (feature_id, run_id) pair (60s TTL)
671
+
672
+ ### 4.3 Integration with Detail Panel
673
+
674
+ **File:** `packages/web-dashboard/src/components/detail-panel.tsx`
675
+
676
+ **Changes:**
677
+
678
+ 1. Add new tab: "Runtime" (after "Evidence" tab)
679
+ 2. Render `<RuntimeInspector featureId={selectedFeature.feature_id} />` when tab is active
680
+ 3. Badge on tab shows total operation count (if available)
681
+
682
+ **Tab Order:**
683
+
684
+ 1. Overview
685
+ 2. Plan
686
+ 3. Gates
687
+ 4. Evidence
688
+ 5. **Runtime** (new)
689
+ 6. Logs
690
+
691
+ ---
692
+
693
+ ## 5. Testing Strategy
694
+
695
+ ### 5.1 Unit Tests
696
+
697
+ **Schema Tests:**
698
+
699
+ - `schemas/state.schema.spec.ts`
700
+ - Validates run_history field structure
701
+ - Rejects invalid run_history entries
702
+ - Allows empty run_history array
703
+ - Validates date-time formats
704
+
705
+ **Backend Tests:**
706
+
707
+ - `api/runtime/runs/route.spec.ts`
708
+ - Returns run history for valid feature_id
709
+ - Returns 404 for missing feature
710
+ - Returns 404 for missing state file
711
+ - Handles YAML parse errors
712
+ - Checks file existence for operations/events
713
+
714
+ - `api/runtime/operations/route.spec.ts`
715
+ - Returns operations for valid feature_id
716
+ - Uses latest run_id when not specified
717
+ - Uses specified run_id when provided
718
+ - Returns 404 for missing feature
719
+ - Returns 404 for missing run_history
720
+ - Returns 404 for missing ledger file
721
+ - Handles JSON parse errors
722
+ - Applies pagination correctly
723
+ - Filters by tool_name
724
+ - Sorts by timestamp descending
725
+
726
+ - `api/runtime/events/route.spec.ts`
727
+ - Returns events for valid feature_id
728
+ - Uses latest run_id when not specified
729
+ - Uses specified run_id when provided
730
+ - Returns 404 for missing feature
731
+ - Returns 404 for missing run_history
732
+ - Returns 404 for missing events file
733
+ - Handles JSONL parse errors
734
+ - Applies pagination correctly
735
+ - Filters by event_type and role
736
+ - Sorts by timestamp descending
737
+
738
+ **Frontend Tests:**
739
+
740
+ - `components/runtime-inspector.spec.tsx`
741
+ - Renders operations tab by default
742
+ - Fetches run history on mount
743
+ - Selects latest run by default
744
+ - Switches between tabs
745
+ - Changes selected run
746
+ - Refetches data on run change
747
+ - Expands/collapses operation rows
748
+ - Applies filters
749
+ - Handles pagination
750
+ - Shows loading state
751
+ - Shows error state
752
+ - Copies operation_id to clipboard
753
+
754
+ ### 5.2 Integration Tests
755
+
756
+ **End-to-End:**
757
+
758
+ 1. Create feature with multiple runs
759
+ 2. Open feature detail panel
760
+ 3. Click "Runtime" tab
761
+ 4. Verify run selector appears with all runs
762
+ 5. Verify latest run is selected
763
+ 6. Verify operations list appears
764
+ 7. Select older run from dropdown
765
+ 8. Verify operations list updates
766
+ 9. Expand operation row
767
+ 10. Verify JSON response is visible
768
+ 11. Switch to Events tab
769
+ 12. Verify events timeline appears
770
+ 13. Apply filter (e.g., "Failed only")
771
+ 14. Verify filtered results
772
+
773
+ ### 5.3 Performance Tests
774
+
775
+ **Benchmarks:**
776
+
777
+ - Load run history (10 runs) in < 50ms
778
+ - Load 100 operations in < 200ms
779
+ - Load 100 events in < 200ms
780
+ - Render 100 operations in < 100ms
781
+ - Filter 100 operations in < 50ms
782
+ - Pagination in < 50ms
783
+ - Run selector change in < 100ms
784
+
785
+ **Stress Tests:**
786
+
787
+ - Handle 50 runs in history gracefully
788
+ - Handle 1000 operations gracefully (virtualization)
789
+ - Handle 1000 events gracefully (virtualization)
790
+ - Handle 10MB ledger file (return error with suggestion)
791
+
792
+ ---
793
+
794
+ ## 6. Acceptance Criteria
795
+
796
+ ### 6.1 Must Have
797
+
798
+ - [ ] Schema change: Add `run_history` field to `state.schema.json`
799
+ - [ ] Supervisor: Update run_history on feature start/stop
800
+ - [ ] FeatureStateService: Support run_history read/write
801
+ - [ ] `GET /api/runtime/runs` endpoint implemented
802
+ - [ ] `GET /api/runtime/operations` endpoint implemented
803
+ - [ ] `GET /api/runtime/events` endpoint implemented
804
+ - [ ] Run ID resolution from run_history (latest by default)
805
+ - [ ] RuntimeInspector component renders in detail panel
806
+ - [ ] Run selector dropdown with all historical runs
807
+ - [ ] Operations tab shows last 50 operations by default
808
+ - [ ] Events tab shows last 50 events by default
809
+ - [ ] Operations sorted by timestamp (newest first)
810
+ - [ ] Events sorted by timestamp (newest first)
811
+ - [ ] Expand/collapse operation rows
812
+ - [ ] Expand/collapse event rows
813
+ - [ ] Copy operation_id and request_hash
814
+ - [ ] Filter operations by tool_name
815
+ - [ ] Filter operations by success/failure
816
+ - [ ] Filter events by role
817
+ - [ ] Filter events by event_type
818
+ - [ ] Pagination controls (Next/Previous)
819
+ - [ ] Loading state
820
+ - [ ] Error state with retry button
821
+ - [ ] Empty state ("No operations recorded")
822
+ - [ ] All tests pass (>= 90% coverage)
823
+ - [ ] TypeScript strict mode passes
824
+ - [ ] ESLint zero warnings
825
+
826
+ ### 6.2 Should Have
827
+
828
+ - [ ] Syntax highlighting for JSON responses
829
+ - [ ] Duration calculation for events
830
+ - [ ] Time range filters (Last Hour/Last Day/All)
831
+ - [ ] Export operations to JSON file
832
+ - [ ] Export events to JSON file
833
+ - [ ] Search within operation responses
834
+ - [ ] Keyboard navigation (arrow keys to expand/collapse)
835
+
836
+ ### 6.3 Nice to Have
837
+
838
+ - [ ] Real-time updates via SSE (append new operations/events)
839
+ - [ ] Diff view for plan.update operations
840
+ - [ ] Link from operation to related feature state change
841
+ - [ ] Flame graph for operation timing
842
+ - [ ] Event correlation (link worker_started to worker_completed)
843
+
844
+ ---
845
+
846
+ ## 7. Non-Goals
847
+
848
+ - **Mutation of runtime files:** This feature is read-only inspection
849
+ - **Global runtime view:** Always scoped to single feature
850
+ - **Historical run comparison:** Only shows latest run (or specified run_id)
851
+ - **Real-time streaming:** Initial version uses polling/manual refresh
852
+ - **Advanced analytics:** No aggregation, charts, or trend analysis (use Analytics page)
853
+
854
+ ---
855
+
856
+ ## 8. Rollout Plan
857
+
858
+ ### 8.1 Phase 0: Schema and State Management (Week 1)
859
+
860
+ - Add `run_history` field to `state.schema.json`
861
+ - Update FeatureStateService to read/write run_history
862
+ - Update SupervisorRuntime to append run_id on feature start
863
+ - Update SupervisorRuntime to update run status on feature end
864
+ - Add migration for existing features (backfill empty run_history)
865
+ - Add unit tests for schema validation
866
+ - Add unit tests for state service
867
+
868
+ ### 8.2 Phase 1: Backend API (Week 2)
869
+
870
+ - Implement `/api/runtime/runs` endpoint
871
+ - Implement `/api/runtime/operations` endpoint with run_history resolution
872
+ - Implement `/api/runtime/events` endpoint with run_history resolution
873
+ - Add unit tests
874
+ - Add integration tests
875
+ - Document API in README
876
+
877
+ ### 8.3 Phase 2: Frontend UI (Week 3)
878
+
879
+ - Implement RuntimeInspector component
880
+ - Add run selector dropdown
881
+ - Add Operations tab
882
+ - Add Events tab
883
+ - Add filter controls
884
+ - Add pagination
885
+ - Integrate with detail panel
886
+
887
+ ### 8.4 Phase 3: Polish (Week 4)
888
+
889
+ - Add syntax highlighting
890
+ - Add duration calculations
891
+ - Add export functionality
892
+ - Add keyboard navigation
893
+ - Performance optimization
894
+ - Accessibility audit
895
+
896
+ ### 8.5 Phase 4: Documentation (Week 4)
897
+
898
+ - Update state.schema.json documentation
899
+ - Update dashboard README
900
+ - Add screenshots to docs
901
+ - Create user guide
902
+ - Update CLAUDE.md and AGENTS.md
903
+
904
+ ---
905
+
906
+ ## 9. Success Metrics
907
+
908
+ ### 9.1 Functional Metrics
909
+
910
+ - API response time < 200ms (p95)
911
+ - UI render time < 100ms (p95)
912
+ - Zero crashes on large files (< 10MB)
913
+ - 100% test coverage for new code
914
+
915
+ ### 9.2 User Metrics
916
+
917
+ - Time to find failure cause reduced by 50%
918
+ - Number of "What happened?" questions reduced
919
+ - Operator satisfaction score > 4/5
920
+
921
+ ---
922
+
923
+ ## 10. References
924
+
925
+ ### 10.1 Related Documents
926
+
927
+ - `spec-files/completed/agentic_orchestrator_dashboard_advanced_ux_spec.md` - Dashboard UX standards
928
+ - `README.md` - CLI and tool contracts
929
+ - `CLAUDE.md` - Architecture patterns
930
+
931
+ ### 10.2 Related Code
932
+
933
+ - `packages/web-dashboard/src/components/detail-panel.tsx` - Feature detail panel
934
+ - `packages/web-dashboard/src/lib/aop-client.ts` - API client utilities
935
+ - `apps/control-plane/src/mcp/tool-runtime.ts` - Operation ledger writer
936
+ - `apps/control-plane/src/supervisor/runtime.ts` - Worker events writer
937
+
938
+ ---
939
+
940
+ **End of Specification**