agentic-orchestrator 0.1.13 → 0.1.15

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 (108) hide show
  1. package/AGENTS.md +139 -0
  2. package/CLAUDE.md +12 -0
  3. package/agentic/orchestrator/agents.yaml +3 -0
  4. package/agentic/orchestrator/defaults/policy.defaults.yaml +3 -0
  5. package/agentic/orchestrator/policy.yaml +3 -0
  6. package/agentic/orchestrator/schemas/agents.schema.json +15 -0
  7. package/agentic/orchestrator/schemas/policy.schema.json +14 -0
  8. package/apps/control-plane/src/cli/cli-argument-parser.ts +7 -0
  9. package/apps/control-plane/src/cli/help-command-handler.ts +8 -0
  10. package/apps/control-plane/src/cli/init-command-handler.ts +6 -0
  11. package/apps/control-plane/src/cli/resume-command-handler.ts +31 -2
  12. package/apps/control-plane/src/cli/run-command-handler.ts +31 -3
  13. package/apps/control-plane/src/cli/types.ts +1 -0
  14. package/apps/control-plane/src/core/error-codes.ts +4 -0
  15. package/apps/control-plane/src/core/kernel.ts +3 -0
  16. package/apps/control-plane/src/index.ts +14 -0
  17. package/apps/control-plane/src/interfaces/cli/bootstrap.ts +25 -3
  18. package/apps/control-plane/src/providers/api-worker-provider.ts +115 -0
  19. package/apps/control-plane/src/providers/cli-worker-provider.ts +385 -0
  20. package/apps/control-plane/src/providers/output-parsers/generic-output-parser.ts +100 -0
  21. package/apps/control-plane/src/providers/output-parsers/index.ts +11 -0
  22. package/apps/control-plane/src/providers/output-parsers/types.ts +23 -0
  23. package/apps/control-plane/src/providers/providers.ts +19 -0
  24. package/apps/control-plane/src/providers/worker-provider-factory.ts +198 -0
  25. package/apps/control-plane/src/supervisor/build-wave-executor.ts +140 -3
  26. package/apps/control-plane/src/supervisor/planning-wave-executor.ts +125 -5
  27. package/apps/control-plane/src/supervisor/qa-wave-executor.ts +144 -2
  28. package/apps/control-plane/src/supervisor/runtime.ts +24 -0
  29. package/apps/control-plane/src/supervisor/worker-decision-loop.ts +134 -12
  30. package/apps/control-plane/test/cli.unit.spec.ts +36 -0
  31. package/apps/control-plane/test/dashboard-api.integration.spec.ts +2 -2
  32. package/apps/control-plane/test/resume-command.spec.ts +31 -1
  33. package/apps/control-plane/test/worker-decision-loop.spec.ts +3 -0
  34. package/apps/control-plane/test/worker-execution-policy.spec.ts +284 -0
  35. package/apps/control-plane/test/worker-provider-adapters.spec.ts +440 -0
  36. package/apps/control-plane/test/worker-provider-factory.spec.ts +151 -0
  37. package/config/agentic/orchestrator/agents.yaml +3 -0
  38. package/dist/apps/control-plane/cli/cli-argument-parser.js +7 -0
  39. package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
  40. package/dist/apps/control-plane/cli/help-command-handler.js +8 -0
  41. package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
  42. package/dist/apps/control-plane/cli/init-command-handler.js +6 -0
  43. package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
  44. package/dist/apps/control-plane/cli/resume-command-handler.d.ts +3 -0
  45. package/dist/apps/control-plane/cli/resume-command-handler.js +18 -2
  46. package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
  47. package/dist/apps/control-plane/cli/run-command-handler.d.ts +3 -1
  48. package/dist/apps/control-plane/cli/run-command-handler.js +17 -3
  49. package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
  50. package/dist/apps/control-plane/cli/types.d.ts +1 -0
  51. package/dist/apps/control-plane/core/error-codes.d.ts +4 -0
  52. package/dist/apps/control-plane/core/error-codes.js +4 -0
  53. package/dist/apps/control-plane/core/error-codes.js.map +1 -1
  54. package/dist/apps/control-plane/core/kernel.d.ts +3 -0
  55. package/dist/apps/control-plane/core/kernel.js.map +1 -1
  56. package/dist/apps/control-plane/index.d.ts +2 -0
  57. package/dist/apps/control-plane/index.js +1 -0
  58. package/dist/apps/control-plane/index.js.map +1 -1
  59. package/dist/apps/control-plane/interfaces/cli/bootstrap.js +14 -2
  60. package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
  61. package/dist/apps/control-plane/providers/api-worker-provider.d.ts +31 -0
  62. package/dist/apps/control-plane/providers/api-worker-provider.js +73 -0
  63. package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -0
  64. package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +46 -0
  65. package/dist/apps/control-plane/providers/cli-worker-provider.js +274 -0
  66. package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -0
  67. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.d.ts +10 -0
  68. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js +79 -0
  69. package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js.map +1 -0
  70. package/dist/apps/control-plane/providers/output-parsers/index.d.ts +2 -0
  71. package/dist/apps/control-plane/providers/output-parsers/index.js +2 -0
  72. package/dist/apps/control-plane/providers/output-parsers/index.js.map +1 -0
  73. package/dist/apps/control-plane/providers/output-parsers/types.d.ts +21 -0
  74. package/dist/apps/control-plane/providers/output-parsers/types.js +2 -0
  75. package/dist/apps/control-plane/providers/output-parsers/types.js.map +1 -0
  76. package/dist/apps/control-plane/providers/providers.d.ts +4 -0
  77. package/dist/apps/control-plane/providers/providers.js +15 -0
  78. package/dist/apps/control-plane/providers/providers.js.map +1 -1
  79. package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +41 -0
  80. package/dist/apps/control-plane/providers/worker-provider-factory.js +104 -0
  81. package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -0
  82. package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +13 -0
  83. package/dist/apps/control-plane/supervisor/build-wave-executor.js +92 -3
  84. package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
  85. package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +12 -0
  86. package/dist/apps/control-plane/supervisor/planning-wave-executor.js +83 -5
  87. package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
  88. package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +13 -0
  89. package/dist/apps/control-plane/supervisor/qa-wave-executor.js +91 -2
  90. package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
  91. package/dist/apps/control-plane/supervisor/runtime.js +19 -0
  92. package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
  93. package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +10 -0
  94. package/dist/apps/control-plane/supervisor/worker-decision-loop.js +113 -12
  95. package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
  96. package/package.json +2 -2
  97. package/packages/web-dashboard/next-env.d.ts +2 -1
  98. package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +4 -3
  99. package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +6 -2
  100. package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +6 -5
  101. package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +5 -4
  102. package/packages/web-dashboard/src/app/api/features/[id]/route.ts +7 -3
  103. package/packages/web-dashboard/src/lib/aop-client.ts +2 -2
  104. package/packages/web-dashboard/src/lib/orchestrator-tools.ts +1 -1
  105. package/packages/web-dashboard/tsconfig.json +1 -0
  106. package/spec-files/outstanding/agentic_orchestrator_human_input_interaction_protocol_spec.md +590 -0
  107. package/spec-files/outstanding/agentic_orchestrator_real_worker_provider_execution_spec.md +616 -0
  108. package/spec-files/progress.md +91 -0
