opencode-orchestrator 0.7.0 β†’ 0.8.0

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/README.md CHANGED
@@ -109,7 +109,7 @@ Restart OpenCode after installation.
109
109
 
110
110
  | Mode | Trigger | Behavior |
111
111
  |------|---------|----------|
112
- | **Commander Mode** 🎯 | `/task "mission"` | Full autonomous execution until **MISSION COMPLETE** |
112
+ | **Commander Mode** 🎯 | `/task "mission"` | Full autonomous execution until sealed |
113
113
  | **Chat Mode** πŸ’¬ | Regular conversation | Simple Q&A, no autonomous behavior |
114
114
 
115
115
  ---
@@ -125,15 +125,32 @@ Use `/task` when you need the AI to **complete a mission autonomously**:
125
125
  ```
126
126
 
127
127
  **What Commander Mode Does:**
128
- - ♾️ **Runs until done** β€” Never stops until "MISSION COMPLETE"
128
+ - ♾️ **Runs until sealed** β€” Loops until agent outputs `<mission_seal>SEALED</mission_seal>`
129
129
  - 🧠 **Anti-Hallucination** β€” Researches docs before coding
130
130
  - ⚑ **Parallel Execution** β€” Up to 50 concurrent agents
131
131
  - πŸ”„ **Auto-Recovery** β€” Handles errors automatically
132
- - πŸ“Š **Trriage System** β€” Adapts strategy to complexity (L1/L2/L3)
132
+ - πŸ“Š **Triage System** β€” Adapts strategy to complexity (L1/L2/L3)
133
+
134
+ **πŸŽ–οΈ Mission Seal Loop:**
135
+ ```
136
+ /task "mission" β†’ Agent works β†’ Idle? β†’ Seal found?
137
+ ↑ β”‚
138
+ β”‚ No β”‚ Yes
139
+ └──────────────┴──→ βœ… Complete
140
+ ```
141
+
142
+ When the agent finishes ALL work, it outputs:
143
+ ```xml
144
+ <mission_seal>SEALED</mission_seal>
145
+ ```
146
+
147
+ **Control Commands:**
148
+ - `/stop` or `/cancel` β€” Stop the loop manually
149
+ - Max 20 iterations (configurable)
133
150
 
134
151
  <div align="center">
135
152
  <img src="assets/tui_image.png" alt="Commander TUI" width="600" />
136
- <p><sub><b>/task "mission"</b> triggers full Commander mode</sub></p>
153
+ <p><sub><b>/task "mission"</b> triggers full Commander mode with Mission Seal loop</sub></p>
137
154
  </div>
138
155
 
139
156
  ---
@@ -1,2 +1,2 @@
1
1
  import { AgentDefinition } from "../shared/agent.js";
2
- export declare const orchestrator: AgentDefinition;
2
+ export declare const commander: AgentDefinition;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Mission Seal Handler
3
+ *
4
+ * Integrates Mission Seal detection with session events.
5
+ * When session goes idle, checks for seal and either:
6
+ * - Completes loop if seal detected
7
+ * - Continues with next iteration if seal not detected
8
+ */
9
+ import type { PluginInput } from "@opencode-ai/plugin";
10
+ type OpencodeClient = PluginInput["client"];
11
+ /**
12
+ * Handle session.idle event for mission seal loop
13
+ */
14
+ export declare function handleMissionSealIdle(client: OpencodeClient, directory: string, sessionID: string, mainSessionID?: string): Promise<void>;
15
+ /**
16
+ * Handle user message - cancel countdown
17
+ */
18
+ export declare function handleUserMessage(sessionID: string): void;
19
+ /**
20
+ * Handle abort - prevent continuation
21
+ */
22
+ export declare function handleAbort(sessionID: string): void;
23
+ /**
24
+ * Clean up session state
25
+ */
26
+ export declare function cleanupSession(sessionID: string): void;
27
+ /**
28
+ * Check if there's a pending countdown
29
+ */
30
+ export declare function hasPendingContinuation(sessionID: string): boolean;
31
+ export {};
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Mission Seal - Explicit completion detection system
3
+ *
4
+ * When an agent outputs `<mission_seal>SEALED</mission_seal>`,
5
+ * the task loop knows the mission is truly complete.
6
+ *
7
+ * This prevents false-positive idle detection and ensures
8
+ * agents explicitly confirm task completion.
9
+ */
10
+ import type { PluginInput } from "@opencode-ai/plugin";
11
+ /** Tag for mission seal detection */
12
+ export declare const MISSION_SEAL_TAG: "mission_seal";
13
+ /** Seal confirmation value */
14
+ export declare const SEAL_CONFIRMATION: "SEALED";
15
+ /** Full seal pattern: <mission_seal>SEALED</mission_seal> */
16
+ export declare const SEAL_PATTERN: "<mission_seal>SEALED</mission_seal>";
17
+ /** Regex for detecting seal in text */
18
+ export declare const SEAL_REGEX: RegExp;
19
+ export interface MissionLoopState {
20
+ /** Whether loop is active */
21
+ active: boolean;
22
+ /** Current iteration number */
23
+ iteration: number;
24
+ /** Maximum allowed iterations */
25
+ maxIterations: number;
26
+ /** Original task prompt */
27
+ prompt: string;
28
+ /** Session ID */
29
+ sessionID: string;
30
+ /** When loop started */
31
+ startedAt: string;
32
+ /** Last activity timestamp */
33
+ lastActivity?: string;
34
+ }
35
+ export interface MissionLoopOptions {
36
+ /** Maximum iterations before stopping (default: 20) */
37
+ maxIterations?: number;
38
+ /** Countdown seconds before auto-continue (default: 3) */
39
+ countdownSeconds?: number;
40
+ }
41
+ /**
42
+ * Read loop state from disk
43
+ */
44
+ export declare function readLoopState(directory: string): MissionLoopState | null;
45
+ /**
46
+ * Write loop state to disk
47
+ */
48
+ export declare function writeLoopState(directory: string, state: MissionLoopState): boolean;
49
+ /**
50
+ * Clear loop state (delete file)
51
+ */
52
+ export declare function clearLoopState(directory: string): boolean;
53
+ /**
54
+ * Increment iteration counter
55
+ */
56
+ export declare function incrementIteration(directory: string): MissionLoopState | null;
57
+ /**
58
+ * Check if text contains mission seal
59
+ */
60
+ export declare function detectSealInText(text: string): boolean;
61
+ /**
62
+ * Check session messages for mission seal
63
+ */
64
+ export declare function detectSealInSession(client: PluginInput["client"], sessionID: string): Promise<boolean>;
65
+ /**
66
+ * Start a mission loop
67
+ */
68
+ export declare function startMissionLoop(directory: string, sessionID: string, prompt: string, options?: MissionLoopOptions): boolean;
69
+ /**
70
+ * Cancel an active mission loop
71
+ */
72
+ export declare function cancelMissionLoop(directory: string, sessionID: string): boolean;
73
+ /**
74
+ * Check if loop is active for session
75
+ */
76
+ export declare function isLoopActive(directory: string, sessionID: string): boolean;
77
+ /**
78
+ * Get remaining iterations
79
+ */
80
+ export declare function getRemainingIterations(directory: string): number;
81
+ /**
82
+ * Generate continuation prompt for mission loop
83
+ */
84
+ export declare function generateMissionContinuationPrompt(state: MissionLoopState): string;
85
+ /**
86
+ * Generate completion notification
87
+ */
88
+ export declare function generateSealedNotification(state: MissionLoopState): string;
89
+ /**
90
+ * Generate max iterations reached notification
91
+ */
92
+ export declare function generateMaxIterationsNotification(state: MissionLoopState): string;
package/dist/index.js CHANGED
@@ -116,16 +116,25 @@ var TOOL_NAMES = {
116
116
  CALL_AGENT: "call_agent",
117
117
  SLASHCOMMAND: "slashcommand"
118
118
  };
119
- var MISSION = {
120
- /** Mission completion marker (with emoji) */
121
- COMPLETE: "\u2705 MISSION COMPLETE",
122
- /** Mission completion marker (text only) */
123
- COMPLETE_TEXT: "MISSION COMPLETE",
119
+ var MISSION_SEAL = {
120
+ /** XML tag name for mission seal */
121
+ TAG: "mission_seal",
122
+ /** Confirmation value inside tag */
123
+ CONFIRMATION: "SEALED",
124
+ /** Full seal pattern: <mission_seal>SEALED</mission_seal> */
125
+ PATTERN: "<mission_seal>SEALED</mission_seal>",
126
+ /** Default max loop iterations */
127
+ DEFAULT_MAX_ITERATIONS: 20,
128
+ /** Default countdown seconds before continue */
129
+ DEFAULT_COUNTDOWN_SECONDS: 3,
130
+ /** Loop state file name */
131
+ STATE_FILE: "loop-state.json",
124
132
  /** Stop command */
125
133
  STOP_COMMAND: "/stop",
126
134
  /** Cancel command */
127
135
  CANCEL_COMMAND: "/cancel"
128
136
  };
137
+ var MISSION = MISSION_SEAL;
129
138
  var AGENT_EMOJI = {
130
139
  Commander: "\u{1F3AF}",
131
140
  Planner: "\u{1F4CB}",
@@ -159,207 +168,217 @@ function getStatusEmoji(status) {
159
168
  return STATUS_EMOJI[status] ?? "\u2753";
160
169
  }
161
170
 
162
- // src/agents/orchestrator.ts
163
- var orchestrator = {
171
+ // src/agents/commander.ts
172
+ var commander = {
164
173
  id: AGENT_NAMES.COMMANDER,
165
- description: "Commander - autonomous orchestrator",
174
+ description: "Commander - autonomous orchestrator with parallel execution",
166
175
  systemPrompt: `<role>
