opencode-swarm 7.126.2 → 7.126.3

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.
@@ -35,7 +35,7 @@ If you are not sure whether you are touching one of these, you are touching one
35
35
  The full list of 12 invariants is in `AGENTS.md`. The four that have caused the most recent production regressions:
36
36
 
37
37
  1. **Plugin initialization is bounded and fail-open.** Every awaited operation on the plugin-init path must be wrapped in `withTimeout(...)` and degrade non-fatally on timeout. Issue #704 (v7.0.3) and the v7.3.3 git-hygiene regression both stem from violating this. The OpenCode plugin host silently drops a plugin whose entry never resolves; users see "no agents in TUI / GUI" with no error.
38
- - **Bounded is not free:** `withTimeout` only prevents an *unbounded* hang — the awaited work's latency still counts toward the ~400 ms repro-704 init deadline. Defer non-trivial init I/O via `queueMicrotask` when nothing downstream needs it before `server()` resolves.
38
+ - **Bounded is not free:** `withTimeout` only prevents an *unbounded* hang — the awaited work's latency still counts toward the ~400 ms repro-704 init deadline. Register non-trivial init I/O in the wrapper-owned post-resolution task queue when nothing downstream needs it before `server()` resolves. Do not use `queueMicrotask` inside the initializer: it can run during a later `await` while `server()` is still unresolved.
39
39
  2. **Subprocesses are bounded, non-interactive, and killable.** Every `bunSpawn(['<bin>', ...])` call must pass `cwd`, `stdin: 'ignore'` (unless intentionally interactive), `timeout: <ms>`, bounded stdio, and call `proc.kill()` in a `finally`. An outer `withTimeout` is not enough — it lets the awaiter proceed but does not abort the child.
40
40
  3. **Runtime portability — Node-ESM-loadable + v1 plugin shape.** No top-level `bun:` imports in `dist/index.js`. Default export is `{ id, server }`. All `Bun.*` calls go through `src/utils/bun-compat.ts`. v6.86.8 / v6.86.9 are the cautionary tales.
41
41
  4. **Test mock isolation.** `mock.module(...)` leaks across files in Bun's shared test-runner process. Prefer, in order: (a) `_test_exports` for pure function testing with zero mocks, (b) `_internals` dependency-injection seam for within-module mocking (see `src/utils/gitignore-warning.ts:_internals` and `src/hooks/diff-scope.ts:_internals`), (c) `mock.module` only when unavoidable. Restore in `afterEach`. The writing-tests skill covers all three tiers in detail; load it before modifying tests.
@@ -144,7 +144,7 @@ tree:
144
144
  tracked path. It creates an auditable, path-scoped stash and returns its
145
145
  recovery command. Do not issue `git stash` through shell. The controller never
146
146
  stashes untracked files; move or remove those manually, or abort the checkout.
147
- - **Check out the head branch locally.** Feedback verification reads the working-tree
147
+ - **Check out the head branch locally before dispatching feedback lanes.** Feedback verification reads the working-tree
148
148
  filesystem (`Read`/`Glob`/`Grep`), and fixes must land on the PR branch — without a
149
149
  checkout you would verify and patch the base branch's code instead. Record the
150
150
  exact `merge_base...head_ref` range for diff-scoped inspection.
@@ -159,6 +159,15 @@ tree:
159
159
  the upstream of an existing local branch with
160
160
  `git branch --set-upstream-to=<remote>/<remote-branch> <local-branch>`).
161
161
  Branch creation/tracking is blocked after the immutable head is bound.
162
+ - `gh pr checkout` is permitted only in its non-force, non-submodule form with
163
+ the PR number/URL and optional `--repo` or `--branch` flags. Never use
164
+ `--force`, `--recurse-submodules`, or detached checkout during this
165
+ transition.
166
+ - Before the first feedback verification dispatch binds the head, prove that
167
+ `git rev-parse HEAD` equals the authoritative full `pr_head_sha`,
168
+ `git status --porcelain` is empty, and the current branch tracks the intended
169
+ PR head remote/branch. A detached checkout is valid for review, not feedback
170
+ publication.
162
171
 
