opencode-swarm 7.168.1 → 7.169.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.
Files changed (133) hide show
  1. package/.opencode/skills/swarm-pr-feedback/SKILL.md +11 -11
  2. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  3. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  4. package/dist/cli/{coder-settlement-54a3d97g.js → coder-settlement-fd6ba876.js} +12 -12
  5. package/dist/cli/{config-doctor-vzp6b3ng.js → config-doctor-zeppqwwx.js} +2 -2
  6. package/dist/cli/{core-yynse50x.js → core-fj1afc31.js} +5 -2
  7. package/dist/cli/{curation-policy-mgwv8h2k.js → curation-policy-k74qz9ms.js} +5 -5
  8. package/dist/cli/{curator-drift-k0zrnm09.js → curator-drift-3ssjr0nx.js} +5 -5
  9. package/dist/cli/{curator-agdhhzqt.js → curator-emftndv0.js} +39 -38
  10. package/dist/cli/curator-llm-factory-4t773tmz.js +72 -0
  11. package/dist/cli/{dispatch-8ks9dyk5.js → dispatch-hwwj3qrb.js} +2 -2
  12. package/dist/cli/{evidence-summary-service-6mmcekr7.js → evidence-summary-service-51b69jc3.js} +16 -16
  13. package/dist/cli/{gate-evidence-xqvkqhrk.js → gate-evidence-53s161wb.js} +7 -7
  14. package/dist/cli/guardrail-explain-mhx8gt8q.js +73 -0
  15. package/dist/cli/{guardrail-log-5wa5c77w.js → guardrail-log-xg6hrdsq.js} +8 -8
  16. package/dist/cli/{guardrail-reset-dh78tbcf.js → guardrail-reset-fgv5kt5x.js} +39 -38
  17. package/dist/cli/{hive-promoter-3czsx7c6.js → hive-promoter-41zygtgx.js} +39 -38
  18. package/dist/cli/index-0hgmsyfp.js +92 -0
  19. package/dist/cli/{index-6df6wbvj.js → index-0vgs5r39.js} +8 -8
  20. package/dist/cli/{index-3jmb4ppa.js → index-1cbjemgh.js} +2 -2
  21. package/dist/cli/{index-p612v1mv.js → index-2s7dvzff.js} +200 -51
  22. package/dist/cli/{index-qthc56c4.js → index-2znfa537.js} +4 -4
  23. package/dist/cli/{index-91ww9hyr.js → index-3bfzpzsb.js} +1 -1
  24. package/dist/cli/{index-kkmezerc.js → index-3zcds757.js} +3101 -1918
  25. package/dist/cli/{index-d5qf7hvh.js → index-5400m33a.js} +1 -1
  26. package/dist/cli/{index-bw9x8d8n.js → index-55fkkjec.js} +5 -5
  27. package/dist/cli/{index-qwsh0h2g.js → index-5qt9yf5w.js} +4 -4
  28. package/dist/cli/{index-chebm5h5.js → index-5reh1bjz.js} +3 -3
  29. package/dist/cli/{index-2xbww1x0.js → index-76ng6vmq.js} +7 -7
  30. package/dist/cli/{index-qhey6vc3.js → index-7h01bkm6.js} +2 -2
  31. package/dist/cli/{index-gh9ybrrs.js → index-83m0y4cj.js} +6 -6
  32. package/dist/cli/{index-yt9n9zt3.js → index-8x9keek6.js} +41 -40
  33. package/dist/cli/{index-8ybjqg51.js → index-9ttqbhvw.js} +1 -1
  34. package/dist/cli/{index-kear8gb7.js → index-b3pmzbh1.js} +2 -2
  35. package/dist/cli/{index-h439y187.js → index-bernkwgf.js} +1 -1
  36. package/dist/cli/{index-m35hybf0.js → index-bm5xrfnx.js} +1 -1
  37. package/dist/cli/{index-pyf517sz.js → index-br3mvbsa.js} +2 -2
  38. package/dist/cli/{index-4r5pmtvk.js → index-bx1wgn3a.js} +4 -4
  39. package/dist/cli/{index-xhb4gryr.js → index-c7kr7tnk.js} +4 -4
  40. package/dist/cli/{index-nwwk3dej.js → index-cgpwjctj.js} +1 -1
  41. package/dist/cli/{index-q8091q8b.js → index-dd48vt27.js} +3 -3
  42. package/dist/cli/{index-wst6n478.js → index-dvbf6fpn.js} +1 -1
  43. package/dist/cli/{index-w3x1dmrf.js → index-e4dxf5cr.js} +39 -38
  44. package/dist/cli/{index-5g6rhkn7.js → index-egkc2bpv.js} +36 -1
  45. package/dist/cli/{index-4kv1ew3q.js → index-exf0j569.js} +1 -1
  46. package/dist/cli/{index-a8xbvsse.js → index-fgp96k3r.js} +2 -2
  47. package/dist/cli/{index-5zqakgp4.js → index-fhh02gwx.js} +3 -3
  48. package/dist/cli/{index-dfyv3xkd.js → index-gfbggp8k.js} +9 -9
  49. package/dist/cli/{index-f1fps3w9.js → index-ksybszed.js} +7 -7
  50. package/dist/cli/{index-v3xc4sde.js → index-nbdmdyke.js} +2 -1
  51. package/dist/cli/{index-z6qreakh.js → index-nprdr0sm.js} +6 -4
  52. package/dist/cli/{index-9b2105n0.js → index-nwv3e3kc.js} +2 -2
  53. package/dist/cli/{index-bvqqwx84.js → index-nyn01yrz.js} +2 -2
  54. package/dist/cli/{index-y85aptep.js → index-p6xsgk4r.js} +7 -7
  55. package/dist/cli/{index-xkf3672y.js → index-s96dpjsk.js} +2 -2
  56. package/dist/cli/{index-j0bxxz9d.js → index-sb1s03y9.js} +8 -8
  57. package/dist/cli/{index-gmpmgtzn.js → index-sxcfszbe.js} +5 -5
  58. package/dist/cli/{index-qkwtth00.js → index-wwr67xc0.js} +197 -35
  59. package/dist/cli/{index-gp9yzr1v.js → index-xnpjwc4h.js} +1 -1
  60. package/dist/cli/{index-apy1qfj0.js → index-yj24ny5k.js} +26 -4
  61. package/dist/cli/{index-w1dfkp1q.js → index-zapc8vj4.js} +14 -14
  62. package/dist/cli/index.js +39 -38
  63. package/dist/cli/{knowledge-escalator-135dz4eh.js → knowledge-escalator-07s44av0.js} +13 -13
  64. package/dist/cli/{knowledge-events-27gwv47q.js → knowledge-events-j2n1569p.js} +11 -11
  65. package/dist/cli/{knowledge-link-dr3xnwyd.js → knowledge-link-rkxfrmhm.js} +4 -4
  66. package/dist/cli/{knowledge-store-80m44bfw.js → knowledge-store-85metj89.js} +5 -5
  67. package/dist/cli/{knowledge-validator-crsfb2cc.js → knowledge-validator-63k1xzcc.js} +7 -7
  68. package/dist/cli/{pending-delegations-gwgjzzkz.js → pending-delegations-dckmjymn.js} +12 -12
  69. package/dist/cli/{pr-subscriptions-g633nhz4.js → pr-subscriptions-pyh73me6.js} +12 -12
  70. package/dist/cli/{pr-workflow-gate-4dc5nt2e.js → pr-workflow-gate-k1r4rjw4.js} +39 -38
  71. package/dist/cli/{runner-k0ycgv8x.js → runner-1dwrgyyr.js} +6 -6
  72. package/dist/cli/{scan-cursor-avxjsm4w.js → scan-cursor-k6egg4n0.js} +6 -6
  73. package/dist/cli/{schema-3ja77k4y.js → schema-vdrtpggt.js} +5 -1
  74. package/dist/cli/{scope-persistence-f540tc50.js → scope-persistence-h1mmww19.js} +14 -14
  75. package/dist/cli/{skill-generator-kcqqpg1g.js → skill-generator-pmn6gmvk.js} +15 -15
  76. package/dist/cli/{snapshot-coordination-init-e4s8bn4p.js → snapshot-coordination-init-rspykgd0.js} +39 -38
  77. package/dist/cli/{telemetry-2wzapf11.js → telemetry-fdtaemnv.js} +1 -1
  78. package/dist/cli/{workspace-snapshot-rkgxhj9b.js → workspace-snapshot-hkz2wt1c.js} +4 -4
  79. package/dist/cli/{worktree-collision-ownership-rk9gz638.js → worktree-collision-ownership-x84dzzzc.js} +18 -104
  80. package/dist/cli/{worktree-isolation-1bdzfgky.js → worktree-isolation-nw9pakkx.js} +39 -38
  81. package/dist/commands/destructive-purge.d.ts +85 -0
  82. package/dist/commands/registry.d.ts +2 -2
  83. package/dist/commands/reset-session.d.ts +5 -1
  84. package/dist/config/constants.d.ts +4 -1
  85. package/dist/config/lane-context.d.ts +19 -0
  86. package/dist/config/schema.d.ts +77 -0
  87. package/dist/evaluation/index.d.ts +1 -0
  88. package/dist/evaluation/retrieval-quality.d.ts +116 -0
  89. package/dist/failures/invocation-failure.d.ts +23 -4
  90. package/dist/hooks/init-orphan-recovery.d.ts +7 -0
  91. package/dist/hooks/pr-workflow-gate.d.ts +8 -2
  92. package/dist/index.js +596 -590
  93. package/dist/memory/embeddings/reranker.d.ts +13 -2
  94. package/dist/memory/evaluation.d.ts +99 -0
  95. package/dist/memory/heldout-evaluation-corpus.d.ts +51 -0
  96. package/dist/memory/index.d.ts +5 -2
  97. package/dist/memory/sqlite-provider.d.ts +35 -1
  98. package/dist/memory/types.d.ts +14 -0
  99. package/dist/observability/otel-mapping.d.ts +5 -5
  100. package/dist/observability/otlp-exporter.d.ts +80 -0
  101. package/dist/parallel/lane-owners.d.ts +76 -0
  102. package/dist/tools/repo-graph/query.d.ts +6 -1
  103. package/dist/tools/repo-graph/types.d.ts +13 -4
  104. package/dist/utils/bun-compat.d.ts +20 -0
  105. package/dist/utils/gitignore-warning.d.ts +5 -2
  106. package/dist/worktree/base-migration.d.ts +55 -0
  107. package/dist/worktree/core.d.ts +15 -6
  108. package/dist/worktree/ownership.d.ts +66 -0
  109. package/opencode-swarm.schema.json +97 -0
  110. package/package.json +4 -2
  111. package/tests/fixtures/memory-recall-heldout/manifest.json +311 -0
  112. package/tests/fixtures/memory-recall-heldout/sources/bash.sh +1 -0
  113. package/tests/fixtures/memory-recall-heldout/sources/c.c +1 -0
  114. package/tests/fixtures/memory-recall-heldout/sources/cpp.cpp +1 -0
  115. package/tests/fixtures/memory-recall-heldout/sources/csharp.cs +1 -0
  116. package/tests/fixtures/memory-recall-heldout/sources/css.css +3 -0
  117. package/tests/fixtures/memory-recall-heldout/sources/dart.dart +1 -0
  118. package/tests/fixtures/memory-recall-heldout/sources/go.go +3 -0
  119. package/tests/fixtures/memory-recall-heldout/sources/ini.ini +2 -0
  120. package/tests/fixtures/memory-recall-heldout/sources/java.java +1 -0
  121. package/tests/fixtures/memory-recall-heldout/sources/javascript.js +3 -0
  122. package/tests/fixtures/memory-recall-heldout/sources/kotlin.kt +1 -0
  123. package/tests/fixtures/memory-recall-heldout/sources/php.php +1 -0
  124. package/tests/fixtures/memory-recall-heldout/sources/powershell.ps1 +1 -0
  125. package/tests/fixtures/memory-recall-heldout/sources/python.py +2 -0
  126. package/tests/fixtures/memory-recall-heldout/sources/regex.regex +1 -0
  127. package/tests/fixtures/memory-recall-heldout/sources/ruby.rb +3 -0
  128. package/tests/fixtures/memory-recall-heldout/sources/rust.rs +1 -0
  129. package/tests/fixtures/memory-recall-heldout/sources/swift.swift +1 -0
  130. package/tests/fixtures/memory-recall-heldout/sources/tsx.tsx +3 -0
  131. package/tests/fixtures/memory-recall-heldout/sources/typescript.ts +3 -0
  132. package/dist/cli/curator-llm-factory-ygxd6hfx.js +0 -71
  133. package/dist/cli/guardrail-explain-vjtjhgzs.js +0 -72
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Issue #2527 (F4): one-time migration of the LEGACY parent-level shared
3
+ * worktree base (`<project-parent>/.swarm-worktrees`, shared by every
4
+ * sibling checkout — the root of the cross-project destruction class) into
5
+ * the project-internal default base (`<project>/.swarm-worktrees`).
6
+ *
7
+ * Ordering contract (plan-critic round 2, item 3): migration runs AFTER the
8
+ * recovery lock, AFTER the live-lane-owner scan (it needs the liveness
9
+ * answer), and AFTER the existing fail-closed uncertainty guards — mutating
10
+ * gitdir pointers under uncertain project state is not acceptable — and
11
+ * BEFORE enumeration-for-deletion.
12
+ *
13
+ * Safety contract: migration NEVER deletes anything. Owned + not-live
14
+ * registered worktrees are MOVED with `git worktree move` (the primitive
15
+ * that rewrites both gitdir pointers atomically; same-volume moves are an
16
+ * internal rename — empirically verified on Windows with a git-excluded
17
+ * target and dirty content). Foreign-owned lanes, live-owned lanes, and
18
+ * ownership-unprovable `.git`-less remnants are LEFT AT THEIR LEGACY PATHS
19
+ * (their owning checkouts migrate them; a bounded advisory line surfaces
20
+ * them). The legacy base directory itself is removed only when EMPTY (plain
21
+ * rmdir, never rm -rf). Timeout or per-lane failure ⇒ leave in place,
22
+ * retry next start; N bounded by the lane-owner store caps and the pass's
23
+ * withTimeout budget.
24
+ */
25
+ import * as fs from 'node:fs';
26
+ import { resolveWorktreeRepoOwnership } from '../config/lane-context';
27
+ import type { LiveLaneOwnerEntry } from '../parallel/lane-owners';
28
+ import { bunSpawn } from '../utils/bun-compat';
29
+ import { resolveGitExecutable } from '../utils/git-executable.js';
30
+ export interface BaseMigrationResult {
31
+ attempted: boolean;
32
+ legacyBaseExists: boolean;
33
+ moved: string[];
34
+ retained: Array<{
35
+ lanePath: string;
36
+ reason: string;
37
+ }>;
38
+ legacyBaseRemoved: boolean;
39
+ }
40
+ export declare const _internals: {
41
+ resolveWorktreeRepoOwnership: typeof resolveWorktreeRepoOwnership;
42
+ bunSpawn: typeof bunSpawn;
43
+ resolveGitExecutable: typeof resolveGitExecutable;
44
+ readdirSync: typeof fs.readdirSync;
45
+ existsSync: typeof fs.existsSync;
46
+ mkdirSync: typeof fs.mkdirSync;
47
+ rmdirSync: typeof fs.rmdirSync;
48
+ realpathSync: typeof fs.realpathSync;
49
+ };
50
+ /**
51
+ * Migrate owned, non-live lanes from the legacy parent-level base into the
52
+ * project-internal default base. Fail-open and non-throwing by contract
53
+ * (runs inside the bounded init-orphan-recovery pass).
54
+ */
55
+ export declare function migrateLegacyWorktreeBase(directory: string, liveOwners: LiveLaneOwnerEntry[]): Promise<BaseMigrationResult>;
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import * as fs from 'node:fs';
12
12
  import * as fsPromises from 'node:fs/promises';
