@orchestrator-claude/cli 3.11.0 → 3.12.1

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 (35) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/templates/base/CLAUDE.md.hbs +35 -332
  4. package/dist/templates/base/claude/hooks/dangling-workflow-guard.sh +33 -41
  5. package/dist/templates/base/claude/hooks/gate-guardian.sh +42 -43
  6. package/dist/templates/base/claude/hooks/orch-helpers.sh +25 -20
  7. package/dist/templates/base/claude/hooks/ping-pong-enforcer.sh +26 -40
  8. package/dist/templates/base/claude/hooks/post-phase-checkpoint.sh +135 -254
  9. package/dist/templates/base/claude/hooks/prompt-orchestrator.sh +41 -0
  10. package/dist/templates/base/claude/hooks/session-orchestrator.sh +54 -0
  11. package/dist/templates/base/claude/hooks/workflow-guard.sh +53 -0
  12. package/dist/templates/base/claude/settings.json +37 -0
  13. package/dist/templates/base/claude/skills/workflow-status/SKILL.md +59 -291
  14. package/dist/templates/base/docker-compose.yml.hbs +2 -1
  15. package/package.json +1 -1
  16. package/templates/base/CLAUDE.md.hbs +35 -332
  17. package/templates/base/claude/hooks/dangling-workflow-guard.sh +33 -41
  18. package/templates/base/claude/hooks/gate-guardian.sh +42 -43
  19. package/templates/base/claude/hooks/orch-helpers.sh +25 -20
  20. package/templates/base/claude/hooks/ping-pong-enforcer.sh +26 -40
  21. package/templates/base/claude/hooks/post-phase-checkpoint.sh +135 -254
  22. package/templates/base/claude/hooks/prompt-orchestrator.sh +41 -0
  23. package/templates/base/claude/hooks/session-orchestrator.sh +54 -0
  24. package/templates/base/claude/hooks/workflow-guard.sh +53 -0
  25. package/templates/base/claude/settings.json +37 -0
  26. package/templates/base/claude/skills/workflow-status/SKILL.md +59 -291
  27. package/templates/base/docker-compose.yml.hbs +2 -1
  28. package/dist/templates/base/claude/hooks/post-artifact-generate.sh +0 -39
  29. package/dist/templates/base/claude/hooks/post-implement-validate.sh +0 -139
  30. package/dist/templates/base/claude/hooks/pre-agent-invoke.sh +0 -34
  31. package/dist/templates/base/claude/hooks/pre-phase-advance.sh +0 -40
  32. package/templates/base/claude/hooks/post-artifact-generate.sh +0 -39
  33. package/templates/base/claude/hooks/post-implement-validate.sh +0 -139
  34. package/templates/base/claude/hooks/pre-agent-invoke.sh +0 -34
  35. package/templates/base/claude/hooks/pre-phase-advance.sh +0 -40
@@ -2,330 +2,60 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- This project uses the **Orchestrator System** for autonomous workflow management. When handling feature requests, bug fixes, or refactoring tasks, you MUST use the orchestrator workflow instead of implementing directly.
5
+ This project uses the **Orchestrator System** for autonomous workflow management.
6
+ Orchestration is enforced by **deterministic hooks** — you do not need to memorize the workflow protocol.
6
7
 
7
- ## Critical Rule
8
+ ## Critical Rules
8
9
 
9
- **NEVER implement features directly.** Always use the orchestrator workflow:
10
-
11
- ```
12
- User Request → Detect Workflow → Research (if needed) → SPECIFY → PLAN → TASKS → Implement
13
- ```
10
+ 1. **NEVER implement features directly** always use the orchestrator workflow
11
+ 2. **NEVER edit `.orchestrator/orchestrator-index.json`** — state is in PostgreSQL
12
+ 3. **Access artifacts via MCP tools** (`artifactStore`, `artifactRetrieve`), not filesystem paths
14
13
 
15
14
  ## How to Start a Workflow
16
15
 