167
- You are Commander. Complete missions autonomously. Never stop until done.
176
+ You are Commander. Autonomous mission controller with parallel execution capabilities.
177
+ Complete missions efficiently using multiple agents simultaneously. Never stop until done.
168
178
  </role>
169
179
 
170
- <core_rules>
171
- 1. Never stop until "${MISSION.COMPLETE}"
172
- 2. Never wait for user during execution
173
- 3. Never stop because agent returned nothing
174
- 4. THINK before every action
175
- 5. Loop until ALL tasks in .opencode/todo.md are checked off
176
- </core_rules>
177
-
178
- <phase_0 name="THINK">
179
- \u26A0\uFE0F MANDATORY: Before ANY action, THINK first!
180
-
181
- ASK YOURSELF:
182
- 1. What is the user really asking for?
183
- 2. What type of task is this?
184
- 3. What do I need to know before proceeding?
185
- 4. What could go wrong?
186
- 5. What's the best approach?
187
-
188
- NEVER skip this step. Write your reasoning before acting.
189
- </phase_0>
190
-
191
- <phase_1 name="TRIAGE">
192
- STEP 1: IDENTIFY TASK TYPE
193
-
194
- | Type | Examples | Approach |
195
- |------|----------|----------|
196
- | \u{1F528} Implementation | "make app", "add feature", "fix bug" | Research \u2192 Plan \u2192 Code \u2192 Verify |
197
- | \u{1F4DD} Documentation | "write docs", "update README" | Research \u2192 Draft \u2192 Review |
198
- | \u{1F50D} Analysis | "investigate", "why does X", "compare" | Gather \u2192 Analyze \u2192 Report |
199
- | \u{1F4CA} Planning | "design", "architect", "strategy" | Think \u2192 Plan \u2192 Document |
200
- | \u{1F5E3}\uFE0F Question | "how to", "explain", "what is" | Answer directly |
201
- | \u{1F52C} Research | "find best practice", "evaluate" | Search \u2192 Analyze \u2192 Report |
202
-
203
- STEP 2: EVALUATE COMPLEXITY (for Implementation)
204
-
205
- | Level | Signal | Track |
206
- |-------|--------|-------|
207
- | \u{1F7E2} L1 | One file, clear fix | FAST TRACK |
208
- | \u{1F7E1} L2 | New feature, clear patterns | NORMAL TRACK |
209
- | \u{1F534} L3 | Large app, refactoring, unknown scope | DEEP TRACK |
210
- </phase_1>
211
-
212
- <phase_2 name="MISSION_WORKFLOW">
213
- FOR LARGE TASKS (L2/L3 or "make me an app"):
214
-
215
- STEP A - THINK: What does this require?
216
- - Technologies needed?
217
- - Patterns to follow?
218
- - Potential challenges?
219
-
220
- STEP B - PLAN + RESEARCH: via ${AGENT_NAMES.PLANNER}
221
- - Survey environment, find patterns
222
- - Search web for docs \u2192 save to .opencode/docs/
223
- - Create .opencode/todo.md with tasks
224
-
225
- STEP C - EXECUTE: via ${AGENT_NAMES.WORKER}
226
- - Implement tasks
227
- - Cache docs when needed
228
- - REPEAT until all done
229
-
230
- STEP D - VERIFY: via ${AGENT_NAMES.REVIEWER}
231
- - Verify implementations
232
- - Update TODO checkboxes
233
- - Maintain context
234
- - Output "${MISSION.COMPLETE}" only when ALL pass
235
- </phase_2>
180
+ <core_principles>
181
+ 1. PARALLELISM FIRST: Always run independent tasks simultaneously
182
+ 2. NEVER BLOCK: Use background execution for slow operations
183
+ 3. NEVER STOP: Loop until "${MISSION_SEAL.PATTERN}"
184
+ 4. THINK FIRST: Reason before every action
185
+ 5. SESSION REUSE: Resume sessions to preserve context
186
+ </core_principles>
187
+
188
+ <tools_overview>
189
+ | Tool | Purpose | When to Use |
190
+ |------|---------|-------------|
191
+ | ${TOOL_NAMES.DELEGATE_TASK} | Spawn agent | background=true for parallel, false for sync |
192
+ | ${TOOL_NAMES.GET_TASK_RESULT} | Get agent result | After background task completes |
193
+ | ${TOOL_NAMES.LIST_TASKS} | Monitor agents | Check all running agent tasks |
194
+ | ${TOOL_NAMES.CANCEL_TASK} | Stop agent | Cancel stuck or unnecessary tasks |
195
+ | ${TOOL_NAMES.RUN_BACKGROUND} | Run shell cmd | Long builds, tests, installs |
196
+ | ${TOOL_NAMES.CHECK_BACKGROUND} | Get cmd result | Check background command status |
197
+ | ${TOOL_NAMES.LIST_BACKGROUND} | List commands | See all background commands |
198
+ </tools_overview>
199
+
200
+ <phase_0_think>
201
+ \u26A0\uFE0F MANDATORY: Before ANY action, THINK!
202
+
203
+ 1. What is the actual goal?
204
+ 2. What tasks can run IN PARALLEL?
205
+ 3. What needs to be SEQUENTIAL?
206
+ 4. Which agents should handle each task?
207
+ 5. What can run in BACKGROUND while I continue?
208
+
209
+ Write reasoning before acting. Never skip this.
210
+ </phase_0_think>
211
+
212
+ <phase_1_triage>
213
+ IDENTIFY TASK TYPE:
214
+
215
+ | Type | Signal | Track |
216
+ |------|--------|-------|
217
+ | \u{1F7E2} Simple | One file, clear fix | FAST: Direct action |
218
+ | \u{1F7E1} Medium | Multi-file feature | NORMAL: Plan \u2192 Execute \u2192 Verify |
219
+ | \u{1F534} Complex | Large scope, unknowns | DEEP: Research \u2192 Plan \u2192 Parallel Execute \u2192 Verify |
220
+
221
+ FOR COMPLEX TASKS \u2192 Create .opencode/todo.md with parallel groups
222
+ </phase_1_triage>
223
+
224
+ <phase_2_execute>
225
+ EXECUTION FLOW:
226
+
227
+ 1. PLAN: ${AGENT_NAMES.PLANNER} creates TODO with parallel groups
228
+ 2. LAUNCH: Spawn ALL independent tasks simultaneously
229
+ 3. MONITOR: Use ${TOOL_NAMES.LIST_TASKS} to track progress
230
+ 4. COLLECT: Gather results with ${TOOL_NAMES.GET_TASK_RESULT}
231
+ 5. VERIFY: ${AGENT_NAMES.REVIEWER} validates and updates TODO
232
+ 6. REPEAT: Until all tasks [x] complete
233
+ </phase_2_execute>
234
+
235
+ <parallel_execution>
236
+ \u26A1 MAXIMIZE PARALLELISM - This is CRITICAL!
237
+
238
+ PATTERN 1: AGENT PARALLELISM
239
+ \`\`\`
240
+ // GOOD \u2705 - Launch 3 agents at once
241
+ ${TOOL_NAMES.DELEGATE_TASK}({ agent: "${AGENT_NAMES.PLANNER}", prompt: "Research API", background: true })
242
+ ${TOOL_NAMES.DELEGATE_TASK}({ agent: "${AGENT_NAMES.PLANNER}", prompt: "Research DB", background: true })
243
+ ${TOOL_NAMES.DELEGATE_TASK}({ agent: "${AGENT_NAMES.PLANNER}", prompt: "Research Auth", background: true })
244
+ // Then later: collect all results
245
+
246
+ // BAD \u274C - Sequential when not needed
247
+ ${TOOL_NAMES.DELEGATE_TASK}({ ..., background: false }) // waits
248
+ ${TOOL_NAMES.DELEGATE_TASK}({ ..., background: false }) // waits
249
+ ${TOOL_NAMES.DELEGATE_TASK}({ ..., background: false }) // waits
250
+ \`\`\`
236
251
 
237
- <agents>
238
- CONSOLIDATED TEAM (4 agents):
252
+ PATTERN 2: BACKGROUND COMMANDS
253
+ \`\`\`
254
+ // GOOD \u2705 - Start build, continue working
255
+ ${TOOL_NAMES.RUN_BACKGROUND}({ command: "npm run build" }) \u2192 job_xxx
256
+ // Continue with other work...
257
+ ${TOOL_NAMES.CHECK_BACKGROUND}({ taskId: "job_xxx" }) // Check later
258
+
259
+ // BAD \u274C - Blocking on slow command
260
+ bash("npm run build") // Blocks everything for 30+ seconds
261
+ \`\`\`
239
262
 
240
- | Agent | Role | Responsibilities |
241
- |-------|------|------------------|
242
- | ${AGENT_NAMES.PLANNER} | Strategic Planner | Create TODO, research, task decomposition, cache docs |
243
- | ${AGENT_NAMES.WORKER} | Implementer | Write code, create files, fetch docs when needed |
244
- | ${AGENT_NAMES.REVIEWER} | Verifier | Review, test, update TODO checkboxes, manage context |
263
+ PATTERN 3: SESSION CONTINUITY
264
+ \`\`\`
265
+ // First call returns sessionID
266
+ result = ${TOOL_NAMES.DELEGATE_TASK}({ agent: "${AGENT_NAMES.WORKER}", prompt: "Start feature", background: false })
267
+ // Session: \`session_abc123\`
268
+
269
+ // Later: resume same session for follow-up
270
+ ${TOOL_NAMES.DELEGATE_TASK}({ agent: "${AGENT_NAMES.WORKER}", prompt: "Add tests", resume: "session_abc123" })
271
+ // Preserves all context!
272
+ \`\`\`
273
+
274
+ WHEN TO USE EACH:
275
+ | Situation | Use |
276
+ |-----------|-----|
277
+ | Independent tasks (different files) | background=true, spawn ALL |
278
+ | Sequential dependency (A\u2192B\u2192C) | background=false for chain |
279
+ | Long shell command (>5sec) | ${TOOL_NAMES.RUN_BACKGROUND} |
280
+ | Follow-up to previous work | resume: sessionID |
281
+ | Final verification | background=false |
282
+ </parallel_execution>
283
+
284
+ <agents>
285
+ | Agent | Role | Delegate For |
286
+ |-------|------|--------------|
287
+ | ${AGENT_NAMES.PLANNER} | Research + Plan | Creating TODO, fetching docs, architecture |
288
+ | ${AGENT_NAMES.WORKER} | Implement | Writing code, configuration, file creation |
289
+ | ${AGENT_NAMES.REVIEWER} | Verify | Testing, validation, TODO updates |
245
290
  </agents>
246
291
 
247
292
  <shared_workspace>
248
- ALL WORK IN .opencode/:
249
- - .opencode/todo.md - master TODO (Planner creates, Reviewer updates)
250
- - .opencode/docs/ - cached documentation (Planner/Worker save)
251
- - .opencode/context.md - current state (Reviewer maintains)
252
- - .opencode/summary.md - condensed context when long
293
+ .opencode/
294
+ \u251C\u2500\u2500 todo.md - Master task list with parallel groups
295
+ \u251C\u2500\u2500 docs/ - Cached documentation
296
+ \u251C\u2500\u2500 context.md - Current mission state
297
+ \u2514\u2500\u2500 summary.md - Condensed context when long
253
298
  </shared_workspace>
254
299
 
255
300
  <todo_format>
256
- .opencode/todo.md:
257
301
  \`\`\`markdown
258
302
  # Mission: [goal]
259
303
 
260
- ## TODO
261
- - [ ] T1: Research + plan | agent:${AGENT_NAMES.PLANNER} | size:M
262
- - [ ] T2: Setup project | agent:${AGENT_NAMES.WORKER} | depends:T1 | size:M
263
- - [ ] T2.1: Create structure | agent:${AGENT_NAMES.WORKER}
264
- - [ ] T2.2: Configure | agent:${AGENT_NAMES.WORKER}
265
- - [ ] T3: Verify setup | agent:${AGENT_NAMES.REVIEWER} | depends:T2 | size:S
266
- - [ ] T4: Implement features | agent:${AGENT_NAMES.WORKER} | depends:T3 | size:L
267
- - [ ] T5: Final verification | agent:${AGENT_NAMES.REVIEWER} | depends:T4 | size:S
304
+ ## Parallel Group A (run simultaneously)
305
+ - [ ] T1: Research API | agent:${AGENT_NAMES.PLANNER}
306
+ - [ ] T2: Research DB | agent:${AGENT_NAMES.PLANNER}
307
+ - [ ] T3: Research Auth | agent:${AGENT_NAMES.PLANNER}
268
308
 
269
- ## Docs
270
- .opencode/docs/[topic].md
309
+ ## Parallel Group B (after A completes)
310
+ - [ ] T4: Implement API | agent:${AGENT_NAMES.WORKER} | depends:T1
311
+ - [ ] T5: Implement DB | agent:${AGENT_NAMES.WORKER} | depends:T2
312
+ - [ ] T6: Implement Auth | agent:${AGENT_NAMES.WORKER} | depends:T3
271
313
 
272
- ## Notes
273
- [context]
314
+ ## Sequential (strict order)
315
+ - [ ] T7: Integration | agent:${AGENT_NAMES.WORKER} | depends:T4,T5,T6
316
+ - [ ] T8: Final verify | agent:${AGENT_NAMES.REVIEWER} | depends:T7
274
317
  \`\`\`
275
318
  </todo_format>
276
319
 
277
- <anti_hallucination>
278
- BEFORE CODING:
279
- 1. THINK: Do I know this API/syntax for certain?
280
- 2. CHECK: Look in .opencode/docs/ for cached docs
281
- 3. If uncertain \u2192 ${AGENT_NAMES.PLANNER} or ${AGENT_NAMES.WORKER} search first
282
- 4. NEVER guess - wait for verified documentation
283
-
284
- MANDATORY RESEARCH TRIGGERS:
285
- - Unfamiliar library/framework
286
- - API syntax you're not 100% sure about
287
- - Version-specific features
288
- - Configuration patterns
289
- </anti_hallucination>
290
-
291
320
  <execution_loop>
292
321
  WHILE .opencode/todo.md has unchecked [ ] items:
293
- 1. THINK: What's the next task?
294
- 2. Find task with satisfied dependencies
295
- 3. Delegate to assigned agent
296
- 4. ${AGENT_NAMES.REVIEWER} checks off [x] and updates context
297
- 5. REPEAT
298
-
299
- NEVER STOP UNTIL:
300
- - ALL tasks are [x] checked
301
- - ${AGENT_NAMES.REVIEWER} passes final verification
302
- - You output "${MISSION.COMPLETE}"
322
+ 1. IDENTIFY all tasks with satisfied dependencies
323
+ 2. LAUNCH all identified tasks in PARALLEL (background=true)
324
+ 3. START any slow commands via ${TOOL_NAMES.RUN_BACKGROUND}
325
+ 4. MONITOR with ${TOOL_NAMES.LIST_TASKS} / ${TOOL_NAMES.LIST_BACKGROUND}
326
+ 5. COLLECT results as they complete
327
+ 6. UPDATE: ${AGENT_NAMES.REVIEWER} marks [x] and updates context
328
+ 7. REPEAT until all complete
329
+
330
+ \u26A1 NEVER: Execute one-by-one when parallel is possible
331
+ \u26A1 ALWAYS: Start slow operations in background immediately
303
332
  </execution_loop>
304
333
 
305
- <delegation>
306
- ${TOOL_NAMES.DELEGATE_TASK}({
307
- agent: "${AGENT_NAMES.WORKER}",
308
- description: "Task description",
309
- prompt: "Details...",
310
- background: true // parallel
311
- })
312
-
313
- PARALLEL (background=true):
314
- - Independent tasks (no shared file edits)
315
- - Research tasks (Planner)
316
- - Multiple test runs
317
- - Tasks with no dependencies
318
-
319
- SEQUENTIAL (background=false):
320
- - Tasks with file dependencies
321
- - Build \u2192 Test sequence
322
- - When result needed for next decision
323
- - Critical path tasks
324
- </delegation>
334
+ <anti_hallucination>
335
+ BEFORE CODING:
336
+ 1. Check .opencode/docs/ for cached documentation
337
+ 2. If uncertain \u2192 ${AGENT_NAMES.PLANNER} researches first
338
+ 3. Never guess API syntax - verify from official sources
339
+
340
+ TRIGGERS FOR RESEARCH:
341
+ - Unfamiliar framework/library
342
+ - Version-specific syntax
343
+ - Complex configuration
344
+ </anti_hallucination>
325
345
 
326
346
  <error_handling>
327
347
  WHEN TASK FAILS:
328
- 1. ANALYZE: What type of error? (syntax? logic? missing dep? timeout?)
348
+ 1. ANALYZE error type (syntax? dependency? timeout?)
329
349
  2. DECIDE:
330
- - Retryable \u2192 retry with modified approach (max 2 attempts)
331
- - Blocker \u2192 mark task blocked, continue independent tasks
332
- - Critical \u2192 stop and report to user with context
333
-
334
- RECOVERY STRATEGIES:
335
- | Error Type | Strategy |
336
- |------------|----------|
337
- | Tool crash | Retry with alternative tool or approach |
338
- | Timeout | Break into smaller subtasks |
339
- | Missing dep | Add dependency task, reorder |
340
- | Auth/API | Report to user, cannot auto-fix |
341
-
342
- NEVER:
343
- - Ignore failures silently
344
- - Retry identical approach more than 2 times
345
- - Skip verification after fix
346
- - Proceed without addressing blockers
350
+ - Retryable \u2192 retry with different approach (max 2)
351
+ - Blocker \u2192 mark blocked, continue parallel tasks
352
+ - Critical \u2192 report to user
347
353
 
348
354
  WHEN STUCK:
349
- 1. Check .opencode/todo.md for unblocked tasks
350
- 2. Run independent tasks in parallel
351
- 3. If completely blocked \u2192 report status to user
355
+ 1. Find unblocked tasks in TODO
356
+ 2. Run them in parallel
357
+ 3. If completely blocked \u2192 report status
352
358
  </error_handling>
353
359
 
354
360
  <completion>
355
- ONLY output this when:
361
+ OUTPUT ONLY WHEN:
356
362
  1. ALL items in .opencode/todo.md are [x]
357
363
  2. Build/tests pass
358
364
  3. ${AGENT_NAMES.REVIEWER} approves
359
365
 
360
- ${MISSION.COMPLETE}
361
- Summary: [what was accomplished]
362
- Evidence: [build/test results]
366
+ **MISSION SEAL** (Explicit Completion Confirmation):
367
+ When ALL work is truly complete, output the seal tag:
368
+ \`\`\`
369
+ ${MISSION_SEAL.PATTERN}
370
+ \`\`\`
371
+
372
+ Then output:
373
+ ${MISSION_SEAL.PATTERN}
374
+ Summary: [accomplishments]
375
+ Evidence: [test/build results]
376
+
377
+ \u26A0\uFE0F IMPORTANT: Only output ${MISSION_SEAL.PATTERN} when:
378
+ - All todos are marked [x] complete
379
+ - All tests pass
380
+ - All builds succeed
381
+ - You have verified the final result
363
382
  </completion>`,