13
+ import { clearLiveLaneOwner } from '../parallel/lane-owners';
13
14
  import { bunSpawn } from '../utils/bun-compat';
14
15
  import { resolveGitExecutable } from '../utils/git-executable.js';
15
16
  import type { WorktreeHandle, WorktreeOptions, WorktreeProvisionResult } from './types';
@@ -23,6 +24,11 @@ import type { WorktreeHandle, WorktreeOptions, WorktreeProvisionResult } from '.
23
24
  */
24
25
  export declare const _internals: {
25
26
  bunSpawn: typeof bunSpawn;
27
+ /**
28
+ * Issue #2527 F3: clear the durable live-lane-owner record when this
29
+ * module removes a worktree (seam so tests can observe the clear).
30
+ */
31
+ clearLiveLaneOwner: typeof clearLiveLaneOwner;
26
32
  /** Test seam for process.platform — allows non-Windows CIs to exercise Windows paths. */
27
33
  platform: string;
28
34
  /** Test seam for sleep — allows tests to skip real delays. */
@@ -190,15 +196,18 @@ export declare function makeWorktreeBranchName(sessionId: string, id: string, op
190
196
  */
191
197
  /**
192
198
  * Resolves the swarm-managed worktree base directory: `directory/worktreeDir`
193
- * when an override is configured, otherwise the DD-6 default
194
- * `<project-parent>/.swarm-worktrees`. Shared by `provisionWorktree` (path
195
- * construction) and the destructive-command guard / removeWorktree force
196
- * fallback (containment checks) so both sides agree on what counts as
197
- * "swarm-managed".
199
+ * when an override is configured, otherwise the project-INTERNAL default
200
+ * `<project>/.swarm-worktrees` (issue #2527 root fix — the pre-#2527 default
201
+ * was the project's PARENT, so every sibling checkout shared one base and
202
+ * reclamation in one project could destroy another project's lanes).
203
+ * Shared by `provisionWorktree` (path construction) and the
204
+ * destructive-command guard / removeWorktree force fallback (containment
205
+ * checks) so both sides agree on what counts as "swarm-managed". The legacy
206
+ * parent-level base is migrated by `base-migration.ts`, never deleted.
198
207
  *
199
208
  * @param directory - Project root (an absolute path to the git working tree).
200
209
  * @param worktreeDir - Optional worktree-dir override (relative to `directory`
201
- * or absolute). When absent, the DD-6 default base is used.
210
+ * or absolute). When absent, the default base is used.
202
211
  * @returns The absolute worktree base directory.
203
212
  */
204
213
  export declare function resolveWorktreeBaseDir(directory: string, worktreeDir?: string): string;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Issue #2527: the single ownership-gated worktree-directory reclamation
3
+ * path.
4
+ *
5
+ * Every deletion of a worktree-base directory reachable from plugin init
6
+ * (init orphan recovery) or `/swarm reset-session` routes through
7
+ * `removeOwnedWorktreeDir`. The contract, frozen by the #2527 acceptance
8
+ * checks (C1/C2/C5/C7/C10) and pinned by the C7 leg-B source-scan ratchet:
9
+ *
10
+ * 1. A `.git`-bearing candidate is deletable ONLY when the existing
11
+ * commondir-based primitive (`resolveWorktreeRepoOwnership` on
12
+ * `readLinkedWorktreeGitDir` + `resolveMainWorktree`) proves this
13
+ * repository owns it.
14
+ * 2. A `git worktree remove` refusal is a STOP — never an escalation to
15
+ * `rmSync`. The refusal text ("is not a working tree", "contains
16
+ * modified or untracked files") is itself the safety signal: the first
17
+ * is git saying this repo does not own the path; the second is git
18
+ * refusing to destroy uncommitted work. Both must preserve the
19
+ * candidate.
20
+ * 3. A `.git`-less directory is deletable ONLY when it sits inside this
21
+ * project's own default worktree base (ours by construction, per F1).
22
+ * Anywhere else — the legacy parent-level shared base, or a configured
23
+ * `worktree_dir` override that may point anywhere — the ownership of a
24
+ * bare directory cannot be proven and it is skipped and reported.
25
+ * Review-round hardening: the marker probe is errno-discriminating —
26
+ * an unreadable-but-present `.git` classifies as `uncertain`, never as
27
+ * "gitless".
28
+ *
29
+ * The entry files (`src/hooks/init-orphan-recovery.ts`,
30
+ * `src/commands/reset-session.ts`) must not call `rmSync` on base-derived
31
+ * paths themselves — the C7 ratchet enforces it.
32
+ */
33
+ import * as fs from 'node:fs';
34
+ import { resolveWorktreeRepoOwnership } from '../config/lane-context';
35
+ import { isPathUnderSwarmWorktreeBase, removeWorktree } from './core';
36
+ export type OwnedRemovalOutcome = {
37
+ status: 'removed';
38
+ } | {
39
+ status: 'skipped';
40
+ reason: string;
41
+ } | {
42
+ status: 'refused';
43
+ reason: string;
44
+ };
45
+ export type GitMarkerProbe = 'gitless' | 'present' | 'uncertain';
46
+ export declare const _internals: {
47
+ resolveWorktreeRepoOwnership: typeof resolveWorktreeRepoOwnership;
48
+ isPathUnderSwarmWorktreeBase: typeof isPathUnderSwarmWorktreeBase;
49
+ removeWorktree: typeof removeWorktree;
50
+ rmSync: typeof fs.rmSync;
51
+ statSync: any;
52
+ };
53
+ /**
54
+ * Errno-discriminating `.git` marker probe. A bare `existsSync` collapses
55
+ * every I/O error (EPERM/EBUSY/EMFILE on a transiently-unreadable marker)
56
+ * into "gitless", which would route an ownership-unprovable path into
57
+ * removal. Only a proven-absent marker is "gitless"; any other error is
58
+ * "uncertain" and the caller must retain the candidate.
59
+ */
60
+ export declare function probeGitMarker(dotGitPath: string): GitMarkerProbe;
61
+ /**
62
+ * Attempt to reclaim one worktree-base directory, gated by repo ownership.
63
+ * NEVER throws: every failure is a returned outcome so callers can report
64
+ * and continue with the next candidate.
65
+ */
66
+ export declare function removeOwnedWorktreeDir(worktreePath: string, projectRoot: string): Promise<OwnedRemovalOutcome>;
@@ -3082,6 +3082,103 @@
3082
3082
  }
3083
3083
  }
3084
3084
  },