163
172
  When a verification lane result includes `output_ref`, treat `output` as a
164
173
  preview and call `retrieve_lane_output` before using it to classify, resolve,
@@ -733,8 +742,10 @@ the independently approved digest, the exact approved commit remains current,
733
742
  its bound upstream remote-tracking ref points to that exact commit, every
734
743
  feedback ID has exact-provenance evidence, and no PR-workflow lanes remain
735
744
  open. While the gate remains active, the runtime replaces architect
736
- final-response text with a mechanical blocked notice and re-wakes an idle
737
- parent session.
745
+ final-response text with a mechanical blocked notice and normally re-wakes an
746
+ idle parent session. A user interruption pauses automatic wakes until a later
747
+ explicit user turn settles; the durable gate remains available to continue or
748
+ abort.
738
749
 
739
750
  Report:
740
751
 
@@ -134,9 +134,26 @@ If scope cannot be determined, review the narrowest safe scope available and sta
134
134
 
135
135
  ### Pre-flight git ref availability
136
136
 
137
- Before launching explorers (Phase 3), confirm the PR branch refs are available:
138
- - If `head_ref` is a remote branch that is not checked out locally, fetch it via `git fetch origin <head_ref>`
139
- - **Check out the head branch locally.** Explorer agents read files from the working tree, not from git history — passing the commit range in the delegation prompt is not sufficient because `Read` / `Glob` / `Grep` tools operate on the filesystem. Without a checkout, explorers silently read the base branch's version of changed files and produce invalid candidates. **Before checking out, verify the working tree is clean (`git status --porcelain`). If tracked changes exist, call `prepare_pr_workflow_checkout` with every explicit dirty tracked path. It creates an auditable, path-scoped stash and returns its recovery command. Do not issue `git stash` through shell. The controller never stashes untracked files; move or remove those manually, or abort the checkout.**
137
+ Before launching explorers (Phase 3), perform this exact standalone sequence:
138
+
139
+ 1. Resolve and retain the authoritative full `pr_head_sha` from PR metadata.
140
+ 2. Verify the working tree is clean with `git status --porcelain`. If tracked
141
+ changes exist, call `prepare_pr_workflow_checkout` with every explicit dirty
142
+ tracked path. Do not issue `git stash` through shell. The controller never
143
+ stashes untracked files; move or remove those manually, or abort.
144
+ 3. Fetch the PR head as one standalone command, for example
145
+ `git fetch origin refs/pull/<N>/head`. Do not compose fetch and checkout.
146
+ 4. Prove the full commit exists locally with
147
+ `git cat-file -e <full_pr_head_sha>^{commit}`.
148
+ 5. Check out the exact PR filesystem with
149
+ `git switch --detach <full_pr_head_sha>`. Do not use `--track FETCH_HEAD`:
150
+ `FETCH_HEAD` is not a remote-tracking branch.
151
+ 6. Confirm `git rev-parse HEAD` equals the full `pr_head_sha`, bind that exact
152
+ head through the first PR-review controller call, and finish this before dispatching explorer lanes.
153
+
154
+ Explorer agents read files from the working tree, not from git history. Passing
155
+ the commit range in a prompt cannot substitute for this checkout because
156
+ `Read` / `Glob` / `Grep` operate on the filesystem.
140
157
  - Explicitly pass the verified merge-base range (`base_sha...pr_head_sha`) in every explorer delegation so explorers inspect exactly the controller-bound PR diff. Include `base_ref` only as the live ref used to recompute `base_sha`; do not substitute a two-dot branch-tip range.
141
158
 
142
159
  If refs cannot be fetched or checked out, state the limitation in the context pack.
@@ -1405,7 +1422,9 @@ the same exact
1405
1422
  `pr_head_sha`. The tool refuses to clear the session gate while required base,
1406
1423
  trigger, declared reviewer/critic, or open-lane obligations remain incomplete.
1407
1424
  While the gate remains active, the runtime replaces architect final-response