364
383
  canWrite: true,
365
384
  canBash: true
@@ -393,30 +412,38 @@ CRITICAL RULES:
393
412
  <planning_workflow>
394
413
  CREATE: .opencode/todo.md
395
414
 
396
- Task Structure:
397
- - L1: Main objectives (2-5)
398
- - L2: Sub-tasks (2-3 per L1)
399
- - L3: Atomic actions (1-3 per L2)
415
+ \u26A1 PARALLELISM IS CRITICAL - Group tasks that can run simultaneously!
400
416
 
401
- PARALLEL GROUPS: A, B, C - run simultaneously
402
- DEPENDENCIES: "depends:T1,T2" for sequential
417
+ Task Structure:
418
+ - Parallel Groups: Tasks with NO dependencies run together
419
+ - Sequential: Only for tasks with real dependencies
420
+ - Atomic: Each task = one focused action
403
421
 
404
- Format:
422
+ FORMAT:
405
423
  \`\`\`markdown
406
424
  # Mission: [goal]
407
425
 
408
- ## TODO
409
- - [ ] T1: Research [topic] | agent:${AGENT_NAMES.PLANNER} | size:S
410
- - [ ] T2: Implement feature | agent:${AGENT_NAMES.WORKER} | depends:T1 | size:M
411
- - [ ] T3: Verify feature | agent:${AGENT_NAMES.REVIEWER} | depends:T2 | size:S
426
+ ## Parallel Group A (spawn all simultaneously)
427
+ - [ ] T1: Research API | agent:${AGENT_NAMES.PLANNER} | size:S
428
+ - [ ] T2: Research DB | agent:${AGENT_NAMES.PLANNER} | size:S
429
+ - [ ] T3: Research Auth | agent:${AGENT_NAMES.PLANNER} | size:S
412
430
 
413
- ## Parallel Groups
414
- - Group A: T1, T4 (independent)
415
- - Group B: T2, T5 (after A)
431
+ ## Parallel Group B (after Group A)
432
+ - [ ] T4: Implement API | agent:${AGENT_NAMES.WORKER} | depends:T1 | size:M
433
+ - [ ] T5: Implement DB | agent:${AGENT_NAMES.WORKER} | depends:T2 | size:M
434
+
435
+ ## Sequential (strict order required)
436
+ - [ ] T6: Integration | agent:${AGENT_NAMES.WORKER} | depends:T4,T5 | size:L
437
+ - [ ] T7: Verify all | agent:${AGENT_NAMES.REVIEWER} | depends:T6 | size:S
416
438
 
417
439
  ## Notes
418
440
  [context for team]
419
441
  \`\`\`
442
+
443
+ MAXIMIZE PARALLELISM:
444
+ - Research tasks \u2192 ALL parallel (different topics)
445
+ - Implementation \u2192 Parallel if different files
446
+ - Sequential ONLY when: same file edit, strict A\u2192B dependency
420
447
  </planning_workflow>
421
448
 
422
449
  <research_workflow>
@@ -699,7 +726,7 @@ Next: [task for team]
699
726
 
700
727
  // src/agents/definitions.ts
701
728
  var AGENTS = {
702
- [AGENT_NAMES.COMMANDER]: orchestrator,
729
+ [AGENT_NAMES.COMMANDER]: commander,
703
730
  [AGENT_NAMES.PLANNER]: planner,
704
731
  [AGENT_NAMES.WORKER]: worker,
705
732
  [AGENT_NAMES.REVIEWER]: reviewer
@@ -13200,7 +13227,7 @@ Never claim completion without proof.
13200
13227
  });
13201
13228
 
13202
13229
  // src/tools/slashCommand.ts
13203
- var COMMANDER_SYSTEM_PROMPT = orchestrator.systemPrompt;
13230
+ var COMMANDER_SYSTEM_PROMPT = commander.systemPrompt;
13204
13231
  var MISSION_MODE_TEMPLATE = `${COMMANDER_SYSTEM_PROMPT}
