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.
- package/AGENTS.md +139 -0
- package/CLAUDE.md +12 -0
- package/agentic/orchestrator/agents.yaml +3 -0
- package/agentic/orchestrator/defaults/policy.defaults.yaml +3 -0
- package/agentic/orchestrator/policy.yaml +3 -0
- package/agentic/orchestrator/schemas/agents.schema.json +15 -0
- package/agentic/orchestrator/schemas/policy.schema.json +14 -0
- package/apps/control-plane/src/cli/cli-argument-parser.ts +7 -0
- package/apps/control-plane/src/cli/help-command-handler.ts +8 -0
- package/apps/control-plane/src/cli/init-command-handler.ts +6 -0
- package/apps/control-plane/src/cli/resume-command-handler.ts +31 -2
- package/apps/control-plane/src/cli/run-command-handler.ts +31 -3
- package/apps/control-plane/src/cli/types.ts +1 -0
- package/apps/control-plane/src/core/error-codes.ts +4 -0
- package/apps/control-plane/src/core/kernel.ts +3 -0
- package/apps/control-plane/src/index.ts +14 -0
- package/apps/control-plane/src/interfaces/cli/bootstrap.ts +25 -3
- package/apps/control-plane/src/providers/api-worker-provider.ts +115 -0
- package/apps/control-plane/src/providers/cli-worker-provider.ts +385 -0
- package/apps/control-plane/src/providers/output-parsers/generic-output-parser.ts +100 -0
- package/apps/control-plane/src/providers/output-parsers/index.ts +11 -0
- package/apps/control-plane/src/providers/output-parsers/types.ts +23 -0
- package/apps/control-plane/src/providers/providers.ts +19 -0
- package/apps/control-plane/src/providers/worker-provider-factory.ts +198 -0
- package/apps/control-plane/src/supervisor/build-wave-executor.ts +140 -3
- package/apps/control-plane/src/supervisor/planning-wave-executor.ts +125 -5
- package/apps/control-plane/src/supervisor/qa-wave-executor.ts +144 -2
- package/apps/control-plane/src/supervisor/runtime.ts +24 -0
- package/apps/control-plane/src/supervisor/worker-decision-loop.ts +134 -12
- package/apps/control-plane/test/cli.unit.spec.ts +36 -0
- package/apps/control-plane/test/dashboard-api.integration.spec.ts +2 -2
- package/apps/control-plane/test/resume-command.spec.ts +31 -1
- package/apps/control-plane/test/worker-decision-loop.spec.ts +3 -0
- package/apps/control-plane/test/worker-execution-policy.spec.ts +284 -0
- package/apps/control-plane/test/worker-provider-adapters.spec.ts +440 -0
- package/apps/control-plane/test/worker-provider-factory.spec.ts +151 -0
- package/config/agentic/orchestrator/agents.yaml +3 -0
- package/dist/apps/control-plane/cli/cli-argument-parser.js +7 -0
- package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
- package/dist/apps/control-plane/cli/help-command-handler.js +8 -0
- package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/init-command-handler.js +6 -0
- package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/resume-command-handler.d.ts +3 -0
- package/dist/apps/control-plane/cli/resume-command-handler.js +18 -2
- package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/run-command-handler.d.ts +3 -1
- package/dist/apps/control-plane/cli/run-command-handler.js +17 -3
- package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/types.d.ts +1 -0
- package/dist/apps/control-plane/core/error-codes.d.ts +4 -0
- package/dist/apps/control-plane/core/error-codes.js +4 -0
- package/dist/apps/control-plane/core/error-codes.js.map +1 -1
- package/dist/apps/control-plane/core/kernel.d.ts +3 -0
- package/dist/apps/control-plane/core/kernel.js.map +1 -1
- package/dist/apps/control-plane/index.d.ts +2 -0
- package/dist/apps/control-plane/index.js +1 -0
- package/dist/apps/control-plane/index.js.map +1 -1
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js +14 -2
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
- package/dist/apps/control-plane/providers/api-worker-provider.d.ts +31 -0
- package/dist/apps/control-plane/providers/api-worker-provider.js +73 -0
- package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -0
- package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +46 -0
- package/dist/apps/control-plane/providers/cli-worker-provider.js +274 -0
- package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -0
- package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.d.ts +10 -0
- package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js +79 -0
- package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js.map +1 -0
- package/dist/apps/control-plane/providers/output-parsers/index.d.ts +2 -0
- package/dist/apps/control-plane/providers/output-parsers/index.js +2 -0
- package/dist/apps/control-plane/providers/output-parsers/index.js.map +1 -0
- package/dist/apps/control-plane/providers/output-parsers/types.d.ts +21 -0
- package/dist/apps/control-plane/providers/output-parsers/types.js +2 -0
- package/dist/apps/control-plane/providers/output-parsers/types.js.map +1 -0
- package/dist/apps/control-plane/providers/providers.d.ts +4 -0
- package/dist/apps/control-plane/providers/providers.js +15 -0
- package/dist/apps/control-plane/providers/providers.js.map +1 -1
- package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +41 -0
- package/dist/apps/control-plane/providers/worker-provider-factory.js +104 -0
- package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -0
- package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +13 -0
- package/dist/apps/control-plane/supervisor/build-wave-executor.js +92 -3
- package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +12 -0
- package/dist/apps/control-plane/supervisor/planning-wave-executor.js +83 -5
- package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +13 -0
- package/dist/apps/control-plane/supervisor/qa-wave-executor.js +91 -2
- package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/runtime.js +19 -0
- package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
- package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +10 -0
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js +113 -12
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
- package/package.json +2 -2
- package/packages/web-dashboard/next-env.d.ts +2 -1
- package/packages/web-dashboard/src/app/api/features/[id]/checkout/route.ts +4 -3
- package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +6 -2
- package/packages/web-dashboard/src/app/api/features/[id]/evidence/[artifact]/route.ts +6 -5
- package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +5 -4
- package/packages/web-dashboard/src/app/api/features/[id]/route.ts +7 -3
- package/packages/web-dashboard/src/lib/aop-client.ts +2 -2
- package/packages/web-dashboard/src/lib/orchestrator-tools.ts +1 -1
- package/packages/web-dashboard/tsconfig.json +1 -0
- package/spec-files/outstanding/agentic_orchestrator_human_input_interaction_protocol_spec.md +590 -0
- package/spec-files/outstanding/agentic_orchestrator_real_worker_provider_execution_spec.md +616 -0
- 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.
|