opencode-swarm 7.135.2 → 7.135.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.
- package/.opencode/skills/critic-gate/SKILL.md +10 -0
- package/dist/agents/index.d.ts +12 -0
- package/dist/cli/{config-doctor-pj3yvxdb.js → config-doctor-4nznqeca.js} +3 -2
- package/dist/cli/{core-4va9z2ng.js → core-4z1s2ak1.js} +3 -2
- package/dist/cli/{curation-policy-b2caf3v3.js → curation-policy-81m14519.js} +3 -3
- package/dist/cli/{curator-drift-2ta83hss.js → curator-drift-jpap6hv4.js} +2 -2
- package/dist/cli/{curator-r1s2mwf2.js → curator-e0z5gcww.js} +24 -23
- package/dist/cli/{curator-llm-factory-9983528d.js → curator-llm-factory-fem13y9n.js} +24 -23
- package/dist/cli/{dispatch-wtk6dxky.js → dispatch-b1fge4xk.js} +2 -2
- package/dist/cli/{evidence-summary-service-feby8ny0.js → evidence-summary-service-w006jnpg.js} +5 -5
- package/dist/cli/{gate-evidence-84b03mb4.js → gate-evidence-aenyz6vt.js} +2 -2
- package/dist/cli/{guardrail-explain-pwxvg5n0.js → guardrail-explain-wgaj23hd.js} +25 -24
- package/dist/cli/{guardrail-log-yzpz8b7t.js → guardrail-log-04p1z1vt.js} +5 -4
- package/dist/cli/{hive-promoter-586dhndj.js → hive-promoter-k345z42k.js} +24 -23
- package/dist/cli/{index-g3meqrsg.js → index-168phrs7.js} +12 -10
- package/dist/cli/{index-3m7kpnqf.js → index-30pg2rs3.js} +1 -1
- package/dist/cli/{index-b0eva00y.js → index-36v55ryg.js} +1 -1
- package/dist/cli/index-3jcyn8g6.js +1219 -0
- package/dist/cli/{index-hdy2nd5h.js → index-45t7w06b.js} +4 -4
- package/dist/cli/{index-bs4m85v1.js → index-5436jxnw.js} +2 -2
- package/dist/cli/{index-j92ser8n.js → index-a01r818w.js} +5 -3
- package/dist/cli/{index-hvrrq3f3.js → index-bcmrg4t4.js} +1 -1
- package/dist/cli/{index-d5psymdk.js → index-c9ddxv4k.js} +57 -8
- package/dist/cli/{index-7pnvf04s.js → index-cggqh2dz.js} +10 -10
- package/dist/cli/{index-340chr1e.js → index-dwargd10.js} +10105 -9998
- package/dist/cli/{index-ckdva4rs.js → index-f52jt0am.js} +5 -5
- package/dist/cli/{index-jgkjxpdh.js → index-gxxxmajn.js} +2 -2
- package/dist/cli/{index-2pxk6qg4.js → index-kb7qy7an.js} +4 -2
- package/dist/cli/{index-j0kte6gd.js → index-p5kr35wh.js} +8 -1210
- package/dist/cli/{index-02cqjna3.js → index-p9ngg568.js} +4 -4
- package/dist/cli/{index-8gw8p7yh.js → index-rv7s2k9y.js} +1 -1
- package/dist/cli/{index-3xbx305x.js → index-tcn457d5.js} +1 -1
- package/dist/cli/{index-9c3gf2wd.js → index-wygxzvtf.js} +6 -4
- package/dist/cli/{index-73dfyfhq.js → index-x20cgr2q.js} +1 -1
- package/dist/cli/{index-cwdy5vw9.js → index-y47crdg9.js} +30 -28
- package/dist/cli/{index-qqkw794p.js → index-yf30m841.js} +3 -3
- package/dist/cli/index.js +27 -25
- package/dist/cli/{knowledge-escalator-w7by1m8m.js → knowledge-escalator-42ecv7m3.js} +4 -4
- package/dist/cli/{knowledge-events-n8xxsay3.js → knowledge-events-zhna7v3g.js} +2 -2
- package/dist/cli/knowledge-link-mm1w967j.js +1 -1
- package/dist/cli/{knowledge-store-xzmvfnx3.js → knowledge-store-56jcfc5k.js} +2 -2
- package/dist/cli/{knowledge-validator-5q1amsq6.js → knowledge-validator-8zk0pnb6.js} +5 -5
- package/dist/cli/{pending-delegations-mt5gs1bt.js → pending-delegations-qajsxct0.js} +4 -4
- package/dist/cli/{pr-subscriptions-v5xd3j6d.js → pr-subscriptions-qhr41epq.js} +4 -4
- package/dist/cli/{scan-cursor-1q1zmt4b.js → scan-cursor-h3ndxd41.js} +3 -3
- package/dist/cli/{schema-8mtsfspm.js → schema-r6wmd7zp.js} +2 -1
- package/dist/cli/scope-persistence-h2fpgxww.js +2 -2
- package/dist/cli/{skill-generator-54xbjgak.js → skill-generator-12cftsx4.js} +6 -6
- package/dist/cli/{worktree-collision-ownership-15hymf1y.js → worktree-collision-ownership-13btcj9g.js} +5 -5
- package/dist/commands/approve-plan-critic.d.ts +21 -0
- package/dist/commands/registry.d.ts +8 -0
- package/dist/config/cache-paths.d.ts +48 -0
- package/dist/config/constants.d.ts +18 -0
- package/dist/config/host-path.d.ts +95 -0
- package/dist/config/lane-context.d.ts +117 -0
- package/dist/config/lane-permissions.d.ts +277 -0
- package/dist/config/schema.d.ts +10 -0
- package/dist/config/swarm-branch.d.ts +130 -0
- package/dist/hooks/delegation-gate.d.ts +42 -1
- package/dist/hooks/skill-propagation-gate.d.ts +10 -0
- package/dist/index.js +211 -199
- package/dist/memory/schema.d.ts +4 -4
- package/dist/tools/approve-plan-critic.d.ts +5 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +1 -1
- package/dist/cli/{index-bfd4xfpp.js → index-4qzeef9h.js} +3 -3
- package/dist/cli/{index-ryqnn3nv.js → index-mrtms113.js} +3 -3
- package/dist/cli/{index-m0ynxkaa.js → index-vm4xw9z3.js} +3 -3
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The swarm worktree BRANCH GRAMMAR — single source of truth for both building
|
|
3
|
+
* and recognising the branch names that identify a swarm-owned worktree.
|
|
4
|
+
*
|
|
5
|
+
* ## Why a grammar and not a prefix
|
|
6
|
+
*
|
|
7
|
+
* Lane detection (`src/config/lane-context.ts`) uses the branch name as its
|
|
8
|
+
* ownership signal because, unlike the worktree's path, it is invariant across
|
|
9
|
+
* all three provisioning layouts (default `.swarm-worktrees`, a configured
|
|
10
|
+
* `worktree.worktree_dir`, and the Windows path-budget fallback that relocates
|
|
11
|
+
* a lane to `<os.tmpdir()>/swwt/...`).
|
|
12
|
+
*
|
|
13
|
+
* Matching a bare `swarm/` PREFIX is not safe. A user running
|
|
14
|
+
* `git worktree add -b swarm/my-own-experiment ../scratch` would be classified
|
|
15
|
+
* as a lane, and their ordinary interactive session would then have
|
|
16
|
+
* `external_directory: { "*": "deny", ... }` injected. That is strictly worse
|
|
17
|
+
* than the hang this subsystem exists to fix, because the host's
|
|
18
|
+
* `Permission.ask` short-circuits on a deny before it ever creates a deferred:
|
|
19
|
+
*
|
|
20
|
+
* ```js
|
|
21
|
+
* // opencode 1.18.10, Permission.ask
|
|
22
|
+
* if (W.action === "deny") return yield* new U.DeniedError({ ... });
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* — so no prompt is raised and "Allow always" can never be reached. The user
|
|
26
|
+
* has no in-session recovery.
|
|
27
|
+
*
|
|
28
|
+
* The grammar below therefore matches the COMPLETE shape
|
|
29
|
+
* `makeWorktreeBranchName` emits, including a session segment constrained to
|
|
30
|
+
* OpenCode's `ses_`-prefixed identifier form. `tests/unit/config/swarm-branch.test.ts`
|
|
31
|
+
* holds a round-trip property test over the producer and a negative corpus of
|
|
32
|
+
* plausible human-authored branch names.
|
|
33
|
+
*
|
|
34
|
+
* @module config/swarm-branch
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* True when `sessionId` is a session identifier the lane grammar can encode.
|
|
38
|
+
*
|
|
39
|
+
* Tool arguments are LLM-supplied (`sessionID: z.string()`) and the host's own
|
|
40
|
+
* `SessionID` brand is only `isStartsWith("ses")`, so a value like `ses-run-1`
|
|
41
|
+
* passes the host but yields a branch the recogniser cannot match — a lane that
|
|
42
|
+
* silently skips permission scoping and hangs. Callers that accept a session id
|
|
43
|
+
* from outside should check this before provisioning.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isSwarmSessionId(sessionId: unknown): sessionId is string;
|
|
46
|
+
/**
|
|
47
|
+
* Builds the branch name for a swarm worktree.
|
|
48
|
+
*
|
|
49
|
+
* The ONLY producer of these names. `makeWorktreeBranchName` in
|
|
50
|
+
* `src/worktree/core.ts` delegates here so the producer and
|
|
51
|
+
* {@link matchSwarmLaneBranch} cannot drift.
|
|
52
|
+
*
|
|
53
|
+
* @param sessionId - Parent session identifier.
|
|
54
|
+
* @param id - Execution-unit identifier (task or lane id).
|
|
55
|
+
* @param purpose - Worktree purpose (e.g. `lane`).
|
|
56
|
+
* @param legacyLane - Use Lean Turbo's `swarm-lane/<sessionId>/<id>` style.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildSwarmBranchName(sessionId: string, id: string, purpose: string, legacyLane: boolean): string;
|
|
59
|
+
/**
|
|
60
|
+
* Recognises the DEFAULT lane PATH shape,
|
|
61
|
+
* `<base>/.swarm-worktrees/<sessionId>/<id>`.
|
|
62
|
+
*
|
|
63
|
+
* This is the fallback ownership signal for a worktree whose HEAD is detached
|
|
64
|
+
* or unreadable, so its branch cannot be consulted. It must be as tight as the
|
|
65
|
+
* branch grammar: matching "any path containing a `.swarm-worktrees` segment"
|
|
66
|
+
* captures a user's own `git worktree add -b my-feature ../.swarm-worktrees/manual-user-wt`,
|
|
67
|
+
* which then has an unrecoverable deny-by-default injected into an ordinary
|
|
68
|
+
* interactive session.
|
|
69
|
+
*
|
|
70
|
+
* `provisionWorktree` builds this path as
|
|
71
|
+
* `path.resolve(resolveWorktreeBaseDir(directory), sessionId, id)`, i.e. exactly
|
|
72
|
+
* two segments after the base, so the shape check requires exactly that — with
|
|
73
|
+
* the session segment held to the SAME `ses_…` constraint the branch grammar
|
|
74
|
+
* uses. The directory name comes from the same `SWARM_WORKTREE_DIR_NAME`
|
|
75
|
+
* constant `resolveWorktreeBaseDir` builds with, so the three definitions
|
|
76
|
+
* cannot drift.
|
|
77
|
+
*
|
|
78
|
+
* KNOWN RESIDUAL (accepted, not a defect to chase): a worktree the USER created
|
|
79
|
+
* at exactly `<base>/.swarm-worktrees/ses_<alnum>/<id>` on a non-swarm branch
|
|
80
|
+
* still classifies as a lane. Reaching it requires deliberately creating a
|
|
81
|
+
* directory literally named `ses_<alnum>` under a `.swarm-worktrees` base, and
|
|
82
|
+
* the same leniency is what keeps a REAL lane detected after someone checks out
|
|
83
|
+
* a different branch inside it. Narrowing further would trade a far more likely
|
|
84
|
+
* false negative (a real lane silently unscoped, i.e. the original hang) for a
|
|
85
|
+
* far less likely false positive.
|
|
86
|
+
*
|
|
87
|
+
* Note this recognises only the DEFAULT layout. A `worktree_dir` override or
|
|
88
|
+
* the Windows path-budget fallback produces a different path, and a lane in
|
|
89
|
+
* those layouts with a detached HEAD is a false NEGATIVE — no permission
|
|
90
|
+
* changes, i.e. today's behaviour. That is the safe direction.
|
|
91
|
+
*
|
|
92
|
+
* @param lanePath - An already-resolved absolute path.
|
|
93
|
+
*/
|
|
94
|
+
export declare function matchSwarmLanePath(lanePath: string): {
|
|
95
|
+
sessionId: string;
|
|
96
|
+
id: string;
|
|
97
|
+
} | undefined;
|
|
98
|
+
/** A branch name recognised as a swarm worktree lane. */
|
|
99
|
+
export interface SwarmLaneBranch {
|
|
100
|
+
/** Worktree purpose. `'lane'` for the legacy style, which encodes no purpose. */
|
|
101
|
+
purpose: string;
|
|
102
|
+
sessionId: string;
|
|
103
|
+
id: string;
|
|
104
|
+
style: 'purpose' | 'legacy-lane';
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Recognises a branch name produced by {@link buildSwarmBranchName}.
|
|
108
|
+
*
|
|
109
|
+
* Matches the complete grammar and nothing wider:
|
|
110
|
+
* - `swarm/<purpose>/<sessionId>/<id>` — exactly 4 segments
|
|
111
|
+
* - `swarm-lane/<sessionId>/<id>` — exactly 3 segments
|
|
112
|
+
*
|
|
113
|
+
* with `<sessionId>` matching `ses_[A-Za-z0-9]+` and `<purpose>` / `<id>` each
|
|
114
|
+
* a single non-empty, non-dot segment. Anything else — including a bare
|
|
115
|
+
* `swarm/my-own-experiment`, or a real lane name with extra trailing segments —
|
|
116
|
+
* returns `undefined`, which classifies the worktree as NOT swarm-owned and
|
|
117
|
+
* leaves it completely untouched.
|
|
118
|
+
*
|
|
119
|
+
* @returns The parsed branch, or `undefined` when the name is not a swarm lane.
|
|
120
|
+
*/
|
|
121
|
+
export declare function matchSwarmLaneBranch(branch: string): SwarmLaneBranch | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Tier-0 test seam (writing-tests skill). The prefix list is an implementation
|
|
124
|
+
* detail of the grammar — production code goes through
|
|
125
|
+
* {@link buildSwarmBranchName} / {@link matchSwarmLaneBranch} — but the branch
|
|
126
|
+
* tests assert that both documented styles are actually exercised.
|
|
127
|
+
*/
|
|
128
|
+
export declare const _test_exports: {
|
|
129
|
+
SWARM_WORKTREE_BRANCH_PREFIXES: readonly ["swarm/", "swarm-lane/"];
|
|
130
|
+
};
|
|
@@ -265,11 +265,50 @@ interface MessageWithParts {
|
|
|
265
265
|
info: MessageInfo;
|
|
266
266
|
parts: MessagePart[];
|
|
267
267
|
}
|
|
268
|
+
declare function extractPlanCriticVerdict(output: unknown): 'APPROVED' | 'NEEDS_REVISION' | 'REJECTED' | null;
|
|
268
269
|
/**
|
|
269
270
|
* Returns whether the plan in the given directory has a valid plan-critic
|
|
270
271
|
* approval. Does not throw — returns `false` for any failure (fail-closed).
|
|
271
272
|
*/
|
|
272
273
|
export declare function isPlanCriticApproved(directory: string): Promise<boolean>;
|
|
274
|
+
/**
|
|
275
|
+
* Escape hatch for the ratchet-tighter `critic_pre_plan` gate (issue #2012).
|
|
276
|
+
*
|
|
277
|
+
* When the critic returns APPROVED but the mechanical snapshot recorder
|
|
278
|
+
* ({@link recordPlanCriticApprovalSnapshotIfApplicable}) fails to persist it
|
|
279
|
+
* (verdict-format mismatch, dispatch-signal miss, or a plan.json read race),
|
|
280
|
+
* the gate permanently blocks ALL coder delegations because `critic_pre_plan`
|
|
281
|
+
* defaults to `true` and cannot be disabled (ratchet-tighter). This records a
|
|
282
|
+
* manual `plan_critic_gate` approval snapshot so the gate unblocks, with a
|
|
283
|
+
* distinct `method: 'manual_override'` audit marker so a human or downstream
|
|
284
|
+
* review can distinguish a manual approval from a mechanical critic approval.
|
|
285
|
+
*
|
|
286
|
+
* This mirrors the established escape-hatch pattern (PR_REVIEW gate #1898:
|
|
287
|
+
* `abortPrWorkflow` + `/swarm abort-pr-workflow` + `abort_pr_workflow` tool).
|
|
288
|
+
*
|
|
289
|
+
* Fail-closed preconditions:
|
|
290
|
+
* - The session must be an active **architect** session. The escape hatch is an
|
|
291
|
+
* escalation; non-architect callers are rejected so a coder/reviewer cannot
|
|
292
|
+
* self-unblock.
|
|
293
|
+
* - A plan.json must exist; you cannot approve a non-existent plan.
|
|
294
|
+
*
|
|
295
|
+
* @param directory - Project root containing `.swarm/`
|
|
296
|
+
* @param sessionID - The caller's session id (must be an architect session)
|
|
297
|
+
* @param options.reason - Optional human/agent-supplied reason (audited)
|
|
298
|
+
* @param options.userConfirmed - `true` only when invoked via the restricted
|
|
299
|
+
* `/swarm approve-plan-critic` command (human-run); `false` when invoked via
|
|
300
|
+
* the `approve_plan_critic` tool (agent-initiated). Recorded in the audit so a
|
|
301
|
+
* self-approve is visible.
|
|
302
|
+
*/
|
|
303
|
+
export declare function forceRecordPlanCriticApproval(directory: string, sessionID: string, options?: {
|
|
304
|
+
reason?: string;
|
|
305
|
+
userConfirmed?: boolean;
|
|
306
|
+
}): Promise<{
|
|
307
|
+
planId: string;
|
|
308
|
+
recordedAt: string;
|
|
309
|
+
reason?: string;
|
|
310
|
+
userConfirmed: boolean;
|
|
311
|
+
}>;
|
|
273
312
|
export declare function resolveDelegatedPlanTaskId(args: Record<string, unknown>, knownPlanTaskIds?: ReadonlySet<string>): string | null;
|
|
274
313
|
/**
|
|
275
314
|
* Builds a cause-specific diagnostic for `prepareCoderScope`'s SCOPE_NOT_DECLARED
|
|
@@ -332,7 +371,9 @@ export declare const _internals: {
|
|
|
332
371
|
bindBackgroundCoderReservationForDispatch: typeof import("../background/pending-delegations.js").bindBackgroundCoderReservation;
|
|
333
372
|
releaseBackgroundCoderReservationForDispatch: typeof import("../background/pending-delegations.js").releaseBackgroundCoderReservation;
|
|
334
373
|
resetStandardWorktreeIsolationState: typeof resetStandardWorktreeIsolationState;
|
|
335
|
-
PLAN_CRITIC_TASK_SIGNALS: readonly ["critic-gate", "plan critic", "review plan", "review the plan", "plan.md", "approve the plan", "plan approval"];
|
|
374
|
+
PLAN_CRITIC_TASK_SIGNALS: readonly ["critic-gate", "plan critic", "review plan", "review the plan", "plan.md", "approve the plan", "plan approval", "pre-implementation review", "evaluate this plan", "evaluate the plan", "assess this plan", "assess the plan", "plan soundness", "before implementation", "review the plan below"];
|
|
375
|
+
extractPlanCriticVerdict: typeof extractPlanCriticVerdict;
|
|
376
|
+
forceRecordPlanCriticApproval: typeof forceRecordPlanCriticApproval;
|
|
336
377
|
provisionWorktree: typeof _wtiInternals.provisionWorktree;
|
|
337
378
|
removeWorktree: typeof _wtiInternals.removeWorktree;
|
|
338
379
|
attemptMergeBackFromDirty: typeof _wtiInternals.attemptMergeBackFromDirty;
|
|
@@ -29,6 +29,16 @@ import { appendSkillUsageEntry, readSkillUsageEntries, readSkillUsageEntriesTail
|
|
|
29
29
|
export declare function loadRoutingSkills(directory: string, targetAgent: string): string[];
|
|
30
30
|
/** Agents that should receive skill context in delegations. */
|
|
31
31
|
export declare const SKILL_CAPABLE_AGENTS: Set<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Skill root directories to scan for SKILL.md files.
|
|
34
|
+
*
|
|
35
|
+
* Exported because `src/config/lane-permissions.ts` resolves these same
|
|
36
|
+
* project-relative roots to absolute directories when building the
|
|
37
|
+
* `external_directory` allowlist for a worktree-lane instance. Keeping one
|
|
38
|
+
* definition means a new skill root cannot be added here and silently become
|
|
39
|
+
* an unanswerable permission prompt inside a lane.
|
|
40
|
+
*/
|
|
41
|
+
export declare const SKILL_SEARCH_ROOTS: string[];
|
|
32
42
|
/**
|
|
33
43
|
* Maximum number of session-scoped skill-usage tail entries to process for
|
|
34
44
|
* skill scoring. This applies to the bounded tail-read window only.
|