1408
- text with a mechanical blocked notice and re-wakes an idle parent session. Only
1425
+ text with a mechanical blocked notice and re-wakes an idle parent session. A
1426
+ user interruption pauses every automatic wake path until a later explicit user
1427
+ turn settles; the durable gate remains available to continue or abort. Only
1409
1428
  emit the final report after the completion tool confirms that the gate cleared.
1410
1429
 
1411
1430
  ## Aborting an unrecoverable review
@@ -1419,9 +1438,11 @@ the merge-base bind can never verify. In that state the response gate
1419
1438
  suspends further auto-resumes after a small number of consecutive
1420
1439
  unproductive wakes, and the only exits are:
1421
1440
 
1422
- 1. **Diagnose and retry as two separate standalone commands.** First run
1423
- `git fetch origin refs/pull/<N>/head:pr-<N>-head` (single command), then
1424
- `git checkout pr-<N>-head` (single command). Then recompute the exact
1441
+ 1. **Diagnose and retry the canonical standalone sequence.** Run
1442
+ `git fetch origin refs/pull/<N>/head`, verify
1443
+ `git cat-file -e <full_pr_head_sha>^{commit}`, then run
1444
+ `git switch --detach <full_pr_head_sha>`. Do not use `--track FETCH_HEAD`.
1445
+ Confirm `git rev-parse HEAD` equals the authoritative PR head, then recompute the exact
1425
1446
  merge base with `git merge-base -- <base_ref> <pr_head_sha>` (single
1426
1447
  command) and retry the `swarm-pr-review:base` dispatch with the exact
1427
1448
  `pr_head_sha`, `base_sha`, and `base_ref`.
@@ -89,7 +89,7 @@ export declare function buildWakeMessage(events: FormattedPrEvent[]): string;
89
89
  * clients that lack it. Bounded by withTimeout; returns false on any
90
90
  * failure or timeout. Never throws.
91
91
  */
92
- declare function sendWakePrompt(sessionID: string, events: FormattedPrEvent[]): Promise<boolean>;
92
+ declare function sendWakePrompt(sessionID: string, events: FormattedPrEvent[], messageID: string): Promise<boolean>;
93
93
  export declare const _internals: {
94
94
  sendWakePrompt: typeof sendWakePrompt;
95
95
  withTimeout: typeof withTimeout;
@@ -14,7 +14,7 @@ import {
14
14
  runCuratorInit,
15
15
  runCuratorPhase,
16
16
  writeCuratorSummary
17
- } from "./index-d88y17ht.js";
17
+ } from "./index-5n868tw8.js";
18
18
  import"./index-gxw20m1d.js";
19
19
  import"./index-3xd9a2g7.js";
20
20
  import"./index-kk1scggc.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  createCuratorLLMDelegate
4
- } from "./index-d88y17ht.js";
4
+ } from "./index-5n868tw8.js";
5
5
  import"./index-gxw20m1d.js";
6
6
  import"./index-3xd9a2g7.js";
7
7
  import"./index-kk1scggc.js";
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-z8ftpav0.js";
5
- import"./index-d88y17ht.js";
4
+ } from "./index-6t5sa6v0.js";
5
+ import"./index-5n868tw8.js";
6
6
  import"./index-gxw20m1d.js";
7
7
  import"./index-3xd9a2g7.js";
8
8
  import"./index-kk1scggc.js";
@@ -7,7 +7,7 @@ import {
7
7
  isHiveEligible,
8
8
  promoteFromSwarm,
9
9
  promoteToHive
10
- } from "./index-d88y17ht.js";
10
+ } from "./index-5n868tw8.js";
11
11
  import"./index-gxw20m1d.js";
12
12
  import"./index-3xd9a2g7.js";
13
13
  import"./index-kk1scggc.js";