3085
+ "observability": {
3086
+ "description": "Observability options — remote OTLP/OpenInference export is opt-in and disabled by default (issue #2485).",
3087
+ "type": "object",
3088
+ "properties": {
3089
+ "export": {
3090
+ "type": "object",
3091
+ "properties": {
3092
+ "enabled": {
3093
+ "default": false,
3094
+ "type": "boolean"
3095
+ },
3096
+ "endpoint": {
3097
+ "default": "",
3098
+ "type": "string",
3099
+ "minLength": 1
3100
+ },
3101
+ "convention": {
3102
+ "default": "genai",
3103
+ "type": "string",
3104
+ "enum": [
3105
+ "genai",
3106
+ "openinference"
3107
+ ]
3108
+ },
3109
+ "headers": {
3110
+ "type": "object",
3111
+ "propertyNames": {
3112
+ "type": "string"
3113
+ },
3114
+ "additionalProperties": {
3115
+ "type": "string"
3116
+ }
3117
+ },
3118
+ "batchSize": {
3119
+ "default": 64,
3120
+ "type": "integer",
3121
+ "minimum": 1,
3122
+ "maximum": 512
3123
+ },
3124
+ "flushIntervalMs": {
3125
+ "default": 5000,
3126
+ "type": "integer",
3127
+ "minimum": 250,
3128
+ "maximum": 300000
3129
+ },
3130
+ "requestTimeoutMs": {
3131
+ "default": 5000,
3132
+ "type": "integer",
3133
+ "minimum": 250,
3134
+ "maximum": 60000
3135
+ },
3136
+ "spoolMaxBytes": {
3137
+ "default": 1048576,
3138
+ "type": "integer",
3139
+ "minimum": 16384,
3140
+ "maximum": 16777216
3141
+ },
3142
+ "spoolMaxAgeMs": {
3143
+ "default": 86400000,
3144
+ "type": "integer",
3145
+ "minimum": 60000,
3146
+ "maximum": 2592000000
3147
+ },
3148
+ "maxRetries": {
3149
+ "default": 3,
3150
+ "type": "integer",
3151
+ "minimum": 0,
3152
+ "maximum": 10
3153
+ },
3154
+ "backoffBaseMs": {
3155
+ "default": 200,
3156
+ "type": "integer",
3157
+ "minimum": 10,
3158
+ "maximum": 10000
3159
+ },
3160
+ "backoffMaxMs": {
3161
+ "default": 30000,
3162
+ "type": "integer",
3163
+ "minimum": 100,
3164
+ "maximum": 300000
3165
+ },
3166
+ "circuitThreshold": {
3167
+ "default": 5,
3168
+ "type": "integer",
3169
+ "minimum": 1,
3170
+ "maximum": 50
3171
+ },
3172
+ "circuitCooldownMs": {
3173
+ "default": 60000,
3174
+ "type": "integer",
3175
+ "minimum": 1000,
3176
+ "maximum": 600000
3177
+ }
3178
+ }
3179
+ }
3180
+ }
3181
+ },
3085
3182
  "learning": {
3086
3183
  "description": "Learning subsystem: real-time admission, PRM persistence, dedup sweep (issue #1821).",
3087
3184
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.168.1",
3
+ "version": "7.169.0",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -85,6 +85,7 @@
85
85
  ".opencode/skills/orchestrating-subagents",
86
86
  ".opencode/skills/durable-session-state",
87
87
  "tests/fixtures/memory-recall",
88
+ "tests/fixtures/memory-recall-heldout",
88
89
  "opencode-swarm.schema.json",
89
90
  "README.md",
90
91
  "LICENSE"
@@ -131,7 +132,8 @@
131
132
  "check:error-channel-discard": "bun run scripts/check-error-channel-discard.ts",
132
133
  "check:path-identity": "bun run scripts/check-path-identity.ts",
133
134
  "check:registry-citations": "bun run scripts/check-registry-citations.ts",
134
- "check:memory-recall": "bun run scripts/memory-recall-regression.ts"
135
+ "check:memory-recall": "bun run scripts/memory-recall-regression.ts",
136
+ "check:retrieval-quality": "bun run scripts/retrieval-quality-regression.ts"
135
137
  },