@@ -0,0 +1,590 @@
1
+ # Feature Spec: Human Input Interaction Protocol for Agent Cluster (AOP)
2
+
3
+ > **Purpose of this document**: Define a first-class, deterministic protocol for cases where planner/builder/qa must pause and request human input (clarifications, approvals, permission overrides) before safe continuation.
4
+
5
+ **Version:** 1.1
6
+ **Date:** 2026-03-04
7
+ **Status:** Draft
8
+ **Roadmap Mapping:** M43
9
+
10
+ ---
11
+
12
+ ## 0. Standards and Dependencies
13
+
14
+ ### 0.1 Required Standards
15
+
16
+ All implementation MUST preserve:
17
+
18
+ - deterministic orchestration behavior and state transitions
19
+ - MCP/in-process tool contract parity
20
+ - strict schema validation (`validate:mcp-contracts`, `validate:architecture`)
21
+ - canonical runtime artifacts under `.aop/**`
22
+ - global topology invariants (`1 + 3N` active sessions)
23
+ - idempotent behavior for mutating tool calls (`operation_id` required)
24
+
25
+ ### 0.2 Required Inputs
26
+
27
+ Implementing agents MUST read:
28
+
29
+ - `apps/control-plane/src/supervisor/worker-decision-loop.ts`
30
+ - `apps/control-plane/src/supervisor/run-coordinator.ts`
31
+ - `apps/control-plane/src/supervisor/planning-wave-executor.ts`
32
+ - `apps/control-plane/src/supervisor/build-wave-executor.ts`
33
+ - `apps/control-plane/src/supervisor/qa-wave-executor.ts`
34
+ - `apps/control-plane/src/core/kernel.ts`
35
+ - `apps/control-plane/src/core/constants.ts`
36
+ - `apps/control-plane/src/cli/status-command-handler.ts`
37
+ - `apps/control-plane/src/cli/send-command-handler.ts`
38
+ - `apps/control-plane/src/application/services/activity-monitor-service.ts`
39
+ - `agentic/orchestrator/tools/catalog.json`
40
+ - `agentic/orchestrator/schemas/state.schema.json`
41
+ - `agentic/orchestrator/schemas/index.schema.json`
42
+ - `agentic/orchestrator/policy.yaml`
43
+ - `agentic/orchestrator/schemas/policy.schema.json`
44
+
45
+ ### 0.3 Scope
46
+
47
+ This spec implements:
48
+
49
+ - explicit question/answer protocol between agents and humans
50
+ - deterministic pause-and-resume behavior for features awaiting input
51
+ - new MCP tools and schema artifacts for question lifecycle
52
+ - CLI and dashboard-facing retrieval/answer workflows
53
+ - regression coverage for question-blocked execution and resume
54
+
55
+ Out of scope:
56
+
57
+ - external ticketing approval workflows (Jira/ServiceNow sync)
58
+ - cryptographic signature workflows for approvals
59
+ - model-vendor-specific conversational UX
60
+
61
+ ### 0.4 OOP and Architecture Guardrails (Mandatory)
62
+
63
+ Implementation for this spec MUST follow explicit object-oriented and architectural best practices:
64
+
65
+ - **KISS**: implement the smallest deterministic question/answer protocol that satisfies the contract.
66
+ - **SRP (Single Responsibility Principle)**: question persistence, state transitions, CLI handling, and status projection MUST remain in separate modules/services.
67
+ - **SOLID-oriented design** (applied pragmatically):
68
+ - open/closed for new question types or answer validators without changing unrelated orchestration flow
69
+ - interface segregation for question store/service/query ports
70
+ - dependency inversion so supervisor/CLI depend on contracts, not storage details
71
+ - **Hexagonal architecture alignment**: domain/application logic must not depend directly on transport adapters (CLI/MCP/dashboard).
72
+ - **Composition over inheritance**: compose question validators/parsers/services rather than building inheritance-heavy hierarchies.
73
+ - **High cohesion / low coupling**: keep WorkerDecisionLoop routing, Kernel state mutation, and artifact I/O separated.
74
+
75
+ Code organization requirements for this spec:
76
+
77
+ - question lifecycle domain logic lives in dedicated services (`create`, `answer`, `list`, `expire`)
78
+ - feature status transitions (`awaiting_input` <-> resumed phase) are owned by kernel/application services, not CLI handlers
79
+ - CLI and dashboard adapters are thin and invoke tool/service contracts only
80
+ - provider-specific worker payload formats are normalized before domain question handling
81
+
82
+ ---
83
+
84
+ ## 1. Current Gap and Defect Class
85
+
86
+ Current system behavior is missing a first-class handshake when agents need input:
87
+
88
+ 1. worker `REQUEST` handling has no `ask_user` action contract.
89
+ 2. `waiting_input` exists only as heuristic activity derivation from `status_reason` text.
90
+ 3. there is no durable question queue artifact.
91
+ 4. no structured answer tool exists (`feature.send_message` is unstructured best-effort delivery).
92
+ 5. run loop has no deterministic pause/resume contract for unresolved questions.
93
+
94
+ Result: operators must use ad hoc `send`/`attach` workflows, and orchestrator semantics are ambiguous when a role cannot proceed safely without human response.
95
+
96
+ ---
97
+
98
+ ## 2. Objectives
99
+
100
+ ### 2.1 Must-Have Outcomes
101
+
102
+ 1. Agents can raise a structured blocking question via tool contract.
103
+ 2. Feature enters deterministic `awaiting_input` state until answered (or expired/escalated).
104
+ 3. Human answers are persisted as first-class artifacts and fed back into role context.
105
+ 4. Orchestrator does not run planner/build/qa waves for features with open blocking questions.
106
+ 5. Answering a question deterministically resumes the correct phase.
107
+ 6. `aop status` can show pending-question state without heuristic parsing.
108
+
109
+ ### 2.2 Non-Goals
110
+
111
+ - replacing existing `aop send` and `aop attach` commands
112
+ - introducing a free-form chat broker between human and agents
113
+ - adding real-time websocket transport requirements to core runtime
114
+
115
+ ---
116
+
117
+ ## 3. Terminology and Invariants
118
+
119
+ ### 3.1 New Terms
120
+
121
+ - **Blocking Question**: a question that must be answered before wave execution can continue.
122
+ - **Question Record**: durable structured artifact for one question lifecycle.
123
+ - **Awaiting Input State**: explicit feature status indicating orchestrator pause pending answer.
124
+
125
+ ### 3.2 Invariants
126
+
127
+ 1. Exactly zero or one **active blocking question** per feature at a time.
128
+ 2. A feature in `awaiting_input` cannot execute planning/build/qa wave logic.
129
+ 3. Answers are append-only in question history (no destructive rewrites).
130
+ 4. Answer operations are idempotent by `operation_id`.
131
+ 5. Resume phase is deterministic from recorded pre-question status.
132
+
133
+ ---
134
+
135
+ ## 4. End-to-End Lifecycle (Normative)
136
+
137
+ ### 4.1 Ask Flow
138
+
139
+ 1. Worker emits:
140
+
141
+ ```json
142
+ {
143
+ "type": "REQUEST",
144
+ "request": {
145
+ "action": "ask_user_input",
146
+ "question_type": "permission_override",
147
+ "prompt": "Allow editing file outside planned file set: config/security/policy.yaml?",
148
+ "details": {
149
+ "requested_paths": ["config/security/policy.yaml"],
150
+ "reason": "Fix required by failing gate"
151
+ },
152
+ "expected_answer": {
153
+ "kind": "single_choice",
154
+ "choices": ["approve", "deny", "needs_more_context"]
155
+ },
156
+ "blocking": true
157
+ }
158
+ }
159
+ ```
160
+
161
+ 2. `WorkerDecisionLoop` routes this to `feature.question_create`.
162
+ 3. Kernel persists question record and transitions feature state to `awaiting_input`.
163
+ 4. Feature retains active session assignment but is skipped by phase executors.
164
+ 5. Operator sees pending question in `aop status` and `aop questions`.
165
+
166
+ ### 4.2 Answer Flow
167
+
168
+ 1. Human answers via `aop answer --feature-id <id> --question-id <qid> --answer <json-or-text>`.
169
+ 2. `feature.question_answer` persists answer and closes question.
170
+ 3. Kernel restores feature status to recorded `resume_status`.
171
+ 4. Next orchestration iteration resumes normal phase execution.
172
+ 5. Answer is included in `feature.get_context` under `human_input.latest_answer`.
173
+
174
+ ### 4.3 Timeout / Expiry Flow
175
+
176
+ 1. If no answer before timeout (`policy.execution.human_input_timeout_ms`), question becomes `expired`.
177
+ 2. Configured action applies (`block_feature` or `fail_feature`).
178
+ 3. Expiry is logged in decisions and question history.
179
+
180
+ ---
181
+
182
+ ## 5. Contract and Schema Deltas
183
+
184
+ ### 5.1 Feature Status Contract
185
+
186
+ Add new status constant and schema enum:
187
+
188
+ - `awaiting_input`
189
+
190
+ State semantics:
191
+
192
+ - terminal: no
193
+ - wave-executable: no
194
+ - eligible for resume: yes (after question resolution)
195
+
196
+ ### 5.2 State Frontmatter Additions (`state.schema.json`)
197
+
198
+ Add:
199
+
200
+ ```yaml
201
+ human_input:
202
+ open_question_id: string | null
203
+ open_question_count: integer
204
+ awaiting_since: date-time | null
205
+ requested_by_role: string | null
206
+ resume_status: string | null
207
+ ```
208
+
209
+ Rules:
210
+
211
+ - `open_question_id` must be null when status is not `awaiting_input`.
212
+ - `resume_status` must be one of `planning|building|qa|blocked|ready_to_merge` when awaiting input.
213
+
214
+ ### 5.3 Question Artifact Contract
215
+
216
+ Add per-feature artifact:
217
+
218
+ ```text
219
+ .aop/features/<feature_id>/questions.json
220
+ ```
221
+
222
+ Shape:
223
+
224
+ ```json
225
+ {
226
+ "version": 1,
227
+ "feature_id": "feature_x",
228
+ "items": [
229
+ {
230
+ "question_id": "q_01J...",
231
+ "status": "open",
232
+ "blocking": true,
233
+ "question_type": "permission_override",
234
+ "role": "builder",
235
+ "session_id": "builder-feature_x-...",
236
+ "prompt": "Allow editing ... ?",
237
+ "details": { "requested_paths": ["..."] },
238
+ "expected_answer": { "kind": "single_choice", "choices": ["approve", "deny"] },
239
+ "created_at": "2026-03-04T22:00:00.000Z",
240
+ "expires_at": "2026-03-04T22:15:00.000Z",
241
+ "answer": null,
242
+ "answered_at": null,
243
+ "answered_by": null,
244
+ "resume_status": "building"
245
+ }
246
+ ]
247
+ }
248
+ ```
249
+
250
+ ### 5.4 Tool Catalog Additions
251
+
252
+ Add new MCP tools:
253
+
254
+ 1. `feature.question_create` (mutating)
255
+ 2. `feature.question_list` (read)
256
+ 3. `feature.question_answer` (mutating)
257
+
258
+ #### `feature.question_create` input
259
+
260
+ - `feature_id` (string)
261
+ - `role` (`planner|builder|qa|orchestrator`)
262
+ - `session_id` (string)
263
+ - `question_type` (`clarification|permission_override|external_decision|risk_ack`)
264
+ - `prompt` (string, min length 1)
265
+ - `details` (object, optional)
266
+ - `expected_answer` (object with `kind`, optional choices/schema)
267
+ - `blocking` (boolean, default true)
268
+ - `operation_id` (string, required)
269
+
270
+ Output:
271
+
272
+ - `question_id`
273
+ - `status`
274
+ - `feature_status`
275
+ - `resume_status`
276
+
277
+ #### `feature.question_list` input
278
+
279
+ - `feature_id` (string)
280
+ - `status` (`open|answered|expired|withdrawn|all`, default `open`)
281
+
282
+ Output:
283
+
284
+ - array of matching question records (stable sorted by `created_at` ascending)
285
+
286
+ #### `feature.question_answer` input
287
+
288
+ - `feature_id` (string)
289
+ - `question_id` (string)
290
+ - `answer` (string or object)
291
+ - `answered_by` (string; `human` or operator identity)
292
+ - `operation_id` (string, required)
293
+
294
+ Output:
295
+
296
+ - `question_id`
297
+ - `question_status` (`answered`)
298
+ - `feature_status` (resumed phase)
299
+ - `resumed` (boolean)
300
+
301
+ ### 5.5 Error Taxonomy Additions
302
+
303
+ Add:
304
+
305
+ - `question_not_found`
306
+ - `question_already_answered`
307
+ - `question_invalid_answer`
308
+ - `question_conflict_open`
309
+ - `question_answer_not_allowed_in_terminal_state`
310
+
311
+ ---
312
+
313
+ ## 6. Runtime Behavior Changes
314
+
315
+ ### 6.1 WorkerDecisionLoop
316
+
317
+ Add handling for `REQUEST.action=ask_user_input`:
318
+
319
+ - call `feature.question_create`
320
+ - mark request handled
321
+ - append note to feature log with question id
322
+
323
+ Unknown `REQUEST.action` remains no-op but MUST log a warning note for observability.
324
+
325
+ ### 6.2 RunCoordinator and Wave Executors
326
+
327
+ When feature status is `awaiting_input`:
328
+
329
+ - planning/build/qa executors must skip worker execution and gates
330
+ - no automatic transition to `blocked` or `failed` unless timeout policy triggers
331
+ - feature remains in the current runtime scope (session cluster intact)
332
+
333
+ ### 6.3 Context Enrichment
334
+
335
+ `feature.get_context` adds:
336
+
337
+ ```yaml
338
+ human_input:
339
+ open_questions: [...]
340
+ latest_answer: {...} | null
341
+ ```
342
+
343
+ Rules:
344
+
345
+ - planner/builder/qa receive at most last `N` answered questions (`N` configurable, default 3)
346
+ - open questions included only for same feature
347
+
348
+ ### 6.4 Activity State Determinism
349
+
350
+ Stop relying on heuristic `status_reason` parsing for waiting-input detection:
351
+
352
+ - if state status is `awaiting_input`, `activity_state` reports `waiting_input`
353
+ - heuristic fallback remains only for backward compatibility during migration window
354
+
355
+ ---
356
+
357
+ ## 7. CLI and Dashboard Surface
358
+
359
+ ### 7.1 New CLI Commands
360
+
361
+ Add:
362
+
363
+ 1. `aop questions --feature-id <id> [--status open|answered|expired|withdrawn|all]`
364
+ 2. `aop answer --feature-id <id> --question-id <qid> --answer <value> [--answered-by <id>]`
365
+
366
+ Behavior:
367
+
368
+ - both commands return structured JSON envelopes
369
+ - answer command validates feature/question state and idempotency
370
+
371
+ ### 7.2 Status Output Enhancements
372
+
373
+ `aop status` and dashboard payload include:
374
+
375
+ - `open_question_count`
376
+ - `open_question_id`
377
+ - `awaiting_since`
378
+ - `resume_status`
379
+
380
+ ---
381
+
382
+ ## 8. Planner / Builder / QA Role Semantics
383
+
384
+ ### 8.1 Planner
385
+
386
+ Planner may ask blocking clarification questions when spec ambiguities prevent safe plan updates.
387
+
388
+ ### 8.2 Builder
389
+
390
+ Builder may ask blocking permission questions for out-of-plan or protected path changes.
391
+
392
+ ### 8.3 QA
393
+
394
+ QA may ask blocking risk-acknowledgement questions when gate failures imply high-risk tradeoffs.
395
+
396
+ ### 8.4 Orchestrator
397
+
398
+ Orchestrator does not synthesize answers. It only records question lifecycle and enforces state transitions.
399
+
400
+ ---
401
+
402
+ ## 9. Policy Contract
403
+
404
+ Add under `policy.execution`:
405
+
406
+ ```yaml
407
+ human_input:
408
+ enabled: true
409
+ timeout_ms: 900000
410
+ on_timeout: block_feature # block_feature | fail_feature
411
+ max_open_questions_per_feature: 1
412
+ context_answer_history_limit: 3
413
+ ```
414
+
415
+ Rules:
416
+
417
+ - if `enabled=false`, `feature.question_create` returns `unsupported_operation`
418
+ - `max_open_questions_per_feature=1` is enforced strictly in v1
419
+
420
+ ---
421
+
422
+ ## 10. Edge-Case Matrix (Normative)
423
+
424
+ 1. Duplicate create requests with same `operation_id`:
425
+
426
+ - replay exact prior success envelope.
427
+
428
+ 2. New question when an open blocking question already exists:
429
+
430
+ - reject with `question_conflict_open`.
431
+
432
+ 3. Answer submitted for unknown question id:
433
+
434
+ - reject with `question_not_found`.
435
+
436
+ 4. Answer submitted for already answered question:
437
+
438
+ - return idempotent success if same operation replay, else `question_already_answered`.
439
+
440
+ 5. Feature reaches terminal status while question open:
441
+
442
+ - auto-close question as `withdrawn` and retain history.
443
+
444
+ 6. Resume status no longer valid at answer time:
445
+
446
+ - fallback resume to `planning` and log deterministic reason.
447
+
448
+ 7. Multi-project mode:
449
+
450
+ - question artifacts must resolve under selected project root only.
451
+
452
+ 8. Stale runtime takeover:
453
+
454
+ - open questions persist and remain answerable post-takeover.
455
+
456
+ 9. Manual `aop send` while awaiting input:
457
+
458
+ - allowed; does not auto-answer question.
459
+
460
+ 10. Missing session cluster while answering:
461
+
462
+ - answer still persists and feature resumes by state transition; session recreation handled by normal runtime recovery.
463
+
464
+ ---
465
+
466
+ ## 11. Implementation Plan
467
+
468
+ ### M43.1 Core Question Service
469
+
470
+ - add `QuestionService` for create/list/answer lifecycle
471
+ - persist `.aop/features/<id>/questions.json`
472
+ - enforce open-question invariant and idempotency behavior
473
+
474
+ ### M43.2 Tooling and Schema Integration
475
+
476
+ - add tool constants and kernel routing
477
+ - add catalog entries and input/output schemas
478
+ - add policy/state schema fields
479
+
480
+ ### M43.3 Runtime Integration
481
+
482
+ - wire `ask_user_input` request handling in `WorkerDecisionLoop`
483
+ - skip awaiting-input features in wave executors
484
+ - enrich `feature.get_context` with human input data
485
+
486
+ ### M43.4 CLI and Reporting
487
+
488
+ - add `questions` and `answer` commands to parser/bootstrap/help
489
+ - extend status/dashboard payload with question summary fields
490
+
491
+ ### M43.5 Verify Path Coverage
492
+
493
+ - add unit/integration tests and include in `npm run verify` path
494
+
495
+ ---
496
+
497
+ ## 12. File-Level Change Targets
498
+
499
+ - `apps/control-plane/src/application/services/question-service.ts` (new)
500
+ - `apps/control-plane/src/core/constants.ts`
501
+ - `apps/control-plane/src/core/kernel.ts`
502
+ - `apps/control-plane/src/supervisor/worker-decision-loop.ts`
503
+ - `apps/control-plane/src/supervisor/planning-wave-executor.ts`
504
+ - `apps/control-plane/src/supervisor/build-wave-executor.ts`
505
+ - `apps/control-plane/src/supervisor/qa-wave-executor.ts`
506
+ - `apps/control-plane/src/cli/types.ts`
507
+ - `apps/control-plane/src/cli/cli-argument-parser.ts`
508
+ - `apps/control-plane/src/cli/help-command-handler.ts`
509
+ - `apps/control-plane/src/cli/questions-command-handler.ts` (new)
510
+ - `apps/control-plane/src/cli/answer-command-handler.ts` (new)
511
+ - `apps/control-plane/src/interfaces/cli/bootstrap.ts`
512
+ - `apps/control-plane/src/cli/status-command-handler.ts`
513
+ - `apps/control-plane/src/application/services/activity-monitor-service.ts`
514
+ - `agentic/orchestrator/tools/catalog.json`
515
+ - `agentic/orchestrator/tools/schemas/input/feature.question_create.input.schema.json` (new)
516
+ - `agentic/orchestrator/tools/schemas/output/feature.question_create.output.schema.json` (new)
517
+ - `agentic/orchestrator/tools/schemas/input/feature.question_list.input.schema.json` (new)
518
+ - `agentic/orchestrator/tools/schemas/output/feature.question_list.output.schema.json` (new)
519
+ - `agentic/orchestrator/tools/schemas/input/feature.question_answer.input.schema.json` (new)
520
+ - `agentic/orchestrator/tools/schemas/output/feature.question_answer.output.schema.json` (new)
521
+ - `agentic/orchestrator/schemas/state.schema.json`
522
+ - `agentic/orchestrator/schemas/policy.schema.json`
523
+ - `agentic/orchestrator/policy.yaml`
524
+ - `README.md`
525
+ - `apps/control-plane/test/question-service.spec.ts` (new)
526
+ - `apps/control-plane/test/worker-decision-loop.spec.ts`
527
+ - `apps/control-plane/test/run-coordinator.spec.ts`
528
+ - `apps/control-plane/test/cli.unit.spec.ts`
529
+ - `apps/control-plane/test/status-command.spec.ts`
530
+ - `apps/control-plane/test/mcp.spec.ts`
531
+
532
+ ---
533
+
534
+ ## 13. Test Plan (Must Be in `npm run verify` Path)
535
+
536
+ ### 13.1 Unit
537
+
538
+ - question create transitions state to `awaiting_input`
539
+ - answer transitions to recorded `resume_status`
540
+ - duplicate open question is rejected
541
+ - answer idempotency and replay behavior
542
+
543
+ ### 13.2 Supervisor Integration
544
+
545
+ - feature in `awaiting_input` is skipped by all wave executors
546
+ - answering question resumes the next iteration in deterministic phase
547
+
548
+ ### 13.3 CLI Integration
549
+
550
+ - `aop questions` returns open questions sorted deterministically
551
+ - `aop answer` closes question and reports resumed status
552
+
553
+ ### 13.4 MCP Contract
554
+
555
+ - all new tools validate schema and role authorization
556
+ - mutating tools enforce `operation_id`
557
+
558
+ ### 13.5 Regression
559
+
560
+ - GIVEN builder asks permission override WHEN unanswered THEN no further patch/gate actions execute for that feature
561
+ - GIVEN answer is provided WHEN next iteration runs THEN builder resumes and can continue gate repair
562
+
563
+ ---
564
+
565
+ ## 14. Acceptance Criteria
566
+
567
+ 1. Agent-generated blocking questions become first-class persisted artifacts.
568
+ 2. Feature status transitions to `awaiting_input` deterministically.
569
+ 3. No planning/building/qa waves execute for features with open blocking question.
570
+ 4. Human answer flow is deterministic, idempotent, and auditable.
571
+ 5. Feature resumes from recorded phase after answer.
572
+ 6. `aop status`, `aop questions`, and `aop answer` provide complete operator workflow.
573
+ 7. `npm run verify` fails if awaiting-input pause/resume invariants regress.
574
+ 8. Implementation boundaries follow KISS/SRP/SOLID/Hexagonal requirements from Section 0.4.
575
+
576
+ ---
577
+
578
+ ## 15. Risks and Mitigations
579
+
580
+ - Risk: status-model expansion (`awaiting_input`) causes unintended branch regressions.
581
+ - Mitigation: add explicit status transition tests in all wave executors and coordinator.
582
+
583
+ - Risk: unanswered questions stall active slots indefinitely.
584
+ - Mitigation: policy timeout with deterministic expiry action and status reporting.
585
+
586
+ - Risk: users bypass structured answers with ad hoc `send`.
587
+ - Mitigation: keep `send` but require `question_answer` to clear blocking state.
588
+
589
+ - Risk: tool-surface growth increases contract maintenance load.
590
+ - Mitigation: strict MCP schema/metadata validation and parity tests.