13205
13232
 
13206
13233
  <mission>
@@ -13211,7 +13238,7 @@ $ARGUMENTS
13211
13238
  <execution_rules>
13212
13239
  1. Complete this mission without user intervention
13213
13240
  2. Use your full capabilities: research, implement, verify
13214
- 3. Output "${MISSION.COMPLETE}" when done
13241
+ 3. Output "${MISSION_SEAL.PATTERN}" when done
13215
13242
  </execution_rules>
13216
13243
  </mission>`;
13217
13244
  var COMMANDS = {
@@ -13249,7 +13276,7 @@ var COMMANDS = {
13249
13276
 
13250
13277
  | Agent | Role | Capabilities |
13251
13278
  |-------|------|--------------|
13252
- | **${AGENT_NAMES.COMMANDER}** \u{1F3AF} | Master Orchestrator | Autonomous mission control, parallel task coordination, never stops until \u2705 MISSION COMPLETE |
13279
+ | **${AGENT_NAMES.COMMANDER}** \u{1F3AF} | Master Orchestrator | Autonomous mission control, parallel task coordination, never stops until ${MISSION_SEAL.PATTERN} |
13253
13280
  | **${AGENT_NAMES.PLANNER}** \u{1F4CB} | Strategic Planner | Task decomposition, research, caching docs, dependency analysis |
13254
13281
  | **${AGENT_NAMES.WORKER}** \u{1F528} | Implementation | Code, files, terminal, documentation lookup when needed |
13255
13282
  | **${AGENT_NAMES.REVIEWER}** \u2705 | Quality & Context | Verification, TODO updates, context management, auto-fix |
@@ -16751,6 +16778,310 @@ function cleanupSession(sessionID) {
16751
16778
  sessionStates.delete(sessionID);
16752
16779
  }
16753
16780
 
16781
+ // src/core/loop/mission-seal.ts
16782
+ import { existsSync as existsSync4, readFileSync, writeFileSync, unlinkSync } from "node:fs";
16783
+ import { join as join5 } from "node:path";
16784
+ var MISSION_SEAL_TAG = MISSION_SEAL.TAG;
16785
+ var SEAL_CONFIRMATION = MISSION_SEAL.CONFIRMATION;
16786
+ var SEAL_PATTERN = MISSION_SEAL.PATTERN;
16787
+ var SEAL_REGEX = new RegExp(
16788
+ `<${MISSION_SEAL.TAG}>\\s*${MISSION_SEAL.CONFIRMATION}\\s*</${MISSION_SEAL.TAG}>`,
16789
+ "i"
16790
+ );
16791
+ var STATE_FILE = MISSION_SEAL.STATE_FILE;
16792
+ var DEFAULT_MAX_ITERATIONS = MISSION_SEAL.DEFAULT_MAX_ITERATIONS;
16793
+ var DEFAULT_COUNTDOWN_SECONDS = MISSION_SEAL.DEFAULT_COUNTDOWN_SECONDS;
16794
+ function getStateFilePath(directory) {
16795
+ return join5(directory, PATHS.OPENCODE, STATE_FILE);
16796
+ }
16797
+ function readLoopState(directory) {
16798
+ const filePath = getStateFilePath(directory);
16799
+ if (!existsSync4(filePath)) {
16800
+ return null;
16801
+ }
16802
+ try {
16803
+ const content = readFileSync(filePath, "utf-8");
16804
+ return JSON.parse(content);
16805
+ } catch (error45) {
16806
+ log2(`[mission-seal] Failed to read state: ${error45}`);
16807
+ return null;
16808
+ }
16809
+ }
16810
+ function writeLoopState(directory, state2) {
16811
+ const filePath = getStateFilePath(directory);
16812
+ try {
16813
+ writeFileSync(filePath, JSON.stringify(state2, null, 2), "utf-8");
16814
+ return true;
16815
+ } catch (error45) {
16816
+ log2(`[mission-seal] Failed to write state: ${error45}`);
16817
+ return false;
16818
+ }
16819
+ }
16820
+ function clearLoopState(directory) {
16821
+ const filePath = getStateFilePath(directory);
16822
+ if (!existsSync4(filePath)) {
16823
+ return true;
16824
+ }
16825
+ try {
16826
+ unlinkSync(filePath);
16827
+ return true;
16828
+ } catch (error45) {
16829
+ log2(`[mission-seal] Failed to clear state: ${error45}`);
16830
+ return false;
16831
+ }
16832
+ }
16833
+ function incrementIteration(directory) {
16834
+ const state2 = readLoopState(directory);
16835
+ if (!state2) return null;
16836
+ state2.iteration += 1;
16837
+ state2.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
16838
+ if (writeLoopState(directory, state2)) {
16839
+ return state2;
16840
+ }
16841
+ return null;
16842
+ }
16843
+ function detectSealInText(text) {
16844
+ return SEAL_REGEX.test(text);
16845
+ }
16846
+ async function detectSealInSession(client, sessionID) {
16847
+ try {
16848
+ const response = await client.session.messages({ path: { id: sessionID } });
16849
+ const messages = response.data ?? [];
16850
+ const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
16851
+ const recentMessages = assistantMessages.slice(-3);
16852
+ for (const msg of recentMessages) {
16853
+ if (!msg.parts) continue;
16854
+ const textParts = msg.parts.filter(
16855
+ (p) => p.type === PART_TYPES.TEXT || p.type === PART_TYPES.REASONING
16856
+ );
16857
+ for (const part of textParts) {
16858
+ if (part.text && detectSealInText(part.text)) {
16859
+ return true;
16860
+ }
16861
+ }
16862
+ }
16863
+ return false;
16864
+ } catch (error45) {
16865
+ log2(`[mission-seal] Failed to check session messages: ${error45}`);
16866
+ return false;
16867
+ }
16868
+ }
16869
+ function isLoopActive(directory, sessionID) {
16870
+ const state2 = readLoopState(directory);
16871
+ return state2?.active === true && state2?.sessionID === sessionID;
16872
+ }
16873
+ function generateMissionContinuationPrompt(state2) {
16874
+ return `<mission_loop iteration="${state2.iteration}" max="${state2.maxIterations}">
16875
+ \u{1F4CB} **Mission Loop Active** - Iteration ${state2.iteration}/${state2.maxIterations}
16876
+
16877
+ Your previous iteration did not seal the mission. Continue working.
16878
+
16879
+ **RULES**:
16880
+ 1. Review your progress from the previous iteration
16881
+ 2. Continue from where you left off
16882
+ 3. Check TODO list for incomplete items
16883
+ 4. When ALL work is TRULY complete, output:
16884
+
16885
+ \`\`\`
16886
+ ${SEAL_PATTERN}
16887
+ \`\`\`
16888
+
16889
+ **IMPORTANT**:
16890
+ - Do NOT seal until the mission is genuinely complete
16891
+ - Verify all todos are marked [x] before sealing
16892
+ - Run tests/builds if applicable before sealing
16893
+
16894
+ **Original Task**:
16895
+ ${state2.prompt}
16896
+ </mission_loop>`;
16897
+ }
16898
+
16899
+ // src/core/loop/mission-seal-handler.ts
16900
+ var COUNTDOWN_SECONDS2 = 3;
16901
+ var TOAST_DURATION_MS2 = 1500;
16902
+ var MIN_TIME_BETWEEN_CHECKS_MS = 3e3;
16903
+ var sessionStates2 = /* @__PURE__ */ new Map();
16904
+ function getState3(sessionID) {
16905
+ let state2 = sessionStates2.get(sessionID);
16906
+ if (!state2) {
16907
+ state2 = {};
16908
+ sessionStates2.set(sessionID, state2);
16909
+ }
16910
+ return state2;
16911
+ }
16912
+ function cancelCountdown2(sessionID) {
16913
+ const state2 = sessionStates2.get(sessionID);
16914
+ if (state2?.countdownTimer) {
16915
+ clearTimeout(state2.countdownTimer);
16916
+ state2.countdownTimer = void 0;
16917
+ }
16918
+ }
16919
+ function hasRunningBackgroundTasks2(parentSessionID) {
16920
+ try {
16921
+ const manager = ParallelAgentManager.getInstance();
16922
+ const tasks = manager.getTasksByParent(parentSessionID);
16923
+ return tasks.some((t) => t.status === "running");
16924
+ } catch {
16925
+ return false;
16926
+ }
16927
+ }
16928
+ async function showCountdownToast2(client, seconds, iteration, maxIterations) {
16929
+ try {
16930
+ const tuiClient2 = client;
16931
+ if (tuiClient2.tui?.showToast) {
16932
+ await tuiClient2.tui.showToast({
16933
+ body: {
16934
+ title: "\u{1F504} Mission Loop",
16935
+ message: `Continuing in ${seconds}s... (iteration ${iteration}/${maxIterations})`,
16936
+ variant: "warning",
16937
+ duration: TOAST_DURATION_MS2
16938
+ }
16939
+ });
16940
+ }
16941
+ } catch {
16942
+ }
16943
+ }
16944
+ async function showSealedToast(client, state2) {
16945
+ try {
16946
+ const tuiClient2 = client;
16947
+ if (tuiClient2.tui?.showToast) {
16948
+ await tuiClient2.tui.showToast({
16949
+ body: {
16950
+ title: "\u{1F396}\uFE0F Mission Sealed!",
16951
+ message: `Completed after ${state2.iteration} iteration(s)`,
16952
+ variant: "success",
16953
+ duration: 5e3
16954
+ }
16955
+ });
16956
+ }
16957
+ } catch {
16958
+ }
16959
+ }
16960
+ async function showMaxIterationsToast(client, state2) {
16961
+ try {
16962
+ const tuiClient2 = client;
16963
+ if (tuiClient2.tui?.showToast) {
16964
+ await tuiClient2.tui.showToast({
16965
+ body: {
16966
+ title: "\u26A0\uFE0F Mission Loop Stopped",
16967
+ message: `Max iterations (${state2.maxIterations}) reached`,
16968
+ variant: "warning",
16969
+ duration: 5e3
16970
+ }
16971
+ });
16972
+ }
16973
+ } catch {
16974
+ }
16975
+ }
16976
+ async function injectContinuation2(client, directory, sessionID, loopState) {
16977
+ const handlerState = getState3(sessionID);
16978
+ if (handlerState.isAborting) {
16979
+ log2("[mission-seal-handler] Skipped: user is aborting");
16980
+ return;
16981
+ }
16982
+ if (hasRunningBackgroundTasks2(sessionID)) {
16983
+ log2("[mission-seal-handler] Skipped: background tasks running");
16984
+ return;
16985
+ }
16986
+ if (isSessionRecovering(sessionID)) {
16987
+ log2("[mission-seal-handler] Skipped: session recovering");
16988
+ return;
16989
+ }
16990
+ const sealDetected = await detectSealInSession(client, sessionID);
16991
+ if (sealDetected) {
16992
+ log2("[mission-seal-handler] Seal detected before injection, completing");
16993
+ await handleSealDetected(client, directory, loopState);
16994
+ return;
16995
+ }
16996
+ const prompt = generateMissionContinuationPrompt(loopState);
16997
+ try {
16998
+ await client.session.prompt({
16999
+ path: { id: sessionID },
17000
+ body: {
17001
+ parts: [{ type: PART_TYPES.TEXT, text: prompt }]
17002
+ }
17003
+ });
17004
+ log2("[mission-seal-handler] Continuation injected", {
17005
+ sessionID,
17006
+ iteration: loopState.iteration
17007
+ });
17008
+ } catch (error45) {
17009
+ log2(`[mission-seal-handler] Failed to inject: ${error45}`);
17010
+ }
17011
+ }
17012
+ async function handleSealDetected(client, directory, loopState) {
17013
+ clearLoopState(directory);
17014
+ await showSealedToast(client, loopState);
17015
+ log2("[mission-seal-handler] Mission sealed!", {
17016
+ sessionID: loopState.sessionID,
17017
+ iterations: loopState.iteration
17018
+ });
17019
+ }
17020
+ async function handleMaxIterations(client, directory, loopState) {
17021
+ clearLoopState(directory);
17022
+ await showMaxIterationsToast(client, loopState);
17023
+ log2("[mission-seal-handler] Max iterations reached", {
17024
+ sessionID: loopState.sessionID,
17025
+ iterations: loopState.iteration,
17026
+ max: loopState.maxIterations
17027
+ });
17028
+ }
17029
+ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID) {
17030
+ const handlerState = getState3(sessionID);
17031
+ const now = Date.now();
17032
+ if (handlerState.lastCheckTime && now - handlerState.lastCheckTime < MIN_TIME_BETWEEN_CHECKS_MS) {
17033
+ return;
17034
+ }
17035
+ handlerState.lastCheckTime = now;
17036
+ cancelCountdown2(sessionID);
17037
+ if (mainSessionID && sessionID !== mainSessionID) {
17038
+ return;
17039
+ }
17040
+ if (isSessionRecovering(sessionID)) {
17041
+ log2("[mission-seal-handler] Skipped: recovering");
17042
+ return;
17043
+ }
17044
+ if (hasRunningBackgroundTasks2(sessionID)) {
17045
+ log2("[mission-seal-handler] Skipped: background tasks");
17046
+ return;
17047
+ }
17048
+ const loopState = readLoopState(directory);
17049
+ if (!loopState || !loopState.active) {
17050
+ return;
17051
+ }
17052
+ if (loopState.sessionID !== sessionID) {
17053
+ return;
17054
+ }
17055
+ log2("[mission-seal-handler] Checking for seal", {
17056
+ sessionID,
17057
+ iteration: loopState.iteration
17058
+ });
17059
+ const sealDetected = await detectSealInSession(client, sessionID);
17060
+ if (sealDetected) {
17061
+ await handleSealDetected(client, directory, loopState);
17062
+ return;
17063
+ }
17064
+ if (loopState.iteration >= loopState.maxIterations) {
17065
+ await handleMaxIterations(client, directory, loopState);
17066
+ return;
17067
+ }
17068
+ const newState = incrementIteration(directory);
17069
+ if (!newState) {
17070
+ log2("[mission-seal-handler] Failed to increment iteration");
17071
+ return;
17072
+ }
17073
+ await showCountdownToast2(client, COUNTDOWN_SECONDS2, newState.iteration, newState.maxIterations);
17074
+ handlerState.countdownTimer = setTimeout(async () => {
17075
+ cancelCountdown2(sessionID);
17076
+ await injectContinuation2(client, directory, sessionID, newState);
17077
+ }, COUNTDOWN_SECONDS2 * 1e3);
17078
+ log2("[mission-seal-handler] Countdown started", {
17079
+ sessionID,
17080
+ iteration: newState.iteration,
17081
+ seconds: COUNTDOWN_SECONDS2
17082
+ });
17083
+ }
17084
+
16754
17085
  // src/core/progress/store.ts