136
138
  "dependencies": {
137
139
  "@opencode-ai/plugin": "^1.18.3",
@@ -0,0 +1,311 @@
1
+ {
2
+ "corpus_id": "opencode-swarm-memory-recall-heldout-v1",
3
+ "split": "heldout",
4
+ "version": "1.0.0",
5
+ "supported_languages": [
6
+ "javascript",
7
+ "typescript",
8
+ "python",
9
+ "go",
10
+ "rust",
11
+ "php",
12
+ "java",
13
+ "c",
14
+ "cpp",
15
+ "csharp",
16
+ "ruby",
17
+ "swift",
18
+ "kotlin",
19
+ "dart",
20
+ "css",
21
+ "bash",
22
+ "powershell",
23
+ "ini",
24
+ "regex",
25
+ "tsx"
26
+ ],
27
+ "analyzer_extensions": [
28
+ { "language": "typescript", "extractor_id": "backend:typescript:v1" },
29
+ { "language": "javascript", "extractor_id": "backend:javascript:v1" },
30
+ { "language": "python", "extractor_id": "backend:python:v1" },
31
+ { "language": "go", "extractor_id": "backend:go:v1" },
32
+ { "language": "rust", "extractor_id": "backend:rust:v1" },
33
+ { "language": "php", "extractor_id": "backend:php:v1" },
34
+ { "language": "java", "extractor_id": "backend:java:v1" },
35
+ { "language": "cpp", "extractor_id": "backend:cpp:v1" },
36
+ { "language": "csharp", "extractor_id": "backend:csharp:v1" },
37
+ { "language": "ruby", "extractor_id": "backend:ruby:v1" },
38
+ { "language": "swift", "extractor_id": "backend:swift:v1" },
39
+ { "language": "kotlin", "extractor_id": "backend:kotlin:v1" },
40
+ { "language": "dart", "extractor_id": "backend:dart:v1" }
41
+ ],
42
+ "os_gates": {
43
+ "linux": {
44
+ "id": "retrieval-quality-linux",
45
+ "command": "bun run check:retrieval-quality"
46
+ },
47
+ "macos": {
48
+ "id": "retrieval-quality-macos",
49
+ "command": "bun --smol test tests/unit/memory"
50
+ },
51
+ "windows": {
52
+ "id": "retrieval-quality-windows",
53
+ "command": "bun --smol test tests/unit/memory"
54
+ }
55
+ },
56
+ "thresholds": {
57
+ "precision_at_k": 0.25,
58
+ "recall_at_k": 0.25,
59
+ "max_spurious_edges": 2,
60
+ "max_known_misses": 2,
61
+ "direct_source_positive_hits": 14
62
+ },
63
+ "cases": [
64
+ {
65
+ "id": "javascript-profile",
66
+ "language": "javascript",
67
+ "source_path": "sources/javascript.js",
68
+ "content_hash": "B9638E337E7EB634ACA045E77B4561DE635466D9D7B6AA611EDA03D1468AFFD8",
69
+ "expected_symbols": ["loadUserProfile", "userId"],
70
+ "expected_edges": ["loadUserProfile -> fetch"],
71
+ "known_misses": ["userId"],
72
+ "spurious_edges": ["loadUserProfile -> userId"],
73
+ "paraphrase": "retrieve account details through a remote service",
74
+ "analyzer_id": "backend:javascript:v1"
75
+ },
76
+ {
77
+ "id": "typescript-profile",
78
+ "language": "typescript",
79
+ "source_path": "sources/typescript.ts",
80
+ "content_hash": "0C8303B36471F750A1A9BE5BAE1C6759265669E492E49C7A62589C263C739497",
81
+ "expected_symbols": ["saveInvoice", "invoiceId"],
82
+ "expected_edges": ["saveInvoice -> fetch"],
83
+ "known_misses": ["invoiceId"],
84
+ "spurious_edges": ["saveInvoice -> invoiceId"],
85
+ "paraphrase": "persist a billing document through an HTTP request",
86
+ "analyzer_id": "backend:typescript:v1"
87
+ },
88
+ {
89
+ "id": "python-profile",
90
+ "language": "python",
91
+ "source_path": "sources/python.py",
92
+ "content_hash": "B02409456CDD546DD81616637265866EECE08CBD58AC25A74BF97F05BC87AA9D",
93
+ "expected_symbols": ["rotate_api_key", "api_key"],
94
+ "expected_edges": ["rotate_api_key -> rotate_secret"],
95
+ "known_misses": ["api_key"],
96
+ "spurious_edges": ["rotate_api_key -> api_key"],
97
+ "paraphrase": "replace a secret credential with a newly rotated key",
98
+ "analyzer_id": "backend:python:v1"
99
+ },
100
+ {
101
+ "id": "go-profile",
102
+ "language": "go",
103
+ "source_path": "sources/go.go",
104
+ "content_hash": "FBD76CEC751667AE095543444E3731CAD8005AFC605801637673795FB5FB0EC8",
105
+ "expected_symbols": ["ParseConfig", "configPath"],
106
+ "expected_edges": ["ParseConfig -> string"],
107
+ "known_misses": ["configPath"],
108
+ "spurious_edges": ["ParseConfig -> configPath"],
109
+ "paraphrase": "read settings from a configuration path",
110
+ "analyzer_id": "backend:go:v1"
111
+ },
112
+ {
113
+ "id": "rust-profile",
114
+ "language": "rust",
115
+ "source_path": "sources/rust.rs",
116
+ "content_hash": "C45037A40930367399DB3643615E7505425E3146C6F6737B886E0FE843C53226",
117
+ "expected_symbols": ["publish_artifact", "artifact_id"],
118
+ "expected_edges": ["publish_artifact -> format"],
119
+ "known_misses": ["artifact_id"],
120
+ "spurious_edges": ["publish_artifact -> artifact_id"],
121
+ "paraphrase": "publish a build artifact using its identifier",
122
+ "analyzer_id": "backend:rust:v1"
123
+ },
124
+ {
125
+ "id": "php-profile",
126
+ "language": "php",
127
+ "source_path": "sources/php.php",
128
+ "content_hash": "6A22BE82C25024874413438ECD550360628A25CBFFA528E3FC6E9480636D1BFA",
129
+ "expected_symbols": ["find_order", "orderId"],
130
+ "expected_edges": ["find_order -> string"],
131
+ "known_misses": ["orderId"],
132
+ "spurious_edges": ["find_order -> orderId"],
133
+ "paraphrase": "look up a purchase using its order identifier",
134
+ "analyzer_id": "backend:php:v1"
135
+ },
136
+ {
137
+ "id": "java-profile",
138
+ "language": "java",
139
+ "source_path": "sources/java.java",
140
+ "content_hash": "6F6A7B2DBE906137856D71C60DDDB0F2A0BC6D3FBA46204ACE4CF5F9BB43669F",
141
+ "expected_symbols": ["sendWebhook", "webhookUrl"],
142
+ "expected_edges": ["sendWebhook -> String"],
143
+ "known_misses": ["webhookUrl"],
144
+ "spurious_edges": ["Webhooks -> webhookUrl"],
145
+ "paraphrase": "deliver an event to a callback URL",
146
+ "analyzer_id": "backend:java:v1"
147
+ },
148
+ {
149
+ "id": "c-profile",
150
+ "language": "c",
151
+ "source_path": "sources/c.c",
152
+ "content_hash": "C2CF3904D71ED57B52D204C9B1A7A7BAB90E30DF636F725FB939F0D14759B63F",
153
+ "expected_symbols": ["open_socket", "socket_fd"],
154
+ "expected_edges": ["open_socket -> char"],
155
+ "known_misses": ["socket_fd"],
156
+ "spurious_edges": ["open_socket -> close_socket"],
157
+ "paraphrase": "open a network channel from its descriptor",
158
+ "analyzer_id": "parser-only:c:v1"
159
+ },
160
+ {
161
+ "id": "cpp-profile",
162
+ "language": "cpp",
163
+ "source_path": "sources/cpp.cpp",
164
+ "content_hash": "25F855671A74CE618980E69790589ED2AC027566674ABCACB2E54EA3C3B8B3DD",
165
+ "expected_symbols": ["render_widget", "widget_id"],
166
+ "expected_edges": ["render_widget -> string"],
167
+ "known_misses": ["widget_id"],
168
+ "spurious_edges": ["render_widget -> widget_id", "render_widget -> std"],
169
+ "paraphrase": "draw a user interface component by identifier",
170
+ "analyzer_id": "backend:cpp:v1"
171
+ },
172
+ {
173
+ "id": "csharp-profile",
174
+ "language": "csharp",
175
+ "source_path": "sources/csharp.cs",
176
+ "content_hash": "CFD8618108A02D2EB98D122313198DEE4684C204BA676347550C3310FBD8566D",
177
+ "expected_symbols": ["AuthorizeRequest", "requestId"],
178
+ "expected_edges": ["AuthorizeRequest -> string"],
179
+ "known_misses": ["requestId"],
180
+ "spurious_edges": [
181
+ "<module> -> AuthorizeRequest",
182
+ "<module> -> requestId"
183
+ ],
184
+ "paraphrase": "check whether an incoming request is permitted",
185
+ "analyzer_id": "backend:csharp:v1"
186
+ },
187
+ {
188
+ "id": "ruby-profile",
189
+ "language": "ruby",
190
+ "source_path": "sources/ruby.rb",
191
+ "content_hash": "47BC5872B2085EE4C738484E2261F20CDF7A36115F97F1FD904813A9BDACA6F8",
192
+ "expected_symbols": ["normalize_email", "email"],
193
+ "expected_edges": ["normalize_email -> strip"],
194
+ "known_misses": ["email"],
195
+ "spurious_edges": [
196
+ "normalize_email -> email",
197
+ "normalize_email -> downcase"
198
+ ],
199
+ "paraphrase": "canonicalize an address before storing it",
200
+ "analyzer_id": "backend:ruby:v1"
201
+ },
202
+ {
203
+ "id": "swift-profile",
204
+ "language": "swift",
205
+ "source_path": "sources/swift.swift",
206
+ "content_hash": "9AA176B51176FC6DFF98097678E04AC5B57B787E2F0A5E16B6B3C5F0433839BA",
207
+ "expected_symbols": ["cacheImage", "imageURL"],
208
+ "expected_edges": ["cacheImage -> String"],
209
+ "known_misses": ["imageURL"],
210
+ "spurious_edges": ["cacheImage -> imageURL"],
211
+ "paraphrase": "store a downloaded picture for later display",
212
+ "analyzer_id": "backend:swift:v1"
213
+ },
214
+ {
215
+ "id": "kotlin-profile",
216
+ "language": "kotlin",
217
+ "source_path": "sources/kotlin.kt",
218
+ "content_hash": "102FA601E66DB4AC3AF2C0E30BE865077980F58252C7A438968820C8D2AA23B2",
219
+ "expected_symbols": ["syncCalendar", "calendarId"],
220
+ "expected_edges": ["syncCalendar -> String"],
221
+ "known_misses": ["calendarId"],
222
+ "spurious_edges": ["syncCalendar -> calendarId"],
223
+ "paraphrase": "synchronize an appointment calendar by identifier",
224
+ "analyzer_id": "backend:kotlin:v1"
225
+ },
226
+ {
227
+ "id": "dart-profile",
228
+ "language": "dart",
229
+ "source_path": "sources/dart.dart",
230
+ "content_hash": "4E21F3AC09BF159D68CEA641DB11AC8EA68B1BF2E61F3098028E40DF1AE25808",
231
+ "expected_symbols": ["decodeToken", "token"],
232
+ "expected_edges": ["decodeToken -> String"],
233
+ "known_misses": ["token"],
234
+ "spurious_edges": ["decodeToken -> token"],
235
+ "paraphrase": "interpret a signed credential for a session",
236
+ "analyzer_id": "backend:dart:v1"
237
+ },
238
+ {
239
+ "id": "css-profile",
240
+ "language": "css",
241
+ "source_path": "sources/css.css",
242
+ "content_hash": "4D9C610B3F17E60A83CAB953BF9CAC157F001A1CB06CDAA089ADE0A9886E1411",
243
+ "expected_symbols": ["notification-banner", "notification-hue"],
244
+ "expected_edges": ["notification-banner -> notification-hue"],
245
+ "known_misses": ["notification-hue"],
246
+ "spurious_edges": ["notification-banner -> danger-color"],
247
+ "paraphrase": "style a notice banner with its theme hue",
248
+ "analyzer_id": "parser-only:css:v1"
249
+ },
250
+ {
251
+ "id": "bash-profile",
252
+ "language": "bash",
253
+ "source_path": "sources/bash.sh",
254
+ "content_hash": "74ED9524EBC70CB288D4F039212753A29E834E4DBA4DEEBC717F73D2481CAE28",
255
+ "expected_symbols": ["rotate_logs", "log_file"],
256
+ "expected_edges": ["rotate_logs -> printf"],
257
+ "known_misses": ["log_file"],
258
+ "spurious_edges": ["rotate_logs -> delete_logs"],
259
+ "paraphrase": "cycle archived application log files",
260
+ "analyzer_id": "parser-only:bash:v1"
261
+ },
262
+ {
263
+ "id": "powershell-profile",
264
+ "language": "powershell",
265
+ "source_path": "sources/powershell.ps1",
266
+ "content_hash": "15C73C8B30FF023F6977E6268BC1355C0E21121D95DE3D8D10D81AE1BAF56954",
267
+ "expected_symbols": ["Get-InventoryItem", "ItemId"],
268
+ "expected_edges": ["Get-InventoryItem -> string"],
269
+ "known_misses": ["ItemId"],
270
+ "spurious_edges": ["Get-InventoryItem -> Remove-InventoryItem"],
271
+ "paraphrase": "look up a stock item by its identifier",
272
+ "analyzer_id": "parser-only:powershell:v1"
273
+ },
274
+ {
275
+ "id": "ini-profile",
276
+ "language": "ini",
277
+ "source_path": "sources/ini.ini",
278
+ "content_hash": "FDD0199E49555EA760845F23B7DF6F2178B86FC552A29D1E8A39EAD39E20FF3A",
279
+ "expected_symbols": ["database", "connect_timeout"],
280
+ "expected_edges": ["database -> connect_timeout"],
281
+ "known_misses": ["connect_timeout"],
282
+ "spurious_edges": ["database -> delete_database"],
283
+ "paraphrase": "configure a database connection timeout",
284
+ "analyzer_id": "parser-only:ini:v1"
285
+ },
286
+ {
287
+ "id": "regex-profile",
288
+ "language": "regex",
289
+ "source_path": "sources/regex.regex",
290
+ "content_hash": "1413547E127815DDB2AC3A0B25FC2EAA02F3FD6B453FEF15210BA53A90BA1F90",
291
+ "expected_symbols": ["invoice_lookup", "invoice_id"],
292
+ "expected_edges": ["invoice_lookup -> invoice_id"],
293
+ "known_misses": ["invoice_id"],
294
+ "spurious_edges": ["invoice_lookup -> customer_id"],
295
+ "paraphrase": "match an invoice lookup call",
296
+ "analyzer_id": "parser-only:regex:v1"
297
+ },
298
+ {
299
+ "id": "tsx-profile",
300
+ "language": "tsx",
301
+ "source_path": "sources/tsx.tsx",
302
+ "content_hash": "17C67D0709FD2C10E8E619F3E1AB4A836F36C5CD7E4645DB948CAD67B5BD93EE",
303
+ "expected_symbols": ["InvoiceBadge", "invoiceId"],
304
+ "expected_edges": ["InvoiceBadge -> span"],
305
+ "known_misses": ["invoiceId"],
306
+ "spurious_edges": ["InvoiceBadge -> invoiceId"],
307
+ "paraphrase": "render a billing badge from its identifier",
308
+ "analyzer_id": "parser-only:tsx:v1"
309
+ }
310
+ ]
311
+ }
@@ -0,0 +1 @@
1
+ rotate_logs() { printf '/logs/%s\n' "$1"; }
@@ -0,0 +1 @@
1
+ const char *open_socket(const char *socket_fd) { return socket_fd; }
@@ -0,0 +1 @@
1
+ std::string render_widget(const std::string& widget_id) { return "/widgets/" + widget_id; }
@@ -0,0 +1 @@
1
+ string AuthorizeRequest(string requestId) => "/requests/" + requestId;
@@ -0,0 +1,3 @@
1
+ .notification-banner {
2
+ color: var(--notification-hue);
3
+ }
@@ -0,0 +1 @@
1
+ String decodeToken(String token) => '/tokens/' + token;
@@ -0,0 +1,3 @@
1
+ package configs
2
+
3
+ func ParseConfig(configPath string) string { return "/configs/" + configPath }
@@ -0,0 +1,2 @@
1
+ [database]
2
+ connect_timeout=30
@@ -0,0 +1 @@
1
+ class Webhooks { String sendWebhook(String webhookUrl) { return "/hooks/" + webhookUrl; } }
@@ -0,0 +1,3 @@
1
+ export function loadUserProfile(userId) {
2
+ return fetch(`/users/${userId}`);
3
+ }
@@ -0,0 +1 @@
1
+ fun syncCalendar(calendarId: String): String = "/calendars/$calendarId"
@@ -0,0 +1 @@
1
+ <?php function find_order(string $orderId): string { return '/orders/' . $orderId; }
@@ -0,0 +1 @@
1
+ function Get-InventoryItem { param([string]$ItemId) "/inventory/$ItemId" }
@@ -0,0 +1,2 @@
1
+ def rotate_api_key(api_key):
2
+ return rotate_secret("/keys/" + api_key)