@@ -940,8 +940,11 @@ async function bindPrWorkflowHead(directory, sessionID, prHeadSha) {
940
940
  const state = await requireAnyActiveState(directory, sessionID);
941
941
  const normalizedHead = normalizePrHeadSha(prHeadSha);
942
942
  assertCurrentCheckoutHead(directory, normalizedHead);
943
- if (state.mode === "PR_REVIEW")
944
- assertPrReviewCleanCheckout(directory);
943
+ if (!state.prHeadSha)
944
+ assertPrReviewCleanCheckout(directory, state.mode);
945
+ if (!state.prHeadSha && state.mode === "PR_FEEDBACK") {
946
+ assertPrFeedbackTrackingCheckout(directory, normalizedHead);
947
+ }
945
948
  if (state.prHeadSha && state.prHeadSha !== normalizedHead) {
946
949
  throw new Error(`BLOCKED: active ${state.mode} workflow is bound to PR head "${state.prHeadSha}"; received "${normalizedHead}"`);
947
950
  }
@@ -966,9 +969,19 @@ function assertCurrentCheckoutHead(directory, expectedHead) {
966
969
  }
967
970
  return normalizedExpected;
968
971
  }
969
- function assertPrReviewCleanCheckout(directory) {
972
+ function assertPrReviewCleanCheckout(directory, mode = "PR_REVIEW") {
970
973
  if (_test_exports.resolveIsWorkingTreeClean(directory) !== true) {
971
- throw new Error("BLOCKED: PR_REVIEW requires a clean index and working tree at the exact PR head");
974
+ throw new Error(`BLOCKED: ${mode} requires a clean index and working tree at the exact PR head`);
975
+ }
976
+ }
977
+ function assertPrFeedbackTrackingCheckout(directory, prHeadSha) {
978
+ const upstream = _test_exports.resolveCurrentUpstreamPushTarget(directory);
979
+ if (!upstream) {
980
+ throw new Error("BLOCKED: PR_FEEDBACK requires a current local branch bound to an exact remote name, remote branch ref, and remote-tracking ref before the first head bind; detached or non-tracking checkouts are not allowed");
981
+ }
982
+ const matchingRemoteRefs = _test_exports.resolveRemoteRefsContainingHead(directory, prHeadSha);
983
+ if (!matchingRemoteRefs?.includes(upstream.remoteTrackingRef)) {
984
+ throw new Error(`BLOCKED: PR_FEEDBACK upstream "${upstream.remoteTrackingRef}" must point to the exact intake PR head "${prHeadSha}" before the first head bind`);
972
985
  }
973
986
  }
974
987
  var _test_exports = {
@@ -12267,11 +12280,11 @@ var _internals15 = {
12267
12280
  }
12268
12281
  },
12269
12282
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
12270
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-qfh9xty4.js");
12283
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-jm9ehfkg.js");
12271
12284
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
12272
12285
  },
12273
12286
  checkHivePromotions: async (entries, knowledgeConfig, directory) => {
12274
- const { checkHivePromotions } = await import("./hive-promoter-ktt17fyf.js");
12287
+ const { checkHivePromotions } = await import("./hive-promoter-h9c4kyv0.js");
12275
12288
  return checkHivePromotions(entries, knowledgeConfig, directory);
12276
12289
  },
12277
12290
  applyProposalTriage: async (directory, triage) => {
@@ -20138,8 +20151,8 @@ var _internals28 = {
20138
20151
  loadCuratorDeps: async () => {
20139
20152
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
20140
20153
  import("./schema-fa033pqw.js"),
20141
- import("./curator-qfh9xty4.js"),
20142
- import("./curator-llm-factory-0rf29gfq.js")
20154
+ import("./curator-jm9ehfkg.js"),
20155
+ import("./curator-llm-factory-3cy0h9yw.js")
20143
20156
  ]);
20144
20157
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
20145
20158
  }
@@ -20638,7 +20651,7 @@ import { fileURLToPath } from "url";
20638
20651
  // package.json