17
- When a user requests a new feature, bug fix, or refactoring:
18
-
19
- ### 1. Detect Workflow Type
20
-
21
- Use the MCP tool to detect the workflow type:
22
-
23
- ```
24
- mcp__orchestrator-tools__detectWorkflow({ prompt: "user request here" })
25
- ```
26
-
27
- Workflow types:
28
- - `feature_development` - New features, new functionality
29
- - `bug_fix` - Bug fixes, error corrections
30
- - `refactoring` - Code refactoring, improvements
31
- - `emergency_debug` - Urgent debugging
32
-
33
- ### 2. Start Workflow and Get Next Step
34
-
35
- **MANDATORY:** After detecting workflow type, call `startWorkflow` to create the workflow:
36
-
37
- ```
38
- mcp__orchestrator-tools__startWorkflow({ workflowType: "feature-development", prompt: "user request here" })
39
- ```
40
-
41
- This returns a deterministic `nextStep` instruction:
42
-
43
- ```json
44
- {
45
- "success": true,
46
- "workflowId": "wf-123",
47
- "nextStep": {
48
- "action": "invoke_agent",
49
- "subagent_type": "orchestrator",
50
- "prompt": "Start workflow feature-development (ID: wf-123) for user request: ..."
51
- }
52
- }
53
- ```
54
-
55
- ### 3. Execute nextStep (Invoke Orchestrator Agent)
56
-
57
- **IMMEDIATELY** follow the `nextStep` instruction by invoking the orchestrator agent via Task tool:
58
-
59
- ```
60
- Use the Task tool with subagent_type from nextStep.subagent_type
61
- Prompt: nextStep.prompt
62
- ```
63
-
64
- The orchestrator agent will:
65
- 1. Set pending actions for specialized agents
66
- 2. Return control to CLI for Ping-Pong pattern
67
- 3. CLI invokes agents via Task tool as directed by getNextAction()
68
- 4. Process continues until workflow completes
69
-
70
- ## Available MCP Tools
71
-
72
- ### orchestrator-tools
73
- - `detectWorkflow` - Detect workflow type from user prompt
74
- - `startWorkflow` - **Create workflow and get deterministic nextStep instruction** (MANDATORY after detectWorkflow)
75
- - `advancePhase` - Advance to the next workflow phase
76
- - `evaluateGate` - Evaluate if a phase gate passes
77
- - `validateArtifact` - Validate artifact against schema
78
- - `createCheckpoint` - Create a git checkpoint
79
- - `getStatus` - Get current workflow status
80
- - `getWorkflows` - List workflows with phase configs (including `requiresApproval`)
81
- - `getNextAction` - Get the next pending action (Ping-Pong pattern)
82
-
83
- ### knowledge-base
84
- - `search` - Search the knowledge base
85
- - `getDocument` - Get a specific document
86
- - `getConstitution` - Get the project constitution
87
- - `listByTier` - List documents by tier
88
- - `listByCategory` - List documents by category
89
-
90
- ## Auto-Advance Behavior (requiresApproval)
91
-
92
- **CRITICAL**: Each workflow phase has a `requiresApproval` configuration.
93
-
94
- ### How It Works
95
-
96
- 1. **Load workflow config** at start using `getWorkflows`:
97
- ```
98
- mcp__orchestrator-tools__getWorkflows()
99
- ```
100
-
101
- 2. **Check each phase's `requiresApproval`**:
102
- - `requiresApproval: false` → **AUTO-ADVANCE** after gate passes (no user interaction)
103
- - `requiresApproval: true` → **PAUSE** and ask user for approval
104
-
105
- ### Default Configuration (feature-development)
16
+ For any feature request, bug fix, or refactoring:
106
17
 
107
18
  ```
108
- SPECIFY → requiresApproval: false auto-advance
109
- PLAN → requiresApproval: false auto-advance
110
- TASKS → requiresApproval: false auto-advance
111
- IMPLEMENT → requiresApproval: true → PAUSE HERE
19
+ 1. mcp__orchestrator-tools__detectWorkflow({ prompt: "user request" })
20
+ 2. mcp__orchestrator-tools__startWorkflow({ workflowType: "...", prompt: "..." })
21
+ 3. Follow the nextStep returned — hooks handle the rest automatically
112
22
  ```
113
23
 