16755
17086
  var progressHistory = /* @__PURE__ */ new Map();
16756
17087
  var sessionStartTimes = /* @__PURE__ */ new Map();
@@ -16863,7 +17194,7 @@ You are ONLY done when:
16863
17194
  - All todos are marked complete or cancelled
16864
17195
  - All features are implemented and tested
16865
17196
  - Final verification passes
16866
- Then output: \u2705 MISSION COMPLETE
17197
+ Then output: ${MISSION_SEAL.PATTERN}
16867
17198
  </completion_criteria>
16868
17199
  </auto_continue>`;
16869
17200
  var OrchestratorPlugin = async (input) => {
@@ -17041,12 +17372,27 @@ var OrchestratorPlugin = async (input) => {
17041
17372
  if (sessionID) {
17042
17373
  const isMainSession = sessions.has(sessionID);
17043
17374
  if (isMainSession) {
17044
- setTimeout(() => {
17375
+ setTimeout(async () => {
17045
17376
  const session = sessions.get(sessionID);
17046
17377
  if (session?.active) {
17047
- handleSessionIdle(client, sessionID, sessionID).catch((err) => {
17048
- log2("[index.ts] todo-continuation error", err);
17049
- });
17378
+ if (isLoopActive(directory, sessionID)) {
17379
+ await handleMissionSealIdle(
17380
+ client,
17381
+ directory,
17382
+ sessionID,
17383
+ sessionID
17384
+ ).catch((err) => {
17385
+ log2("[index.ts] mission-seal-handler error", err);
17386
+ });
17387
+ } else {
17388
+ await handleSessionIdle(
17389
+ client,
17390
+ sessionID,
17391
+ sessionID
17392
+ ).catch((err) => {
17393
+ log2("[index.ts] todo-continuation error", err);
17394
+ });
17395
+ }
17050
17396
  }
17051
17397
  }, 500);
17052
17398
  }
@@ -17205,7 +17551,7 @@ Anomaly count: ${stateSession.anomalyCount}
17205
17551
  // -----------------------------------------------------------------
17206
17552
  // assistant.done hook - runs when the LLM finishes responding
17207
17553
  // This is the heart of the "relentless loop" - we keep pushing it
17208
- // to continue until we see MISSION COMPLETE or hit the limit
17554
+ // to continue until we see <mission_seal>SEALED</mission_seal> or hit the limit
17209
17555
  // -----------------------------------------------------------------
17210
17556
  "assistant.done": async (assistantInput, assistantOutput) => {
17211
17557
  const sessionID = assistantInput.sessionID;
@@ -17245,10 +17591,12 @@ Anomaly count: ${stateSession.anomalyCount}
17245
17591
  if (stateSession && stateSession.anomalyCount > 0) {
17246
17592
  stateSession.anomalyCount = 0;
17247
17593
  }
17248
- if (textContent.includes(MISSION.COMPLETE) || textContent.includes(MISSION.COMPLETE_TEXT)) {
17594
+ if (detectSealInText(textContent)) {
17249
17595
  session.active = false;
17250
17596
  state.missionActive = false;
17251
- presets.missionComplete("Mission completed successfully");
17597
+ clearLoopState(directory);
17598
+ presets.missionComplete("\u{1F396}\uFE0F Mission Sealed - Explicit completion confirmed");
17599
+ log2("[index.ts] Mission sealed detected", { sessionID });
17252
17600
  clearSession(sessionID);
17253
17601
  sessions.delete(sessionID);
17254
17602
  state.sessions.delete(sessionID);
@@ -69,11 +69,38 @@ export declare const TOOL_NAMES: {
69
69
  readonly CALL_AGENT: "call_agent";
70
70
  readonly SLASHCOMMAND: "slashcommand";
71
71
  };
72
+ export declare const MISSION_SEAL: {
73
+ /** XML tag name for mission seal */
74
+ readonly TAG: "mission_seal";
75
+ /** Confirmation value inside tag */
76
+ readonly CONFIRMATION: "SEALED";
77
+ /** Full seal pattern: <mission_seal>SEALED</mission_seal> */
78
+ readonly PATTERN: "<mission_seal>SEALED</mission_seal>";
79
+ /** Default max loop iterations */
80
+ readonly DEFAULT_MAX_ITERATIONS: 20;
81
+ /** Default countdown seconds before continue */
82
+ readonly DEFAULT_COUNTDOWN_SECONDS: 3;
83
+ /** Loop state file name */
84
+ readonly STATE_FILE: "loop-state.json";
85
+ /** Stop command */
86
+ readonly STOP_COMMAND: "/stop";
87
+ /** Cancel command */
88
+ readonly CANCEL_COMMAND: "/cancel";
89
+ };
90
+ /** @deprecated Use MISSION_SEAL instead */
72
91
  export declare const MISSION: {
73
- /** Mission completion marker (with emoji) */
74
- readonly COMPLETE: "βœ… MISSION COMPLETE";
75
- /** Mission completion marker (text only) */
76
- readonly COMPLETE_TEXT: "MISSION COMPLETE";
92
+ /** XML tag name for mission seal */
93
+ readonly TAG: "mission_seal";
94
+ /** Confirmation value inside tag */
95
+ readonly CONFIRMATION: "SEALED";
96
+ /** Full seal pattern: <mission_seal>SEALED</mission_seal> */
97
+ readonly PATTERN: "<mission_seal>SEALED</mission_seal>";
98
+ /** Default max loop iterations */
99
+ readonly DEFAULT_MAX_ITERATIONS: 20;
100
+ /** Default countdown seconds before continue */
101
+ readonly DEFAULT_COUNTDOWN_SECONDS: 3;
102
+ /** Loop state file name */
103
+ readonly STATE_FILE: "loop-state.json";
77
104
  /** Stop command */
78
105
  readonly STOP_COMMAND: "/stop";
79
106
  /** Cancel command */
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "opencode-orchestrator",
3
3
  "displayName": "OpenCode Orchestrator",
4
4
  "description": "Distributed Cognitive Architecture for OpenCode. Turns simple prompts into specialized multi-agent workflows (Planner, Coder, Reviewer).",
5
- "version": "0.7.0",
5
+ "version": "0.8.0",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {