oh-my-opencode-slim 2.2.0 → 2.2.2

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/dist/index.js CHANGED
@@ -18381,12 +18381,6 @@ var CUSTOM_SKILLS = [
18381
18381
  allowedAgents: ["orchestrator"],
18382
18382
  sourcePath: "src/skills/oh-my-opencode-slim"
18383
18383
  },
18384
- {
18385
- name: "release-smoke-test",
18386
- description: "Validate packed release candidates and bugfixes before public publish",
18387
- allowedAgents: ["orchestrator"],
18388
- sourcePath: "src/skills/release-smoke-test"
18389
- },
18390
18384
  {
18391
18385
  name: "worktrees",
18392
18386
  description: "Manage Git worktrees as OMO safe isolated coding lanes for complex/risky/parallel work",
@@ -18502,7 +18496,7 @@ var DEFAULT_MODELS = {
18502
18496
  var POLL_INTERVAL_BACKGROUND_MS = 2000;
18503
18497
  var MAX_POLL_TIME_MS = 5 * 60 * 1000;
18504
18498
  var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
18505
- var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
18499
+ var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: First choose the lightest workflow that fits the work. If direct execution is justified, complete it and verify proportionately. Otherwise: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
18506
18500
  function formatSystemReminder(text) {
18507
18501
  return `<system-reminder>
18508
18502
  ${text}
@@ -19257,7 +19251,8 @@ var AGENT_DESCRIPTIONS = {
19257
19251
  - Permissions: read_files
19258
19252
  - Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
19259
19253
  - Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
19260
- - **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • When a workflow calls for a **reviewer** subagent • Code needs simplification or YAGNI scrutiny
19254
+ - **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • Code needs simplification or YAGNI scrutiny
19255
+ - **Review use:** Oracle is an escalation, not a default verification step. Request independent Oracle review only when its analysis is expected to materially reduce risk or uncertainty.
19261
19256
  - **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
19262
19257
  - **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
19263
19258
  designer: `@designer
@@ -19323,6 +19318,10 @@ function buildOrchestratorPrompt(disabledAgents) {
19323
19318
  return `<Role>
19324
19319
  You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
19325
19320
 
19321
+ For non-trivial coding work, identify separable lanes first and delegate bounded work to the appropriate specialist. Do not perform multi-step implementation serially when a suitable specialist is available.
19322
+
19323
+ Handle work directly only when it is one isolated, clear, low-risk action and delegation overhead exceeds doing it yourself.
19324
+
19326
19325
  Optimize for quality, speed, cost, and reliability by dispatching the right specialist lanes, tracking background task state, and integrating terminal results into one coherent outcome.
19327
19326
  You have perfect understanding of agent's context management, understand well the cost of building content and reusing context of existing agents when it's best or when it's best to spawn a new agent.
19328
19327
  </Role>
@@ -19343,12 +19342,17 @@ Evaluate approach by: quality, speed and cost.
19343
19342
  Choose the path that optimizes all four.
19344
19343
 
19345
19344
  ## 3. Delegation Check
19346
- Review available agents and lane rules.
19345
+ Review available agents and lane rules. Before beginning non-trivial work, identify which parts can proceed independently.
19346
+
19347
+ **Routing threshold:**
19348
+ - Handle directly only for one isolated, clear, low-risk action where delegation would cost more than execution.
19349
+ - For multi-step implementation, broad discovery, external research, visual work, or complex debugging, delegate to the suitable specialist.
19350
+ - If two or more parts can proceed independently, dispatch them in parallel before starting dependent work.
19351
+ - Do not delegate merely because an agent exists. Do not keep substantive work entirely in the orchestrator merely because each individual step seems easy.
19347
19352
 
19348
19353
  **Dispatch efficiency:**
19349
19354
  - Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
19350
19355
  - Brief user on delegation goal before each call
19351
- - For trivial conversational answers or tiny mechanical edits, direct execution is allowed when scheduling overhead would clearly dominate
19352
19356
  - Record task IDs, state, and advisory ownership/dependency labels
19353
19357
  - Do not immediately wait after spawning independent background tasks unless the next step truly depends on their result
19354
19358
  - Reconcile results, resolve conflicts, and gate dependent lanes
@@ -19356,7 +19360,7 @@ Review available agents and lane rules.
19356
19360
  ${WRITABLE_FILE_OPERATIONS_RULES}
19357
19361
 
19358
19362
  ## 4. Plan and Parallelize
19359
- Build a short work graph before dispatching:
19363
+ When the routing threshold calls for delegation, build a short work graph before dispatching:
19360
19364
  - Independent lanes that can run now
19361
19365
  - Dependency-ordered lanes that must wait
19362
19366
  - Advisory ownership for write-capable lanes
@@ -19374,7 +19378,7 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
19374
19378
 
19375
19379
  ### Background Task Discipline
19376
19380
  - Prefer \`task(..., background: true)\` for delegated work that can run independently.
19377
- - Launch specialist agents in the background by default so the orchestrator stays unblocked and can reconcile results when they return.
19381
+ - For work already chosen for delegation, launch independent specialist lanes in the background so the orchestrator stays unblocked and can reconcile results when they return.
19378
19382
  - Track each task's specialist, objective, task/session ID, and file/topic ownership.
19379
19383
  - Continue orchestration only on non-overlapping work; otherwise briefly report what was launched and stop.
19380
19384
  - Before local edits or another writer task, compare against running task scopes.
@@ -19401,11 +19405,12 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
19401
19405
 
19402
19406
  ## 6. Verify
19403
19407
  - Define the observable success criteria from the user's request.
19404
- - Run the smallest relevant checks: targeted tests, typecheck, lint, build, or a manual behavior check.
19405
- - Inspect the changed diff and verify behavior; passing checks alone are not sufficient.
19406
- - If a check fails, diagnose, fix, and rerun the relevant verification.
19407
- - For risky or ambiguous changes, obtain an independent review when its value justifies the cost.
19408
- - Report verification performed and any remaining limitations.
19408
+ - Choose the minimum verification that produces meaningful evidence for the change's scope, risk, uncertainty, and potential impact.
19409
+ - Start with the narrowest relevant validation. Broaden verification only when integration scope, uncertainty, risk, or a failed focused check justifies it.
19410
+ - Do not run project-wide checks by habit or merely because files changed.
19411
+ - Do not treat verification as a fixed checklist; select evidence that can actually confirm the requested behavior.
19412
+ - Request independent review only when its expected risk reduction justifies its coordination cost.
19413
+ - Report what was verified and any material remaining uncertainty.
19409
19414
 
19410
19415
  </Workflow>
19411
19416
 
@@ -19421,6 +19426,8 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
19421
19426
  - Don't summarize what you did unless asked
19422
19427
  - Don't explain code unless asked
19423
19428
  - One-word answers are fine when appropriate
19429
+ - Default to the minimum response that fully resolves the user's request; expand only when detail is necessary or the user asks for it.
19430
+ - Do not restate the user's request or narrate routine work.
19424
19431
  - Brief delegation notices: "Checking docs via @librarian..." not "I'm going to delegate to @librarian because..."
19425
19432
 
19426
19433
  ## No Flattery
@@ -25082,7 +25089,7 @@ class BackgroundJobBoard {
25082
25089
  const timeouts = job.timeoutCount ?? 0;
25083
25090
  return errors >= threshold || timeouts >= threshold;
25084
25091
  }
25085
- formatForPrompt(parentSessionID, now = Date.now()) {
25092
+ formatForPrompt(parentSessionID, _now) {
25086
25093
  const active = this.list(parentSessionID).filter((job) => job.state === "running" || job.terminalUnreconciled);
25087
25094
  const reusable = this.list(parentSessionID).filter(isReusable);
25088
25095
  if (active.length === 0 && reusable.length === 0)
@@ -25096,7 +25103,7 @@ class BackgroundJobBoard {
25096
25103
  "Cancelled or errored sessions are not reusable.",
25097
25104
  "",
25098
25105
  "#### Active / Unreconciled",
25099
- ...active.length > 0 ? active.map((job) => formatJob(job, now)) : ["- none"],
25106
+ ...active.length > 0 ? active.map(formatJob) : ["- none"],
25100
25107
  "",
25101
25108
  "#### Reusable Sessions",
25102
25109
  ...reusable.length > 0 ? reusable.map((job) => this.formatReusableJob(job)) : ["- none"]
@@ -25173,11 +25180,10 @@ function formatContextFiles(files, maxFiles) {
25173
25180
  function normalizeWhitespace(value) {
25174
25181
  return value.replace(/\s+/g, " ").trim();
25175
25182
  }
25176
- function formatJob(job, now = Date.now()) {
25177
- const ageMs = now - job.lastLaunchedAt;
25183
+ function formatJob(job) {
25178
25184
  const isResume = job.lastLaunchedAt !== job.launchedAt;
25179
- const ageLabel = job.state === "running" && ageMs < 30000 ? ` [${isResume ? "resumed" : "just launched"}, ${Math.floor(ageMs / 1000)}s ago]` : "";
25180
- const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.statusUncertain ? `${job.state}, status uncertain` : job.timedOut ? `${job.state}, timed out` : `${job.state}${ageLabel}`;
25185
+ const displayState = job.state === "running" && isResume ? "running [resumed]" : job.state;
25186
+ const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.statusUncertain ? `${job.state}, status uncertain` : job.timedOut ? `${job.state}, timed out` : displayState;
25181
25187
  const lines = [
25182
25188
  `- ${promptSafe(job.alias)} / ${promptSafe(job.taskID)} / ${promptSafe(job.agent)} / ${promptSafe(status)}`,
25183
25189
  ` Objective: ${promptSafe(job.objective || job.description)}`
@@ -25577,6 +25583,15 @@ function isMessageWithParts(message) {
25577
25583
  function isUserMessageWithParts(message) {
25578
25584
  return isMessageWithParts(message) && message.info.role === "user";
25579
25585
  }
25586
+ function findLatestUserMessage(messages) {
25587
+ for (let index = messages.length - 1;index >= 0; index--) {
25588
+ const message = messages[index];
25589
+ if (isUserMessageWithParts(message)) {
25590
+ return message;
25591
+ }
25592
+ }
25593
+ return;
25594
+ }
25580
25595
 
25581
25596
  // src/hooks/filter-available-skills/index.ts
25582
25597
  var AVAILABLE_SKILLS_BLOCK_REGEX = /<available_skills>\s*([\s\S]*?)\s*<\/available_skills>/g;
@@ -26391,33 +26406,19 @@ function createLoopCommandHook() {
26391
26406
  }
26392
26407
  // src/hooks/phase-reminder/index.ts
26393
26408
  var PHASE_REMINDER_METADATA_KEY = "oh-my-opencode-slim.phaseReminder";
26394
- function createPhaseReminderHook(coordinator) {
26409
+ function hasPhaseReminder(part) {
26410
+ return part.synthetic === true && isRecord2(part.metadata) && part.metadata[PHASE_REMINDER_METADATA_KEY] === true;
26411
+ }
26412
+ function createPhaseReminderHook(options = {}) {
26395
26413
  return {
26396
26414
  "experimental.chat.messages.transform": async (_input, output) => {
26397
26415
  const messages = Array.isArray(output.messages) ? output.messages : [];
26398
- if (messages.length === 0) {
26399
- return;
26400
- }
26401
- let lastUserMessageIndex = -1;
26402
- for (let i = messages.length - 1;i >= 0; i--) {
26403
- if (isUserMessageWithParts(messages[i])) {
26404
- lastUserMessageIndex = i;
26405
- break;
26406
- }
26407
- }
26408
- if (lastUserMessageIndex === -1) {
26416
+ const lastUserMessage = findLatestUserMessage(messages);
26417
+ if (!lastUserMessage) {
26409
26418
  return;
26410
26419
  }
26411
- const lastUserMessage = messages[lastUserMessageIndex];
26412
- if (!isUserMessageWithParts(lastUserMessage)) {
26413
- return;
26414
- }
26415
- const agent = lastUserMessage.info.agent;
26416
- if (agent && agent !== "orchestrator") {
26417
- return;
26418
- }
26419
- const sessionId = lastUserMessage?.info?.sessionID;
26420
- if (sessionId && coordinator?.hasPendingSession(sessionId)) {
26420
+ const { agent, sessionID } = lastUserMessage.info;
26421
+ if (agent !== "orchestrator" || !sessionID || options.shouldInject && !options.shouldInject(sessionID)) {
26421
26422
  return;
26422
26423
  }
26423
26424
  const textPartIndex = lastUserMessage.parts.findIndex((p) => p.type === "text" && p.text !== undefined);
@@ -26428,7 +26429,7 @@ function createPhaseReminderHook(coordinator) {
26428
26429
  if (isInternalInitiatorPart(originalPart)) {
26429
26430
  return;
26430
26431
  }
26431
- if (lastUserMessage.parts.some((part) => part.synthetic === true && isRecord2(part.metadata) && part.metadata[PHASE_REMINDER_METADATA_KEY] === true)) {
26432
+ if (lastUserMessage.parts.some(hasPhaseReminder)) {
26432
26433
  return;
26433
26434
  }
26434
26435
  lastUserMessage.parts.push({
@@ -26453,17 +26454,43 @@ function createPostFileToolNudgeHook(options = {}) {
26453
26454
  return;
26454
26455
  coordinator?.markPending(input.sessionID);
26455
26456
  },
26456
- "experimental.chat.system.transform": async (input, output) => {
26457
- if (!input.sessionID || !coordinator?.consumePending(input.sessionID)) {
26457
+ "experimental.chat.messages.transform": async (_input, output) => {
26458
+ if (!coordinator) {
26458
26459
  return;
26459
26460
  }
26460
- if (options.shouldInject && !options.shouldInject(input.sessionID)) {
26461
+ const messages = Array.isArray(output.messages) ? output.messages : [];
26462
+ const eligible = getEligibleMessage(findLatestUserMessage(messages));
26463
+ if (!eligible) {
26464
+ return;
26465
+ }
26466
+ const { message, sessionID } = eligible;
26467
+ const hasReminder = message.parts.some(hasPhaseReminder);
26468
+ if (options.shouldInject && !options.shouldInject(sessionID)) {
26461
26469
  return;
26462
26470
  }
26463
- output.system.push(PHASE_REMINDER);
26471
+ if (!coordinator.consumePending(sessionID))
26472
+ return;
26473
+ if (hasReminder)
26474
+ return;
26475
+ message.parts.push({
26476
+ type: "text",
26477
+ synthetic: true,
26478
+ text: PHASE_REMINDER,
26479
+ metadata: { [PHASE_REMINDER_METADATA_KEY]: true }
26480
+ });
26464
26481
  }
26465
26482
  };
26466
26483
  }
26484
+ function getEligibleMessage(message) {
26485
+ if (!isUserMessageWithParts(message) || !message.info.sessionID || message.info.agent !== "orchestrator") {
26486
+ return;
26487
+ }
26488
+ const textPart = message.parts.find((part) => part.type === "text" && part.text !== undefined);
26489
+ if (!textPart || isInternalInitiatorPart(textPart)) {
26490
+ return;
26491
+ }
26492
+ return { message, sessionID: message.info.sessionID };
26493
+ }
26467
26494
  // src/hooks/reflect/index.ts
26468
26495
  var COMMAND_NAME3 = "reflect";
26469
26496
  function activationPrompt3(focus, isSessionMode = false, lastN = 50) {
@@ -26524,7 +26551,6 @@ function createReflectCommandHook() {
26524
26551
  class SessionLifecycle {
26525
26552
  #cleanupCallbacks = [];
26526
26553
  #pendingSessionIds = new Set;
26527
- #everPendingSessionIds = new Set;
26528
26554
  #log;
26529
26555
  constructor(log2) {
26530
26556
  this.#log = log2;
@@ -26543,19 +26569,14 @@ class SessionLifecycle {
26543
26569
  }
26544
26570
  markPending(sessionId) {
26545
26571
  this.#pendingSessionIds.add(sessionId);
26546
- this.#everPendingSessionIds.add(sessionId);
26547
26572
  }
26548
26573
  consumePending(sessionId) {
26549
26574
  const had = this.#pendingSessionIds.has(sessionId);
26550
26575
  this.#pendingSessionIds.delete(sessionId);
26551
26576
  return had;
26552
26577
  }
26553
- hasPendingSession(sessionId) {
26554
- return this.#everPendingSessionIds.has(sessionId) && !this.#pendingSessionIds.has(sessionId);
26555
- }
26556
26578
  clearSession(sessionId) {
26557
26579
  this.#pendingSessionIds.delete(sessionId);
26558
- this.#everPendingSessionIds.delete(sessionId);
26559
26580
  }
26560
26581
  }
26561
26582
  // src/hooks/task-session-manager/pending-call-tracker.ts
@@ -33327,6 +33348,7 @@ class ZellijMultiplexer {
33327
33348
  this.firstPaneUsed = true;
33328
33349
  return { success: true, paneId: this.firstPaneId };
33329
33350
  }
33351
+ this.firstPaneUsed = true;
33330
33352
  }
33331
33353
  return await this.createPaneInAgentTab(zellij, sessionId, serverUrl, directory, description);
33332
33354
  } catch {
@@ -33456,13 +33478,12 @@ class ZellijMultiplexer {
33456
33478
  try {
33457
33479
  const existingTab = await this.findTabByName(zellij, "opencode-agents");
33458
33480
  if (existingTab) {
33459
- const firstPane = await this.getFirstPaneInTab(zellij, existingTab.tabId);
33481
+ const firstPane2 = await this.getFirstPaneInTab(zellij, existingTab.tabId);
33460
33482
  return {
33461
33483
  tabId: existingTab.tabId,
33462
- firstPaneId: firstPane || "terminal_0"
33484
+ firstPaneId: firstPane2
33463
33485
  };
33464
33486
  }
33465
- const beforePanes = await this.listPanes(zellij);
33466
33487
  const createProc = crossSpawn([zellij, "action", "new-tab", "--name", "opencode-agents"], { stdout: "pipe", stderr: "pipe" });
33467
33488
  const createExit = await createProc.exited;
33468
33489
  if (createExit !== 0)
@@ -33470,27 +33491,33 @@ class ZellijMultiplexer {
33470
33491
  const newTab = await this.findTabByName(zellij, "opencode-agents");
33471
33492
  if (!newTab)
33472
33493
  return null;
33473
- const afterPanes = await this.listPanes(zellij);
33474
- const newPane = afterPanes.find((p) => !beforePanes.includes(p));
33475
- return { tabId: newTab.tabId, firstPaneId: newPane || "terminal_0" };
33494
+ const firstPane = await this.getFirstPaneInTab(zellij, newTab.tabId);
33495
+ return { tabId: newTab.tabId, firstPaneId: firstPane };
33496
+ } catch {
33497
+ return null;
33498
+ }
33499
+ }
33500
+ async listPanesJson(zellij) {
33501
+ try {
33502
+ const proc = crossSpawn([zellij, "action", "list-panes", "--json", "--tab", "--all"], { stdout: "pipe", stderr: "pipe" });
33503
+ if (await proc.exited !== 0)
33504
+ return null;
33505
+ const stdout = await proc.stdout();
33506
+ return JSON.parse(stdout);
33476
33507
  } catch {
33477
33508
  return null;
33478
33509
  }
33479
33510
  }
33480
33511
  async getFirstPaneInTab(zellij, tabId) {
33481
- const originalTab = await this.getCurrentTabId(zellij);
33482
- await crossSpawn([zellij, "action", "go-to-tab-by-id", tabId], {
33483
- stdout: "ignore",
33484
- stderr: "ignore"
33485
- }).exited;
33486
- const panes = await this.listPanes(zellij);
33487
- if (originalTab) {
33488
- await crossSpawn([zellij, "action", "go-to-tab-by-id", String(originalTab)], {
33489
- stdout: "ignore",
33490
- stderr: "ignore"
33491
- }).exited;
33512
+ try {
33513
+ const panes = await this.listPanesJson(zellij);
33514
+ if (!panes)
33515
+ return null;
33516
+ const pane = panes.find((candidate) => !candidate.is_plugin && candidate.tab_id === Number(tabId));
33517
+ return pane ? `terminal_${pane.id}` : null;
33518
+ } catch {
33519
+ return null;
33492
33520
  }
33493
- return panes[0] || null;
33494
33521
  }
33495
33522
  async findTabByName(zellij, name) {
33496
33523
  try {
@@ -33560,22 +33587,6 @@ class ZellijMultiplexer {
33560
33587
  return null;
33561
33588
  }
33562
33589
  }
33563
- async listPanes(zellij) {
33564
- try {
33565
- const proc = crossSpawn([zellij, "action", "list-panes"], {
33566
- stdout: "pipe",
33567
- stderr: "pipe"
33568
- });
33569
- const exitCode = await proc.exited;
33570
- if (exitCode !== 0)
33571
- return [];
33572
- const stdout = await proc.stdout();
33573
- return stdout.split(`
33574
- `).slice(1).map((line) => line.trim().split(/\s+/)[0]).filter((id) => id?.startsWith("terminal_"));
33575
- } catch {
33576
- return [];
33577
- }
33578
- }
33579
33590
  async closePane(paneId) {
33580
33591
  const zellij = await this.getBinary();
33581
33592
  return gracefulClosePane(zellij, paneId, {
@@ -33607,14 +33618,9 @@ class ZellijMultiplexer {
33607
33618
  }
33608
33619
  async findTabIdForPane(zellij, paneId) {
33609
33620
  try {
33610
- const proc = crossSpawn([zellij, "action", "list-panes", "--json", "--tab", "--all"], {
33611
- stdout: "pipe",
33612
- stderr: "pipe"
33613
- });
33614
- if (await proc.exited !== 0)
33621
+ const panes = await this.listPanesJson(zellij);
33622
+ if (!panes)
33615
33623
  return null;
33616
- const stdout = await proc.stdout();
33617
- const panes = JSON.parse(stdout);
33618
33624
  const normalizedPaneId = normalizePaneId(paneId);
33619
33625
  const pane = panes.find((candidate) => !candidate.is_plugin && String(candidate.id) === normalizedPaneId);
33620
33626
  return pane?.tab_id === undefined ? null : String(pane.tab_id);
@@ -39058,10 +39064,13 @@ var OhMyOpenCodeLite = async (ctx) => {
39058
39064
  }
39059
39065
  };
39060
39066
  };
39061
- phaseReminder = createPhaseReminderHook(sessionLifecycle);
39067
+ const shouldInjectOrchestratorReminder = (sessionID) => sessionAgentMap.get(sessionID) === "orchestrator";
39068
+ phaseReminder = createPhaseReminderHook({
39069
+ shouldInject: shouldInjectOrchestratorReminder
39070
+ });
39062
39071
  filterAvailableSkills = createFilterAvailableSkillsHook(ctx, config);
39063
39072
  postFileToolNudge = createPostFileToolNudgeHook({
39064
- shouldInject: (sessionID) => sessionAgentMap.get(sessionID) === "orchestrator",
39073
+ shouldInject: shouldInjectOrchestratorReminder,
39065
39074
  coordinator: sessionLifecycle
39066
39075
  });
39067
39076
  delegateTaskRetry = createDelegateTaskRetryHook(ctx);
@@ -39466,7 +39475,6 @@ var OhMyOpenCodeLite = async (ctx) => {
39466
39475
  ${output.system[0]}` : "");
39467
39476
  }
39468
39477
  }
39469
- await postFileToolNudge["experimental.chat.system.transform"](input, output);
39470
39478
  collapseSystemInPlace(output.system);
39471
39479
  },
39472
39480
  "experimental.chat.messages.transform": async (input, output) => {
@@ -39492,9 +39500,10 @@ ${output.system[0]}` : "");
39492
39500
  disabledAgents,
39493
39501
  log
39494
39502
  });
39503
+ await taskSessionManagerHook["experimental.chat.messages.transform"](input, typedOutput);
39504
+ await postFileToolNudge["experimental.chat.messages.transform"](input, typedOutput);
39495
39505
  await phaseReminder["experimental.chat.messages.transform"](input, typedOutput);
39496
39506
  await filterAvailableSkills["experimental.chat.messages.transform"](input, typedOutput);
39497
- await taskSessionManagerHook["experimental.chat.messages.transform"](input, typedOutput);
39498
39507
  },
39499
39508
  "tool.execute.after": async (input, output) => {
39500
39509
  await postFileToolNudgeAfter(input, output);
@@ -32,11 +32,11 @@ export declare class ZellijMultiplexer implements Multiplexer {
32
32
  private createPaneInAgentTab;
33
33
  private runInPane;
34
34
  private ensureAgentTab;
35
+ private listPanesJson;
35
36
  private getFirstPaneInTab;
36
37
  private findTabByName;
37
38
  private findTabByNameText;
38
39
  private getCurrentTabId;
39
- private listPanes;
40
40
  closePane(paneId: string): Promise<boolean>;
41
41
  applyLayout(_layout: MultiplexerLayout, _mainPaneSize: number): Promise<void>;
42
42
  private directionArgs;
package/dist/tui.js CHANGED
@@ -130,7 +130,7 @@ var DEFAULT_MODELS = {
130
130
  var POLL_INTERVAL_BACKGROUND_MS = 2000;
131
131
  var MAX_POLL_TIME_MS = 5 * 60 * 1000;
132
132
  var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
133
- var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
133
+ var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: First choose the lightest workflow that fits the work. If direct execution is justified, complete it and verify proportionately. Otherwise: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
134
134
  function formatSystemReminder(text) {
135
135
  return `<system-reminder>
136
136
  ${text}
@@ -582,12 +582,6 @@ var CUSTOM_SKILLS = [
582
582
  allowedAgents: ["orchestrator"],
583
583
  sourcePath: "src/skills/oh-my-opencode-slim"
584
584
  },
585
- {
586
- name: "release-smoke-test",
587
- description: "Validate packed release candidates and bugfixes before public publish",
588
- allowedAgents: ["orchestrator"],
589
- sourcePath: "src/skills/release-smoke-test"
590
- },
591
585
  {
592
586
  name: "worktrees",
593
587
  description: "Manage Git worktrees as OMO safe isolated coding lanes for complex/risky/parallel work",
@@ -95,7 +95,7 @@ export declare class BackgroundJobBoard implements BackgroundJobStore {
95
95
  hasRunning(parentSessionID: string): boolean;
96
96
  hasTerminalUnreconciled(parentSessionID: string): boolean;
97
97
  hasConvergenceSignals(taskID: string, threshold?: number): boolean;
98
- formatForPrompt(parentSessionID: string, now?: number): string | undefined;
98
+ formatForPrompt(parentSessionID: string, _now?: number): string | undefined;
99
99
  clearParent(parentSessionID: string): void;
100
100
  drop(taskID: string): void;
101
101
  deferIfRunning(_sessionId: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-slim",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "Lightweight agent orchestration plugin for OpenCode - a slimmed-down fork of oh-my-opencode",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,6 @@
23
23
  | `deepwork/` | Orchestrator-only | Heavy coding sessions, multi-phase implementation, and risky refactors |
24
24
  | `verification-planning/` | Orchestrator-only | Project-specific evidence planning and verification affordances before non-trivial implementation |
25
25
  | `reflect/` | Orchestrator-only | Learning from repeated work and suggesting reusable improvements |
26
- | `release-smoke-test/` | Orchestrator-only | Packed release-candidate and bugfix validation |
27
26
  | `worktrees/` | Orchestrator-only | Safe Git worktree lanes for parallel, risky, or isolated work |
28
27
  | `oh-my-opencode-slim/` | Orchestrator-only | Plugin configuration and self-improvement guidance |
29
28
 
@@ -60,7 +59,6 @@
60
59
  - `src/skills/deepwork/SKILL.md`
61
60
  - `src/skills/verification-planning/SKILL.md`
62
61
  - `src/skills/reflect/SKILL.md`
63
- - `src/skills/release-smoke-test/SKILL.md`
64
62
  - `src/skills/worktrees/SKILL.md`
65
63
  - `src/skills/oh-my-opencode-slim/SKILL.md`
66
64
  - `package.json` scripts (`verify:release`, `build`) rely on these assets to ensure install-time skill availability
@@ -98,6 +98,5 @@ what remains outside its reach.
98
98
  ## Scope
99
99
 
100
100
  Use this skill proportionately. Small mechanical changes can follow ordinary
101
- project checks directly. For release-specific validation, use
102
- `release-smoke-test`; for larger multi-phase work, let this skill establish the
103
- evidence path that later work follows.
101
+ project checks directly. For larger multi-phase work, let this skill establish
102
+ the evidence path that later work follows.