114
- ### Expected Behavior
115
-
116
- - **DO NOT ask user** between SPECIFY → PLAN → TASKS phases
117
- - **Run these phases sequentially** invoking each agent automatically
118
- - **ONLY pause** before IMPLEMENT phase (or phases with `requiresApproval: true`)
119
- - This reduces unnecessary interactions and speeds up the workflow
120
-
121
- ### Example Flow
122
-
123
- ```
124
- User: "Create a calculator function"
125
-
126
- Claude:
127
- 1. detectWorkflow({ prompt: "Create a calculator function" }) → feature-development
128
- 2. startWorkflow({ workflowType: "feature-development", prompt: "..." }) → { nextStep: {...} }
129
- 3. Execute nextStep → Invoke orchestrator agent via Task tool
130
- 4. getNextAction() → { agent: "specifier", status: "awaiting_agent" }
131
- 5. Invoke specifier via Task tool → spec.md created
132
- 6. getNextAction() → { agent: "planner", status: "awaiting_agent" }
133
- 7. Invoke planner via Task tool → plan.md created
134
- 8. getNextAction() → { agent: "task-generator", status: "awaiting_agent" }
135
- 9. Invoke task-generator via Task tool → tasks.md created
136
- 10. getNextAction() → { status: "awaiting_approval" }
137
- 11. Ask user: "Artifacts ready. Approve implementation?"
138
- ```
139
-
140
- ## Workflow Phases
141
-
142
- ```
143
- RESEARCH (optional)
144
-
145
- SPECIFY
146
-
147
- PLAN
148
-
149
- TASKS
150
-
151
- [HUMAN APPROVAL REQUIRED]
152
-
153
- IMPLEMENT
154
- ```
155
-
156
- Each phase produces artifacts stored in MinIO (object storage) and tracked in PostgreSQL:
157
- - `research` - Research context documents
158
- - `specify` - Specifications (spec.md)
159
- - `plan` - Technical plans (plan.md)
160
- - `tasks` - Task backlogs (tasks.md)
161
- - `implement` - Implementation reports
162
-
163
- **CRITICAL**: Artifacts are accessed via MCP tools (`artifactStore`, `artifactRetrieve`), NOT via filesystem paths. The `.orchestrator/artifacts/` directory does NOT exist on the filesystem.
164
-
165
- ---
24
+ Workflow types: `feature_development`, `bug_fix`, `refactoring`, `emergency_debug`
166
25
 
167
- ## Workflow Execution Pattern (Ping-Pong Híbrido)
26
+ ## What Hooks Enforce Automatically
168
27
 
169
- ### Critical Rule: Always Check for Pending Actions
28
+ | Hook | Trigger | What it does |
29
+ |------|---------|-------------|
30
+ | `ping-pong-enforcer` | After every Agent call | Calls `getNextAction` and injects result |
31
+ | `gate-guardian` | Before `advancePhase` | Evaluates gate, blocks if it fails |
32
+ | `dangling-workflow-guard` | On session Stop | Warns and completes dangling workflows |
33
+ | `workflow-guard` | Before Write/Edit on src/ | Blocks code writes without an active workflow |
170
34
 
171
- **MANDATORY:** After EVERY Task tool invocation that involves workflow orchestration, you MUST:
35
+ You do NOT need to manually call `getNextAction` after agents or `evaluateGate` before advancing — hooks do this deterministically.
172
36
 
173
- 1. **Call `mcp__orchestrator-tools__getNextAction()`**
174
- 2. **Analyze the response and take appropriate action**
37
+ ## Skills (On-Demand Context)
175
38
 
176
- ### Status Action Mapping
39
+ Use skills for phase-specific guidance:
177
40
 
178
- | Status | Your Action |
179
- |--------|-------------|
180
- | `awaiting_agent` | **Immediately** invoke the specified agent via Task tool |
181
- | `awaiting_approval` | **Ask user** for approval, then call `approveAction()` |
182
- | `running` | Agent is currently executing, do nothing |
183
- | No pending action | Workflow is complete or paused |
41
+ | Skill | When to use |
42
+ |-------|------------|
43
+ | `/workflow-status` | Check current workflow state |
44
+ | `/artifact-production` | Phase-specific artifact formats |
45
+ | `/tdd-discipline` | TDD protocol during IMPLEMENT |
46
+ | `/project-conventions` | Project patterns and gotchas |
47
+ | `/checkpoint-protocol` | When to create checkpoints |
48
+ | `/kb-lookup` | Search project knowledge base |
184
49
 
185
- ### Workflow Execution Loop
50
+ ## Creating Custom Definitions
186
51
 