20639
20652
  var package_default = {
20640
20653
  name: "opencode-swarm",
20641
- version: "7.126.2",
20654
+ version: "7.126.3",
20642
20655
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
20643
20656
  main: "dist/index.js",
20644
20657
  types: "dist/index.d.ts",
@@ -41188,7 +41201,7 @@ function buildDetailedHelp(commandName, entry) {
41188
41201
  async function handleHelpCommand(ctx) {
41189
41202
  const targetCommand = ctx.args.join(" ");
41190
41203
  if (!targetCommand) {
41191
- const { buildHelpText } = await import("./index-5nq8dp63.js");
41204
+ const { buildHelpText } = await import("./index-b16153py.js");
41192
41205
  return buildHelpText();
41193
41206
  }
41194
41207
  const tokens = targetCommand.split(/\s+/);
@@ -41197,7 +41210,7 @@ async function handleHelpCommand(ctx) {
41197
41210
  return _internals62.buildDetailedHelp(resolved.key, resolved.entry);
41198
41211
  }
41199
41212
  const similar = _internals62.findSimilarCommands(targetCommand);
41200
- const { buildHelpText: fullHelp } = await import("./index-5nq8dp63.js");
41213
+ const { buildHelpText: fullHelp } = await import("./index-b16153py.js");
41201
41214
  if (similar.length > 0) {
41202
41215
  return `Command '/swarm ${targetCommand}' not found.
41203
41216
 
@@ -41336,7 +41349,7 @@ var COMMAND_REGISTRY = {
41336
41349
  },
41337
41350
  "guardrail explain": {
41338
41351
  handler: async (ctx) => {
41339
- const { handleGuardrailExplain } = await import("./guardrail-explain-jsrjqps1.js");
41352
+ const { handleGuardrailExplain } = await import("./guardrail-explain-va0kj05m.js");
41340
41353
  return handleGuardrailExplain(ctx.directory, ctx.args);
41341
41354
  },
41342
41355
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -41346,7 +41359,7 @@ var COMMAND_REGISTRY = {
41346
41359
  },
41347
41360
  "guardrail-explain": {
41348
41361
  handler: async (ctx) => {
41349
- const { handleGuardrailExplain } = await import("./guardrail-explain-jsrjqps1.js");
41362
+ const { handleGuardrailExplain } = await import("./guardrail-explain-va0kj05m.js");
41350
41363
  return handleGuardrailExplain(ctx.directory, ctx.args);
41351
41364
  },
41352
41365
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -43140,7 +43153,7 @@ HARD CONSTRAINTS (apply regardless of skill load success):
43140
43153
  - Test execution, explorer lanes, reviewer dispatch, and critic challenge are all permitted within this mode
43141
43154
  - Quality is the only metric \u2014 there is no speed, efficiency, or time exception; time, tokens, and agent dispatches are irrelevant to correctness
43142
43155
  - FOLLOW THE SKILL EXACTLY: execute every phase of the loaded SKILL.md in order with no shortcuts, no phase-skipping, and no premature synthesis. If a required coverage phase cannot complete, apply the skill's coverage gate (retry or verified equivalent alternative). If the gap still cannot be closed, stop and surface the lane failure to the user as BLOCKED; do not produce a degraded review, partial verdict, or final synthesis.
43143
- - CHECK OUT THE PR BRANCH LOCALLY before launching explorer lanes: fetch the PR head ref if it is not present, verify the working tree is clean (git status --porcelain), and if tracked changes exist call \`prepare_pr_workflow_checkout\` with every explicit dirty tracked path before checkout. It returns an auditable stash OID and recovery command; it never stashes untracked files, which must be moved or removed manually. Do NOT run \`git stash\` through shell. Then check out the head branch. Explorers read the working-tree filesystem (Read/Glob/Grep), so without a checkout they read the base branch and produce invalid candidates. Always pass the base..head commit range in explorer delegations.
43156
+ - CHECK OUT THE EXACT PR HEAD LOCALLY before dispatching explorer lanes: resolve the authoritative full PR head SHA, verify the working tree is clean (git status --porcelain), and if tracked changes exist call \`prepare_pr_workflow_checkout\` with every explicit dirty tracked path before checkout. It returns an auditable stash OID and recovery command; it never stashes untracked files, which must be moved or removed manually. Do NOT run \`git stash\` through shell. Then use standalone commands: fetch the PR head, verify \`git cat-file -e <full_pr_head_sha>^{commit}\`, run \`git switch --detach <full_pr_head_sha>\`, confirm HEAD equals that SHA, and bind it through the PR-review controller. Do not use \`--track FETCH_HEAD\`. Explorers read the working-tree filesystem (Read/Glob/Grep), so without this checkout they read the base branch and produce invalid candidates. Always pass the base..head commit range in explorer delegations.
43144
43157
  - RUN ALL BASE LANES: the default PR_REVIEW path always launches exactly six repository-agnostic base check-type lanes from the skill. Use \`mode: "swarm-pr-review:base"\` and the exact six \`workflow_lane\` identifiers. The runtime rejects partial, duplicate, or mislabelled waves. Do not collapse, omit, or scale down the base lanes for a small, docs-only, or CI-only PR.
43145
43158
  - RETRY STRUCTURALLY: retry only failed base obligations in later \`swarm-pr-review:base\` async batches with the same exact \`pr_head_sha\`. Blocking \`dispatch_lanes\` and direct Task explorer/reviewer/critic dispatch are not provenance-equivalent and are rejected.
43146
43159
  - USE ASYNC DISPATCH WITHOUT IDLING: launch the base lanes with one \`dispatch_lanes_async\` call when available, record the \`batch_id\`, then keep doing non-dependent architect work while they run. Poll with \`collect_lane_results\` without \`wait\` (or \`wait: false\`) to process settled lanes and continue independent work between polls; use \`wait: true\` only as the final join when no independent work remains.
@@ -43159,7 +43172,7 @@ ACTION: Load skill ${bundledProjectSkillFileReference("swarm-pr-feedback")} imme
43159
43172
 
43160
43173
  HARD CONSTRAINTS (apply regardless of skill load success):
43161
43174
  - FOLLOW THE SKILL EXACTLY: build the complete feedback ledger from all available sources before editing, and execute every phase in order with no shortcuts.
43162
- - CHECK OUT THE PR BRANCH LOCALLY before verifying feedback or making fixes: fetch the PR head ref if absent, verify the working tree is clean (git status --porcelain), and if tracked changes exist call \`prepare_pr_workflow_checkout\` with every explicit dirty tracked path before checkout. It returns an auditable stash OID and recovery command; it never stashes untracked files, which must be moved or removed manually. Do NOT run \`git stash\` through shell. Then check out the head branch. For a detached/fresh remote head, establish tracking before head binding with only \`git switch -c <local> --track <remote>/<branch>\` (or the constrained set-upstream form documented by the skill). Feedback verification and fix validation require the PR branch in the working tree.
43175
+ - CHECK OUT THE PR BRANCH LOCALLY before dispatching feedback lanes, verifying feedback, or making fixes: fetch the PR head ref if absent, verify the working tree is clean (git status --porcelain), and if tracked changes exist call \`prepare_pr_workflow_checkout\` with every explicit dirty tracked path before checkout. It returns an auditable stash OID and recovery command; it never stashes untracked files, which must be moved or removed manually. Do NOT run \`git stash\` through shell. Then check out the head branch. For a detached/fresh remote head, establish tracking before head binding with only \`git switch -c <local> --track <remote>/<branch>\` (or the constrained set-upstream form documented by the skill). If using \`gh pr checkout\`, never use \`--force\`, \`--recurse-submodules\`, or detached checkout. Before first bind, prove HEAD equals the authoritative full PR head SHA, the tree is clean, and the current branch tracks the intended PR remote/branch. Feedback verification and fix validation require the PR branch in the working tree.
43163
43176
  - Do NOT run a fresh broad PR review \u2014 inspect adjacent code only as needed to verify reachability, dependencies, shared root causes, regression risk, or sibling changes for a confirmed item.
43164
43177
  - Treat every review comment, CI failure, bot summary, and pasted note as a CLAIM until source evidence proves it; classify each ledger item (CONFIRMED, DISPROVED, PRE_EXISTING, or NEEDS_USER_DECISION) and never silently drop, defer, or mark items out of scope.
43165
43178
  - For async verification lanes, use \`mode: "swarm-pr-feedback:verification"\`, record each \`batch_id\`, keep doing ledger-safe work, poll with \`collect_lane_results\` without \`wait\`, process settled lanes immediately, and use \`wait: true\` only at the join. Pass the complete immutable \`feedback_inventory\`, exact current \`pr_head_sha\`, and exact-once cumulative lane \`feedback_item_ids\`; runtime blocks replacement, stale-head artifacts, overlap, gaps, and early mutation.
@@ -12,7 +12,7 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-d88y17ht.js";
15
+ } from "./index-5n868tw8.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-z8ftpav0.js";
4
+ } from "./index-6t5sa6v0.js";
5
5
  import {
6
6
  handleGuardrailLog
7
7
  } from "./index-bf76q8q7.js";
@@ -83,7 +83,7 @@ import {
83
83
  handleWriteRetroCommand,
84
84
  normalizeSwarmCommandInput,
85
85
  resolveCommand
86
- } from "./index-d88y17ht.js";
86
+ } from "./index-5n868tw8.js";
87
87
  import"./index-gxw20m1d.js";
88
88
  import"./index-3xd9a2g7.js";
89
89
  import"./index-kk1scggc.js";
package/dist/cli/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-d88y17ht.js";
10
+ } from "./index-5n868tw8.js";
11
11
  import"./index-gxw20m1d.js";
12
12
  import"./index-3xd9a2g7.js";
13
13
  import"./index-kk1scggc.js";
@@ -21,8 +21,9 @@ declare function copyBundledDirectoryBoundedAsync(sourceDir: string, destDir: st
21
21
  * tree so architect MODE dispatch never collides with repository-owned skills
22
22
  * that happen to use the same slug.
23
23
  *
24
- * Async, bounded, and fail-open: safe to `await withTimeout(...)` on the
25
- * plugin-init path (AGENTS.md Invariant 1). Runs at plugin init so the
24
+ * Async, bounded, and fail-open: register `withTimeout(...)` in the
25
+ * wrapper-owned post-resolution task queue on the plugin-init path
26
+ * (AGENTS.md Invariant 1). Runs at plugin init so the
26
27
  * architect's very first auto-entered mode (e.g. SPECIFY on a fresh project) can
27
28
  * load its SKILL.md without a manual `/swarm` command or session restart; the
28
29
  * command path calls it again as a backstop for pre-existing projects.
@@ -6,7 +6,7 @@
6
6
  * - Calls cleanupOrphanedBranches(ctx.directory, []) at plugin init (no sessions active → all swarm-lane branches are orphans)
7
7
  * - Writes results to `<directory>/.swarm/advisories/init-orphan-recovery.json`
8
8
  * - Is wrapped in `withTimeout` so it never blocks plugin init
9
- * - Runs via `queueMicrotask` off the `server()` resolution path (precedent: repoGraphHook.init)
9
+ * - Runs from the wrapper-owned post-resolution queue after `server()` can settle (precedent: repoGraphHook.init)
10
10
  *
11
11
  * This module intentionally lives in `src/hooks/` so that `src/index.ts` can import
12
12
  * it without matching the forbidden `worktree/` or `merge-back/` patterns.
@@ -0,0 +1,31 @@
1
+ import { readPrWorkflowGateState } from './pr-workflow-gate.js';
2
+ export declare const _internals: {
3
+ readPrWorkflowGateState: typeof readPrWorkflowGateState;
4
+ };
5
+ /** Bound module state: every entry is keyed by project plus parent session. */
6
+ export declare const MAX_TRACKED_PR_WORKFLOW_WAKE_STATES = 200;
7
+ export declare const PLUGIN_WAKE_MARKER_TTL_MS = 60000;
8
+ type PausePhase = 'awaiting-idle' | 'paused' | 'resuming';
9
+ export interface PrWorkflowAutoWakeDecision {
10
+ sessionID?: string;
11
+ suppressWake: boolean;
12
+ }
13
+ /** Mark a plugin-authored prompt until its synthetic user event is observed. */
14
+ export declare function markPrWorkflowPluginWake(directory: string, sessionID: string): string;
15
+ /** Remove a marker only when the host definitively rejected the prompt. */
16
+ export declare function cancelPrWorkflowPluginWake(directory: string, sessionID: string, messageID: string): void;
17
+ export declare function isPrWorkflowAutoWakeSuppressed(directory: string, sessionID: string): boolean;
18
+ export declare function clearPrWorkflowAutoWakeState(directory: string, sessionID: string): void;
19
+ /**
20
+ * Observe host events that distinguish a user interruption from an ordinary
21
+ * idle boundary. The durable workflow gate remains intact; only automatic
22
+ * prompts pause. A later real user turn re-enables wakes after that turn's
23
+ * idle boundary.
24
+ */
25
+ export declare function observePrWorkflowAutoWakeEvent(directory: string, rawEvent: unknown): Promise<PrWorkflowAutoWakeDecision>;
26
+ export declare const _test_exports: {
27
+ reset(): void;
28
+ getPausePhase(directory: string, sessionID: string): PausePhase | undefined;
29
+ getPluginWakeMarkerCount(directory: string, sessionID: string, now?: number): number;
30
+ };
31
+ export {};
@@ -191,7 +191,7 @@ export declare function bindPrReviewBase(directory: string, sessionID: string, o
191
191
  /** Prove that caller-provided PR identity equals the actual checked-out commit. */
192
192
  export declare function assertCurrentCheckoutHead(directory: string, expectedHead: string): string;
193
193
  /** Prove that every PR-review lane reads the immutable checked-out PR tree. */
194
- export declare function assertPrReviewCleanCheckout(directory: string): void;
194
+ export declare function assertPrReviewCleanCheckout(directory: string, mode?: PrWorkflowMode): void;
195
195
  export declare function enforcePrWorkflowDispatchLanesAsync(directory: string, sessionID: string, toolName: string): Promise<PrWorkflowGateState | null>;
196
196
  export declare function enforcePrReviewBaseDimensions(directory: string, sessionID: string, lanes: readonly PrWorkflowLaneSpec[], options: {
197
197
  batchId: string;
@@ -1,3 +1,7 @@
1
+ import { readPrWorkflowGateState } from './pr-workflow-gate.js';
2
+ export declare const _internals: {
3
+ readPrWorkflowGateState: typeof readPrWorkflowGateState;
4
+ };
1
5
  /**
2
6
  * Maximum number of consecutive unproductive auto-resumes per gated session
3
7
  * before the response gate suspends further wakes. "Unproductive" means the
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Plugin } from '@opencode-ai/plugin';
2
+ import { createRepoGraphBuilderHook } from './hooks';
2
3
  /**
3
4
  * FIFO-cap a session-keyed Map to at most `max` entries, evicting oldest first.
4
5
  * Values tracked by these maps are plain data (timestamps/usage snapshots), never
@@ -6,6 +7,19 @@ import type { Plugin } from '@opencode-ai/plugin';
6
7
  * unit testing of the cap invariant; used by the heartbeat throttle path below.
7
8
  */
8
9
  export declare function capSessionMap<K, V>(map: Map<K, V>, max: number): void;
10
+ type PostResolutionTask = () => void | Promise<void>;
11
+ /**
12
+ * Start detached initialization work only after the plugin manifest promise can
13
+ * settle. A microtask queued from inside `initializeOpenCodeSwarm` is not truly
14
+ * deferred when that function still has later awaits: the microtask can start
15
+ * expensive filesystem work while `server()` remains unresolved (issue #704).
16
+ */
17
+ declare function schedulePostResolutionTasks(tasks: readonly PostResolutionTask[]): void;
18
+ export declare function overrideIndexInternalsForTest(overrides: {
19
+ createRepoGraphBuilderHook?: typeof createRepoGraphBuilderHook;
20
+ schedulePostResolutionTasks?: typeof schedulePostResolutionTasks;
21
+ }): () => void;
22
+ export declare function schedulePostResolutionTasksForTest(tasks: readonly PostResolutionTask[]): void;
9
23
  declare const _default: {
10
24
  id: "opencode-swarm";
11
25
  server: Plugin;