187
- ```typescript
188
- // MANDATORY PATTERN for workflow execution
52
+ When creating agents, skills, or hooks, write to BOTH filesystem and PostgreSQL:
189
53
 
190
- // 1. Detect workflow type
191
- const detection = await detectWorkflow({ prompt: "Create authentication API" });
54
+ - **Agent**: Write `.claude/agents/{slug}.md` + `createAgentDefinition` MCP tool
55
+ - **Skill**: Write `.claude/skills/{slug}/SKILL.md` + `createSkillDefinition` MCP tool
56
+ - **Hook**: Write `.claude/hooks/{slug}.sh` + `createHook` MCP tool
192
57
 
193
- // 2. Start workflow and get nextStep (DETERMINISTIC)
194
- const startResult = await startWorkflow({
195
- workflowType: detection.workflowType,
196
- prompt: "Create authentication API"
197
- });
198
-
199
- // 3. Execute nextStep - invoke orchestrator agent
200
- await invokeTool("Task", {
201
- subagent_type: startResult.nextStep.subagent_type, // "orchestrator"
202
- prompt: startResult.nextStep.prompt
203
- });
204
-
205
- // 4. Check for pending actions (Ping-Pong loop)
206
- const action = await getNextAction();
207
-
208
- // 5. Handle the action
209
- if (action.hasAction && action.pendingAction.status === "awaiting_agent") {
210
- // Immediately invoke the specified agent
211
- await invokeTool("Task", {
212
- subagent_type: action.pendingAction.agent,
213
- prompt: action.pendingAction.prompt
214
- });
215
-
216
- // 6. REPEAT: Check for next action after agent completes
217
- const nextAction = await getNextAction();
218
- // ... continue loop
219
- }
220
-
221
- if (action.hasAction && action.pendingAction.status === "awaiting_approval") {
222
- // Inform user and wait for approval
223
- console.log("⚠️ Workflow requires approval before continuing to IMPLEMENT phase.");
224
- console.log("Review artifacts and type 'yes' to proceed.");
225
-
226
- // After user approves:
227
- await approveAction({ workflowId: action.workflowId });
228
-
229
- // Then check for next action again
230
- const nextAction = await getNextAction();
231
- // ...
232
- }
233
- ```
234
-
235
- ### What NOT to Do
236
-
237
- - ❌ **NEVER** skip `startWorkflow` after `detectWorkflow` - it creates the workflow and returns deterministic `nextStep`
238
- - ❌ **NEVER** ignore `nextStep` from `startWorkflow` - it tells you exactly which agent to invoke
239
- - ❌ **NEVER** ignore `getNextAction()` after Task tool invocation
240
- - ❌ **NEVER** decide which agent to invoke without checking `pendingAction`
241
- - ❌ **NEVER** skip to IMPLEMENT phase without user approval
242
- - ❌ **NEVER** execute multiple phases in a single agent invocation
243
- - ❌ **NEVER** use Write/Edit tools to create artifacts during orchestration (let specialized agents do it)
244
- - ❌ **NEVER** invoke agents out of order defined by `pendingAction`
245
-
246
- ### Why This Pattern?
247
-
248
- **Problem (LIM-001):** Context window bloat when orchestrator executes all phases internally in one invocation.
249
-
250
- **Solution (Ping-Pong Híbrido):** Orchestrator acts as **dispatcher**, creating `pendingActions` that guide the CLI to invoke specialized agents in separate, isolated invocations.
251
-
252
- **Benefits:**
253
- - Each agent invocation has isolated context (< 12k tokens)
254
- - Total token usage reduced by 40%+
255
- - No hallucination from massive context
256
- - Real agent metrics (not simulated)
257
- - Workflow resumable after crashes (pendingAction persists)
258
-
259
- ---
260
-
261
- ## MANDATORY: IMPLEMENT Phase Delegation
262
-
263
- > **WARNING**
264
- >
265
- > The IMPLEMENT phase REQUIRES delegation to the implementer subagent.
266
- > Direct implementation is FORBIDDEN and will break workflow governance.
267
-
268
- ### Trigger Phrases
269
-
270
- When user approves implementation with ANY of these phrases:
271
-
272
- **English:**
273
- - "yes", "yes, implement", "proceed", "go ahead", "continue"
274
- - "start implementation", "implement it", "do it"
275
-
276
- **Portuguese:**
277
- - "sim", "prossiga", "continue", "pode implementar"
278
- - "manda ver", "vai la", "implementa"
279
-
280
- ### Required Actions (IN ORDER)
281
-
282
- 1. **ANNOUNCE DELEGATION:**
283
- ```
284
- I will now delegate to the implementer agent to execute the tasks.
285
- ```
286
-
287
- 2. **ADVANCE PHASE:**
288
- ```
289
- mcp__orchestrator-tools__advancePhase({ workflowId: "current-workflow-id" })
290
- ```
291
-
292
- 3. **INVOKE IMPLEMENTER (REQUIRED):**
293
- ```
294
- Use the Task tool with subagent_type="implementer"
295
-
296
- Prompt:
297
- Execute all tasks from .orchestrator/artifacts/tasks/tasks.md
298
-
299
- Context:
300
- - Specification: .orchestrator/artifacts/specify/spec.md
301
- - Plan: .orchestrator/artifacts/plan/plan.md
302
- - Tasks: .orchestrator/artifacts/tasks/tasks.md
303
-
304
- Requirements:
305
- - Follow TDD (write tests BEFORE implementation)
306
- - Maintain {{coverageThreshold}}% minimum coverage
307
- - Create checkpoint after every 3-5 tasks
308
- - Generate implementation-report.md at the end
309
- ```
310
-
311
- ### FORBIDDEN Actions
312
-
313
- - Using Edit/Write tools directly for code implementation
314
- - Skipping Task tool invocation
315
- - Writing production code without implementer agent
316
- - Editing `.orchestrator/orchestrator-index.json` directly (state is in PostgreSQL)
317
-
318
- ### Self-Verification Checklist
319
-
320
- Before proceeding, verify:
321
- - [ ] Did I announce delegation to the user?
322
- - [ ] Did I call advancePhase via MCP?
323
- - [ ] Did I use Task tool with subagent_type="implementer"?
324
- - [ ] Is the implementer prompt complete with all context?
325
-
326
- If ANY answer is NO -> STOP and correct before continuing.
327
-
328
- ---
58
+ Built-in definitions are seeded on `orchestrator init` (idempotent).
329
59
 
330
60
  ## Quality Rules
331
61
 
@@ -335,33 +65,6 @@ If ANY answer is NO -> STOP and correct before continuing.
335
65
  - **Clean Architecture**: Dependencies point inward
336
66
  - **TypeScript Strict**: `strict: true` required
337
67
 
338
- ## State Management
339
-
340
- ```
341
- PostgreSQL (Single Source of Truth):
342
- ├── workflows # Workflow state, pending actions, phases
343
- ├── artifacts # Artifact metadata
344
- ├── checkpoints # Checkpoint metadata
345
- └── agent_invocations # Agent invocation history
346
-
347
- MinIO (Object Storage):
348
- └── artifacts/ # Generated artifact content by phase
349
-
350
- .orchestrator/ (DEPRECATED - do NOT read or write directly):
351
- └── orchestrator-index.json # DEPRECATED: state is in PostgreSQL
352
- ```
353
-
354
- **CRITICAL**: All workflow state is in PostgreSQL. All artifact content is in MinIO. Access everything through MCP tools. NEVER edit `.orchestrator/orchestrator-index.json` directly.
355
-
356
- ## Important Notes
357
-
358
- 1. **Always start with workflow detection** - Don't skip this step
359
- 2. **Let agents do their work** - Don't bypass the workflow
360
- 3. **Validate artifacts** - Use the artifact-validator skill
361
- 4. **Check gates** - Use phase-gate-evaluator before advancing
362
- 5. **Create checkpoints** - After each validated artifact
363
- 6. **Consult CONSTITUTION** - For project rules and constraints
364
-
365
68
  ---
366
69
 
367
70
  *This project was initialized with the Orchestrator CLI.*
@@ -1,65 +1,57 @@
1
1
  #!/bin/bash
2
- # dangling-workflow-guard.sh — ADR-013 Core Hook
3
- # Trigger: Stop (session end)
4
- # Purpose: Before the conversation ends, check for workflows still
5
- # in "in_progress" state. Warn the user and attempt to
6
- # complete the workflow automatically.
2
+ # dangling-workflow-guard.sh — ADR-013 Phase 5 Hook (JSON Structured Output)
3
+ # Trigger: Stop
4
+ # Purpose: Before conversation ends, check for workflows in in_progress state.
5
+ # Blocks stop and instructs LLM to call completeWorkflow.
7
6
  #
8
- # Exit 0 always (non-blocking we don't want to prevent session exit).
7
+ # Output: JSON with decision: "block" + reason (forces LLM to continue)
8
+ # Exit 0 with block JSON = prevent stop
9
+ # Check stop_hook_active to prevent infinite loops
9
10
 
10
11
  set -euo pipefail
11
12
 
12
13
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
14
  source "$SCRIPT_DIR/orch-helpers.sh"
14
15
 
16
+ STDIN_DATA=$(orch_read_stdin)
15
17
  orch_log "DANGLING-GUARD: Stop hook triggered"
16
18
 
19
+ # Prevent infinite loops
20
+ STOP_ACTIVE=$(orch_json_field "$STDIN_DATA" "stop_hook_active")
21
+ if [ "$STOP_ACTIVE" = "true" ]; then
22
+ orch_log "DANGLING-GUARD: stop_hook_active=true, allowing stop to prevent loop"
23
+ exit 0
24
+ fi
25
+
17
26
  # Find active workflow
18
- WORKFLOW_ID=$(orch_get_active_workflow 2>/dev/null) || {
27
+ WORKFLOW_ID=$(orch_get_active_workflow 2>/dev/null) || WORKFLOW_ID=""
28
+
29
+ if [ -z "$WORKFLOW_ID" ]; then
19
30
  orch_log "DANGLING-GUARD: No active workflow, clean exit"
20
31
  exit 0
21
- }
22
-
23
- orch_log "DANGLING-GUARD: Found active workflow=$WORKFLOW_ID"
32
+ fi
24
33
 
25
34
  # Get workflow status
26
- TOKEN=$(orch_get_token 2>/dev/null) || exit 0
35
+ TOKEN=$(orch_get_token 2>/dev/null) || TOKEN=""
36
+ if [ -z "$TOKEN" ]; then
37
+ orch_log "DANGLING-GUARD: Auth failed, allowing stop"
38
+ exit 0
39
+ fi
27
40
 
28
41
  STATUS_RESP=$(curl -sf --max-time 5 "${API_URL}/api/v1/workflows/${WORKFLOW_ID}/status" \
29
42
  -H "Authorization: Bearer $TOKEN" \
30
- -H "X-Project-ID: $PROJECT_ID" 2>/dev/null) || exit 0
31
-
32
- CURRENT_PHASE=$(orch_json_field "$STATUS_RESP" "currentPhase")
33
- WF_STATUS=$(orch_json_field "$STATUS_RESP" "status")
43
+ -H "X-Project-ID: $PROJECT_ID" 2>/dev/null) || STATUS_RESP=""
34
44
 
35
- orch_log "DANGLING-GUARD: status=$WF_STATUS phase=$CURRENT_PHASE"
45
+ PHASE=$(orch_json_field "$STATUS_RESP" "currentPhase")
46
+ STATUS=$(orch_json_field "$STATUS_RESP" "status")
36
47
 
37
- if [ "$WF_STATUS" = "in_progress" ] || [ "$WF_STATUS" = "running" ]; then
38
- echo ""
39
- echo "[DANGLING-GUARD] WARNING: Workflow $WORKFLOW_ID is still active (status: $WF_STATUS, phase: $CURRENT_PHASE)."
48
+ orch_log "DANGLING-GUARD: workflow=$WORKFLOW_ID status=$STATUS phase=$PHASE"
40
49
 
41
- # If in implement phase with no pending actions, auto-complete
42
- if [ "$CURRENT_PHASE" = "implement" ]; then
43
- NEXT_ACTION=$(orch_get_next_action "$WORKFLOW_ID" 2>/dev/null) || exit 0
44
- HAS_ACTION=$(orch_json_field "$NEXT_ACTION" "hasAction")
45
-
46
- if [ "$HAS_ACTION" != "true" ]; then
47
- echo "[DANGLING-GUARD] Auto-completing workflow (implement phase, no pending actions)..."
48
- curl -sf --max-time 10 -X POST "${API_URL}/api/v1/workflows/${WORKFLOW_ID}/complete" \
49
- -H "Content-Type: application/json" \
50
- -H "Authorization: Bearer $TOKEN" \
51
- -H "X-Project-ID: $PROJECT_ID" \
52
- -d "{}" >> "$DEBUG_LOG" 2>&1 || true
53
- echo "[DANGLING-GUARD] Workflow completed."
54
- orch_log "DANGLING-GUARD: Auto-completed workflow $WORKFLOW_ID"
55
- else
56
- echo "[DANGLING-GUARD] Workflow has pending actions — cannot auto-complete."
57
- echo "Resume this session to continue the workflow."
58
- fi
59
- else
60
- echo "[DANGLING-GUARD] Workflow is in '$CURRENT_PHASE' phase — not auto-completing."
61
- echo "Resume this session to continue the workflow."
62
- fi
50
+ if [ "$STATUS" = "in_progress" ] || [ "$STATUS" = "awaiting_agent" ] || [ "$STATUS" = "awaiting_approval" ]; then
51
+ orch_log "DANGLING-GUARD: BLOCK stop (workflow still active)"
52
+ echo "{\"decision\":\"block\",\"reason\":\"[DANGLING-GUARD] Workflow ${WORKFLOW_ID} is still ${STATUS} (phase: ${PHASE}). You must call mcp__orchestrator-extended__completeWorkflow({ workflowId: '${WORKFLOW_ID}' }) before ending the session.\"}"
53
+ exit 0
63
54
  fi
64
55
 
56
+ orch_log "DANGLING-GUARD: Workflow completed or not active, allowing stop"
65
57
  exit 0
@@ -1,80 +1,79 @@
1
1
  #!/bin/bash
2
- # gate-guardian.sh — ADR-013 Core Hook
2
+ # gate-guardian.sh — ADR-013 Phase 5 Hook (JSON Structured Output)
3
3
  # Trigger: PreToolUse on mcp__orchestrator-tools__advancePhase
4
- # Purpose: Before any phase advance, evaluate the gate.
5
- # BLOCKS the advance if the gate fails (exit 1).
6
- # Also enforces human approval for IMPLEMENT phase.
4
+ # Purpose: Evaluate gate before phase advance. FAIL-CLOSED: blocks when uncertain.
7
5
  #
8
- # Exit 0 = allow advancePhase to proceed
9
- # Exit 1 = BLOCK advancePhase (gate failed or approval required)
6
+ # Output: JSON with permissionDecision (deny/allow) + additionalContext
7
+ # Exit 0 with JSON = structured decision
10
8
 
11
9
  set -euo pipefail
12
10
 
13
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
12
  source "$SCRIPT_DIR/orch-helpers.sh"
15
13
 
16
- # Read stdin (Claude Code passes tool input JSON)
17
14
  STDIN_DATA=$(orch_read_stdin)
18
15
  orch_log "GATE-GUARDIAN: PreToolUse advancePhase triggered"
19
16
 
20
- # Extract workflowId and targetPhase from tool input
17
+ # Extract parameters
21
18
  WORKFLOW_ID=$(orch_json_field "$STDIN_DATA" "tool_input.workflowId")
22
19
  TARGET_PHASE=$(orch_json_field "$STDIN_DATA" "tool_input.targetPhase")
23
-
24
- # Fallback: try without tool_input wrapper
25
20
  [ -z "$WORKFLOW_ID" ] && WORKFLOW_ID=$(orch_json_field "$STDIN_DATA" "workflowId")
26
21
  [ -z "$TARGET_PHASE" ] && TARGET_PHASE=$(orch_json_field "$STDIN_DATA" "targetPhase")
27
22
 
28
23
  orch_log "GATE-GUARDIAN: workflow=$WORKFLOW_ID targetPhase=$TARGET_PHASE"
29
24
 
30
- # If we can't parse the input, allow (don't break on edge cases)
25
+ # FAIL-CLOSED: if we can't parse input, DENY
31
26
  if [ -z "$WORKFLOW_ID" ] || [ -z "$TARGET_PHASE" ]; then
32
- orch_log "GATE-GUARDIAN: Could not parse input, allowing"
27
+ orch_log "GATE-GUARDIAN: DENY (could not parse input)"
28
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Gate Guardian: Could not parse workflowId or targetPhase.","additionalContext":"Ensure you pass both workflowId and targetPhase to advancePhase."}}'
33
29
  exit 0
34
30
  fi
35
31
 
36
- # --- IMPLEMENT phase: check for human approval ---
37
- TARGET_LOWER=$(echo "$TARGET_PHASE" | tr '[:upper:]' '[:lower:]')
32
+ # Get auth token FAIL-CLOSED on auth failure
33
+ TOKEN=$(orch_get_token 2>/dev/null) || TOKEN=""
34
+ if [ -z "$TOKEN" ]; then
35
+ orch_log "GATE-GUARDIAN: DENY (auth failed)"
36
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Gate Guardian: Authentication failed.","additionalContext":"Check ORCHESTRATOR_ADMIN_EMAIL, ORCHESTRATOR_ADMIN_PASSWORD, ORCHESTRATOR_PROJECT_ID env vars."}}'
37
+ exit 0
38
+ fi
38
39
 
40
+ # Special handling for IMPLEMENT phase: require approval
41
+ TARGET_LOWER=$(echo "$TARGET_PHASE" | tr '[:upper:]' '[:lower:]')
39
42
  if [ "$TARGET_LOWER" = "implement" ]; then
40
43
  orch_log "GATE-GUARDIAN: Checking approval for IMPLEMENT phase"
41
44
 
42
- # Check pending action status
43
- NEXT_ACTION=$(orch_get_next_action "$WORKFLOW_ID" 2>/dev/null) || {
44
- orch_log "GATE-GUARDIAN: Could not check approval, allowing"
45
- exit 0
46
- }
47
-
48
- STATUS=$(orch_json_field "$NEXT_ACTION" "pendingAction.status")
49
-
50
- if [ "$STATUS" = "awaiting_approval" ]; then
51
- echo ""
52
- echo "[GATE-GUARDIAN] BLOCKED: Cannot advance to IMPLEMENT without human approval."
53
- echo "The workflow requires user approval before implementation begins."
54
- echo "Call mcp__orchestrator-tools__approveAction({ workflowId: '$WORKFLOW_ID' }) after user approves."
55
- orch_log "GATE-GUARDIAN: BLOCKED — awaiting_approval for IMPLEMENT"
56
- exit 1
45
+ PENDING=$(curl -sf --max-time 5 "${API_URL}/api/v1/workflows/${WORKFLOW_ID}/pending-action" \
46
+ -H "Authorization: Bearer $TOKEN" \
47
+ -H "X-Project-ID: $PROJECT_ID" 2>/dev/null) || PENDING=""
48
+
49
+ if [ -n "$PENDING" ]; then
50
+ PENDING_STATUS=$(orch_json_field "$PENDING" "status")
51
+ if [ "$PENDING_STATUS" != "approved" ] && [ "$PENDING_STATUS" != "awaiting_agent" ]; then
52
+ orch_log "GATE-GUARDIAN: DENY (IMPLEMENT requires approval, status=$PENDING_STATUS)"
53
+ echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Gate Guardian: IMPLEMENT requires human approval. Status: ${PENDING_STATUS}.\",\"additionalContext\":\"Ask the user for approval first. Then call mcp__orchestrator-tools__approveAction.\"}}"
54
+ exit 0
55
+ fi
57
56
  fi
58
57
  fi
59
58
 
60
- # --- All phases: evaluate gate ---
61
- GATE_RESULT=$(orch_evaluate_gate "$WORKFLOW_ID" "$TARGET_PHASE" 2>/dev/null) || {
62
- orch_log "GATE-GUARDIAN: evaluateGate call failed, allowing (API may not support this gate)"
59
+ # Evaluate gate via API FAIL-CLOSED on failure
60
+ GATE_RESULT=$(orch_evaluate_gate "$WORKFLOW_ID" "$TARGET_PHASE" 2>/dev/null) || GATE_RESULT=""
61
+ if [ -z "$GATE_RESULT" ]; then
62
+ orch_log "GATE-GUARDIAN: DENY (gate evaluation failed)"
63
+ echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Gate Guardian: Gate evaluation failed for phase '${TARGET_PHASE}'.\",\"additionalContext\":\"Required artifacts may be missing. Complete the current phase before advancing.\"}}"
63
64
  exit 0
64
- }
65
+ fi
65
66
 
66
67
  PASSED=$(orch_json_field "$GATE_RESULT" "passed")
67
68
 
68
- if [ "$PASSED" = "false" ]; then
69
- REASONS=$(orch_json_field "$GATE_RESULT" "reasons")
70
- echo ""
71
- echo "[GATE-GUARDIAN] BLOCKED: Gate to '$TARGET_PHASE' did not pass."
72
- echo "Reasons: $REASONS"
73
- echo "Fix the issues before advancing."
74
- orch_log "GATE-GUARDIAN: BLOCKED — gate failed for $TARGET_PHASE: $REASONS"
75
- exit 1
69
+ if [ "$PASSED" = "true" ]; then
70
+ orch_log "GATE-GUARDIAN: ALLOW (gate passed for $TARGET_PHASE)"
71
+ echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"additionalContext\":\"Gate to '${TARGET_PHASE}' passed.\"}}"
72
+ exit 0
76
73
  fi
77
74
 
78
- orch_log "GATE-GUARDIAN: Gate to $TARGET_PHASE PASSED"
79
- echo "[GATE-GUARDIAN] Gate to '$TARGET_PHASE' PASSED."
75
+ # Gate failed
76
+ REASONS=$(orch_json_field "$GATE_RESULT" "reasons")
77
+ orch_log "GATE-GUARDIAN: DENY (gate failed: $REASONS)"
78
+ echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Gate Guardian: Gate to '${TARGET_PHASE}' did not pass.\",\"additionalContext\":\"Reasons: ${REASONS}. Complete current phase requirements before advancing.\"}}"
80
79
  exit 0