opencode-swarm 7.135.4 → 7.136.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 (49) hide show
  1. package/dist/cli/{config-doctor-fgmemknc.js → config-doctor-q0krbxwv.js} +2 -2
  2. package/dist/cli/{curation-policy-frs28q57.js → curation-policy-v6ywe8qd.js} +2 -2
  3. package/dist/cli/{curator-llm-factory-pr59p535.js → curator-llm-factory-mhwje8rf.js} +12 -12
  4. package/dist/cli/{curator-psq8m2j7.js → curator-tqedvpy1.js} +12 -12
  5. package/dist/cli/{guardrail-explain-ws45zchy.js → guardrail-explain-m0m74hvr.js} +13 -13
  6. package/dist/cli/{guardrail-log-gbzek1pz.js → guardrail-log-5g8x6qc6.js} +3 -3
  7. package/dist/cli/{hive-promoter-gdbg4nyd.js → hive-promoter-s804newd.js} +12 -12
  8. package/dist/cli/{index-vh39nxpx.js → index-1kjg590p.js} +1 -1
  9. package/dist/cli/{index-4g3nq4sh.js → index-2cv1j3rf.js} +1 -1
  10. package/dist/cli/{index-jsp8r6f9.js → index-2w4tsmva.js} +1 -1
  11. package/dist/cli/{index-66w4jjg6.js → index-81dkzncr.js} +35 -35
  12. package/dist/cli/{index-mysdsqtk.js → index-9bk16zkv.js} +1 -1
  13. package/dist/cli/{index-ajehqzvn.js → index-bbejqagj.js} +1 -1
  14. package/dist/cli/{index-g86vfxnk.js → index-bwfzq91q.js} +3 -3
  15. package/dist/cli/{index-ck9rx6j1.js → index-cfz5750k.js} +1 -1
  16. package/dist/cli/{index-xfeg0c0c.js → index-cxq1t7j1.js} +14 -14
  17. package/dist/cli/{index-tegdwx34.js → index-j08trvny.js} +5 -5
  18. package/dist/cli/{index-cg413zhk.js → index-m1hew17b.js} +7 -2
  19. package/dist/cli/{index-5s1q6xcw.js → index-n8j0cnp1.js} +4 -4
  20. package/dist/cli/{index-b34vbxmx.js → index-nw9cn84t.js} +1 -1
  21. package/dist/cli/{index-cgqekdja.js → index-qh9466j3.js} +2 -2
  22. package/dist/cli/{index-ys04j1np.js → index-w58bmwyq.js} +2 -2
  23. package/dist/cli/{index-fx7bn93y.js → index-wpqypdge.js} +2 -2
  24. package/dist/cli/index.js +12 -12
  25. package/dist/cli/{knowledge-escalator-0060q7we.js → knowledge-escalator-f1m2xp5x.js} +3 -3
  26. package/dist/cli/{knowledge-events-yh2qwa6k.js → knowledge-events-rksgem6f.js} +1 -1
  27. package/dist/cli/{knowledge-store-geqaez58.js → knowledge-store-t6d6fr8b.js} +1 -1
  28. package/dist/cli/{knowledge-validator-4zq4vm7t.js → knowledge-validator-5ggzb3j1.js} +4 -4
  29. package/dist/cli/{scan-cursor-nk2rybhq.js → scan-cursor-18fnwr58.js} +2 -2
  30. package/dist/cli/{schema-th3tx32c.js → schema-jw15d8bt.js} +1 -1
  31. package/dist/cli/{skill-generator-1947bbkn.js → skill-generator-3n5y902z.js} +5 -5
  32. package/dist/config/schema.d.ts +11 -1
  33. package/dist/hooks/pr-workflow-gate.d.ts +5 -5
  34. package/dist/hooks/pr-workflow-response-gate.d.ts +32 -1
  35. package/dist/hooks/repo-graph-builder.d.ts +17 -11
  36. package/dist/hooks/repo-graph-injection.d.ts +20 -9
  37. package/dist/hooks/semantic-diff-injection.d.ts +2 -2
  38. package/dist/index.js +142 -141
  39. package/dist/tools/repo-graph/builder.d.ts +55 -1
  40. package/dist/tools/repo-graph/cache.d.ts +12 -36
  41. package/dist/tools/repo-graph/freshness.d.ts +54 -0
  42. package/dist/tools/repo-graph/incremental.d.ts +17 -8
  43. package/dist/tools/repo-graph/query.d.ts +7 -1
  44. package/dist/tools/repo-graph/storage.d.ts +3 -1
  45. package/dist/tools/repo-graph/types.d.ts +31 -1
  46. package/dist/tools/repo-graph.d.ts +5 -3
  47. package/dist/tools/repo-map.d.ts +8 -0
  48. package/dist/utils/path-security.d.ts +22 -0
  49. package/package.json +1 -1
@@ -14,7 +14,7 @@ import { extractFileSymbols } from '../../lang/symbol-graph';
14
14
  import { extractGoSymbols, extractPythonSymbols, extractRustSymbols, extractTSSymbols } from '../symbols';
15
15
  import { extractFileOntology } from './ontology';
16
16
  import { safeRealpathSync } from './safe-realpath';
17
- import type { BuildWorkspaceGraphOptions, GraphEdge, GraphNode, RepoGraph, RepoGraphDiagnostics, SymbolEdge } from './types';
17
+ import type { BuildWorkspaceGraphOptions, GraphEdge, GraphExtractorInputWitness, GraphNode, RepoGraph, RepoGraphDiagnostics, SymbolEdge } from './types';
18
18
  /**
19
19
  * _internals DI seam for the walk clock and graph helpers.
20
20
  * Defaults to the real implementations. Tests can override these to inject
@@ -52,6 +52,8 @@ export declare function isScannableSourcePath(p: string): boolean;
52
52
  * queries.
53
53
  */
54
54
  export declare function isAssetEdge(edge: GraphEdge): boolean;
55
+ /** Correctness witnesses are not display diagnostics and must cover the full walk. */
56
+ export declare const MAX_EXTRACTOR_INPUT_WITNESSES = 100256;
55
57
  /**
56
58
  * Add or update a node in the graph.
57
59
  * @param graph - The graph to modify
@@ -144,6 +146,56 @@ declare function parseFileImports(rawContent: string, sourceFile?: string, works
144
146
  * @returns the *exported* names (binding.imported) judged to be used.
145
147
  */
146
148
  declare function computeUsedSymbols(strippedContent: string, bindings: readonly ImportBinding[]): string[];
149
+ /**
150
+ * Return whether a path is a graph-wide extractor input. Changes to these
151
+ * manifests can alter package-boundary ontology for many nodes, so consumers
152
+ * must rebuild rather than treating them as an ordinary one-file refresh.
153
+ */
154
+ export declare function isGraphWideInputPath(filePath: string): boolean;
155
+ /**
156
+ * Async, chunked, cycle-safe equivalent of `findSourceFiles`.
157
+ *
158
+ * Yields to the event loop every `ASYNC_WALK_YIELD_INTERVAL` entries so the
159
+ * Node/Bun macrotask queue continues to drain while the walk runs. This is
160
+ * the variant called from the plugin init path; the sync variant remains
161
+ * available for non-init callers (tools, tests) for compatibility.
162
+ */
163
+ export interface RepoGraphInputMetadata {
164
+ absolutePath: string;
165
+ kind: 'source' | 'manifest';
166
+ sizeBytes: number;
167
+ mtimeMs: number;
168
+ }
169
+ export interface RepoGraphInputWalkResult {
170
+ sourceFiles: string[];
171
+ manifestFiles: string[];
172
+ metadata: RepoGraphInputMetadata[];
173
+ manifestDirs: Set<string>;
174
+ truncated: boolean;
175
+ truncationReason?: 'budget' | 'cap';
176
+ incomplete: boolean;
177
+ unreadableDirectories: string[];
178
+ unreadableFiles: string[];
179
+ probedFiles: number;
180
+ elapsedMs: number;
181
+ }
182
+ export interface RepoGraphInputWalkOptions {
183
+ walkBudgetMs?: number;
184
+ maxFiles?: number;
185
+ followSymlinks?: boolean;
186
+ excludeDirs?: readonly string[];
187
+ /** Capture size/mtime for every source and manifest during this same walk. */
188
+ captureMetadata?: boolean;
189
+ /** Capture only graph-wide manifest metadata (used by the graph builder). */
190
+ captureManifestMetadata?: boolean;
191
+ }
192
+ /**
193
+ * Enumerate every input used by repository-graph extraction with the same
194
+ * bounded, deterministic, cycle-safe traversal as the async graph builder.
195
+ * Directory and metadata I/O failures are surfaced through `incomplete` so a
196
+ * caller can refuse removals/certification instead of guessing.
197
+ */
198
+ export declare function walkRepoGraphInputs(dir: string, options?: RepoGraphInputWalkOptions): Promise<RepoGraphInputWalkResult>;
147
199
  /**
148
200
  * Result of scanning a single file for graph updates.
149
201
  */
@@ -164,6 +216,8 @@ export interface AsyncScanResult {
164
216
  symbolEdges: SymbolEdge[];
165
217
  /** Optional file-level diagnostics collected during async scanning. */
166
218
  diagnostics?: RepoGraphDiagnostics;
219
+ /** Build-time witness for a deterministic non-node skip. */
220
+ inputWitness?: GraphExtractorInputWitness;
167
221
  }
168
222
  /**
169
223
  * Scan a single file and extract its graph node and edges.
@@ -1,48 +1,24 @@
1
1
  /**
2
- * In-memory cache for loaded repo graphs.
2
+ * Bounded in-memory cache for loaded repo graphs.
3
3
  *
4
- * Three maps keyed by normalized workspace path:
5
- * - graphCache — the last loaded/saved RepoGraph for each workspace
6
- * - dirtyFlags — whether the cached graph has been modified since the last save
7
- * - mtimeCache — the file mtime at the time the graph was last loaded/saved,
8
- * used by the optimistic concurrency check in incremental.ts
9
- *
10
- * All public functions normalize the workspace path before use so callers
11
- * are not required to pre-normalize.
4
+ * Graph, dirty, and mtime state intentionally share one entry so eviction can
5
+ * never leave one piece of workspace state behind. Entries are keyed by an
6
+ * absolute normalized workspace path and maintained as a true LRU: every read
7
+ * moves the entry to the newest position and insertion evicts the oldest.
12
8
  */
13
9
  import type { RepoGraph } from './types';
14
- /**
15
- * Get the cached graph for a workspace.
16
- * @param workspace - The workspace directory (absolute or relative path)
17
- * @returns The cached graph or undefined if not cached
18
- */
10
+ /** Return the cached graph for a workspace, if present. */
19
11
  export declare function getCachedGraph(workspace: string): RepoGraph | undefined;
20
12
  /**
21
- * Set the cached graph for a workspace.
22
- * @param workspace - The workspace directory (absolute or relative path)
23
- * @param graph - The graph to cache
24
- * @param mtime - Optional file mtime to track for cache invalidation
13
+ * Cache a graph and mark it clean. Omitting mtime clears any previous mtime so
14
+ * an old optimistic-concurrency witness cannot survive a new graph value.
25
15
  */
26
16
  export declare function setCachedGraph(workspace: string, graph: RepoGraph, mtime?: number): void;
27
- /**
28
- * Mark a workspace's cache as dirty (modified since last save).
29
- * @param workspace - The workspace directory (absolute or relative path)
30
- */
17
+ /** Mark a workspace's cached state dirty, preserving its graph and mtime. */
31
18
  export declare function markDirty(workspace: string): void;
32
- /**
33
- * Check if a workspace's cache is dirty.
34
- * @param workspace - The workspace directory (absolute or relative path)
35
- * @returns True if the cache has been modified since last save
36
- */
19
+ /** Return whether the workspace's cached state is dirty. */
37
20
  export declare function isDirty(workspace: string): boolean;
38
- /**
39
- * Clear the cache for a workspace.
40
- * @param workspace - The workspace directory (absolute or relative path)
41
- */
21
+ /** Remove all cached state for one workspace. */
42
22
  export declare function clearCache(workspace: string): void;
43
- /**
44
- * Get the cached file mtime for a workspace (used for optimistic concurrency).
45
- * @param workspace - The workspace directory (absolute or relative path)
46
- * @returns The cached mtime in milliseconds, or undefined if not cached
47
- */
23
+ /** Return the graph-file mtime captured with the cached graph, if present. */
48
24
  export declare function getCachedMtime(workspace: string): number | undefined;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Bounded content-freshness certification for repository graphs.
3
+ *
4
+ * A probe is one bounded readdir+stat directory walk, not a stat pass over
5
+ * already-known graph nodes. It reads no source contents and performs no
6
+ * parsing, so it is much cheaper than graph construction while still finding
7
+ * additions and removals. The sidecar deliberately fingerprints metadata
8
+ * (byte size + numeric mtime), not file bytes, so a tool that preserves both
9
+ * values can evade detection. Results may also be cached for up to 30 seconds.
10
+ * Callers must therefore treat `inconclusive` as unknown and may mutate/delete
11
+ * only after a complete `drifted` probe.
12
+ */
13
+ import * as fsPromises from 'node:fs/promises';
14
+ import { bunWrite } from '../../utils/bun-compat';
15
+ import { walkRepoGraphInputs } from './builder';
16
+ import type { FreshnessProbeState, RepoGraph } from './types';
17
+ export declare const REPO_GRAPH_FINGERPRINT_FILENAME = "repo-graph.fingerprint.json";
18
+ export declare const FINGERPRINT_SCHEMA_VERSION = 1;
19
+ export declare const EXTRACTOR_STAMP: string;
20
+ export interface FreshnessOptions {
21
+ walkBudgetMs?: number;
22
+ maxFiles?: number;
23
+ followSymlinks?: boolean;
24
+ excludeDirs?: readonly string[];
25
+ }
26
+ export interface FreshnessProbe {
27
+ state: FreshnessProbeState;
28
+ /** Absolute paths positively observed as new or metadata-changed. */
29
+ changed: string[];
30
+ /** Absolute paths absent from a complete walk. Empty when inconclusive. */
31
+ removed: string[];
32
+ truncated: boolean;
33
+ probedFiles: number;
34
+ elapsedMs: number;
35
+ }
36
+ export declare const _internals: {
37
+ now: () => number;
38
+ walkRepoGraphInputs: typeof walkRepoGraphInputs;
39
+ open: typeof fsPromises.open;
40
+ bunWrite: typeof bunWrite;
41
+ fsRename: typeof fsPromises.rename;
42
+ fsUnlink: typeof fsPromises.unlink;
43
+ retryDelayMs: number;
44
+ };
45
+ /** Invalidate one project's probe cache, or every entry when root is omitted. */
46
+ export declare function invalidateFreshnessCache(root?: string): void;
47
+ /** Probe workspace metadata using a bounded per-directory 16-entry LRU cache. */
48
+ export declare function probeFreshness(root: string, options?: FreshnessOptions): Promise<FreshnessProbe>;
49
+ /**
50
+ * Atomically persist a sidecar only when a complete walk certifies that the
51
+ * graph and every intentional stable skip match current metadata. Never
52
+ * throws; `false` means the graph remains deliberately uncertified.
53
+ */
54
+ export declare function writeFingerprint(root: string, graph: RepoGraph, options?: FreshnessOptions): Promise<boolean>;
@@ -15,16 +15,27 @@
15
15
  * rebuild on every incremental update.
16
16
  */
17
17
  import { type Stats } from 'node:fs';
18
+ import { buildWorkspaceGraphAsync, scanFileAsync } from './builder';
19
+ import { writeFingerprint } from './freshness';
20
+ import { saveGraph } from './storage';
21
+ import type { BuildWorkspaceGraphOptions, RepoGraph } from './types';
22
+ /** Public options shared by hook, read-repair, and direct callers. */
23
+ export interface IncrementalUpdateOptions {
24
+ forceRebuild?: boolean;
25
+ /** Bounds and exclusions used by both direct and fallback full builds. */
26
+ buildOptions?: BuildWorkspaceGraphOptions;
27
+ }
18
28
  /**
19
- * DI seam for the optimistic-concurrency stat check (defect A4). Tests override
20
- * `stat` to inject deterministic mtime shifts between load and the pre-save
21
- * re-check, exercising the reload-and-replay branch without races. Defaults to
22
- * the real `fsPromises.stat`. Restore in afterEach.
29
+ * DI seam for concurrency, scan-failure, and paired-persistence tests. Tests
30
+ * must restore every replaced entry in afterEach.
23
31
  */
24
32
  export declare const _internals: {
25
33
  stat: (path: string) => Promise<Stats>;
34
+ scanFileAsync: typeof scanFileAsync;
35
+ buildWorkspaceGraphAsync: typeof buildWorkspaceGraphAsync;
36
+ saveGraph: typeof saveGraph;
37
+ writeFingerprint: typeof writeFingerprint;
26
38
  };
27
- import type { RepoGraph } from './types';
28
39
  /**
29
40
  * Incrementally update the graph for a set of changed files.
30
41
  * Re-scans only the specified files, updates their nodes and edges,
@@ -36,6 +47,4 @@ import type { RepoGraph } from './types';
36
47
  * @param options.forceRebuild - Force a full rebuild instead of incremental
37
48
  * @returns Updated RepoGraph
38
49
  */
39
- export declare function updateGraphForFiles(workspaceRoot: string, filePaths: string[], options?: {
40
- forceRebuild?: boolean;
41
- }): Promise<RepoGraph>;
50
+ export declare function updateGraphForFiles(workspaceRoot: string, filePaths: string[], options?: IncrementalUpdateOptions): Promise<RepoGraph>;
@@ -1,8 +1,14 @@
1
+ import type { FreshnessProbe } from './freshness';
1
2
  import type { BlastRadiusResult, CallerReference, ContextPackResult, DeadExportsResult, FileOntology, FileReference, GraphHealthResult, GraphNode, LocalizationBlock, PackageBoundarySummary, RepoGraph, SymbolReference } from './types';
2
3
  export declare function getGraphNode(graph: RepoGraph, input: string): GraphNode | undefined;
3
4
  export declare function resetQueryCache(): void;
5
+ /**
6
+ * @deprecated Graph age is not a content-freshness signal. Internal consumers
7
+ * use {@link probeFreshness}; this compatibility helper intentionally retains
8
+ * its historical five-minute TTL semantics for external callers.
9
+ */
4
10
  export declare function isGraphFresh(graph: RepoGraph | null, maxAgeMs?: number): boolean;
5
- export declare function getGraphHealth(graph: RepoGraph | null, workspaceRoot?: string): GraphHealthResult;
11
+ export declare function getGraphHealth(graph: RepoGraph | null, workspaceRoot?: string, probe?: FreshnessProbe): GraphHealthResult;
6
12
  export declare function getImporters(graph: RepoGraph, filePath: string): FileReference[];
7
13
  export declare function getDependencies(graph: RepoGraph, filePath: string): FileReference[];
8
14
  export declare function getSymbolConsumers(graph: RepoGraph, filePath: string, symbolName: string): SymbolReference[];
@@ -6,6 +6,7 @@
6
6
  * cache. Symlink resolution guards against workspace-escape attacks.
7
7
  */
8
8
  import * as fsPromises from 'node:fs/promises';
9
+ import { type FreshnessOptions, writeFingerprint } from './freshness';
9
10
  import { safeRealpathSync } from './safe-realpath';
10
11
  import type { RepoGraph } from './types';
11
12
  /**
@@ -20,6 +21,7 @@ export declare const _internals: {
20
21
  safeRealpathSync: typeof safeRealpathSync;
21
22
  fsRename: typeof fsPromises.rename;
22
23
  retryDelayMs: number;
24
+ writeFingerprint: typeof writeFingerprint;
23
25
  };
24
26
  /**
25
27
  * Get the validated path for the repo-graph.json file.
@@ -75,4 +77,4 @@ export declare function loadOrCreateGraph(workspace: string): Promise<RepoGraph>
75
77
  * @throws Error if workspace is dirty but cache is missing (inconsistent state)
76
78
  * @throws Error if save fails
77
79
  */
78
- export declare function saveIfDirty(workspace: string): Promise<void>;
80
+ export declare function saveIfDirty(workspace: string, freshnessOptions?: FreshnessOptions): Promise<void>;
@@ -35,8 +35,14 @@ export declare const REPO_GRAPH_FILENAME = "repo-graph.json";
35
35
  * Diagnostics are additive and optional on all schema versions. Old graphs
36
36
  * without diagnostics remain readable; graph-health queries surface empty
37
37
  * diagnostics with an explicit rebuild note.
38
+ *
39
+ * 1.4.0 adds optional numeric `sizeBytes` and `mtimeMs` witnesses to each
40
+ * node. Builders capture them from the same stat used immediately before the
41
+ * source read. The content-freshness sidecar requires both witnesses before
42
+ * it will certify a graph; older graphs remain readable but are intentionally
43
+ * treated as needing a rebuild before certification.
38
44
  */
39
- export declare const GRAPH_SCHEMA_VERSION = "1.3.0";
45
+ export declare const GRAPH_SCHEMA_VERSION = "1.4.0";
40
46
  /**
41
47
  * Compare dotted numeric version strings (e.g. '1.1.0' >= '1.1.0').
42
48
  * Missing/non-numeric segments are treated as 0. Returns true when `version`
@@ -132,6 +138,10 @@ export interface GraphNode {
132
138
  language: string;
133
139
  /** Last modified timestamp */
134
140
  mtime: string;
141
+ /** Exact byte size captured by the stat that preceded the source read. */
142
+ sizeBytes?: number;
143
+ /** Numeric mtime captured with `sizeBytes`; avoids ISO precision loss. */
144
+ mtimeMs?: number;
135
145
  /** Optional code ontology facts for agent context/preflight packets */
136
146
  ontology?: FileOntology;
137
147
  }
@@ -280,6 +290,14 @@ export interface GraphUnresolvedImport {
280
290
  file: string;
281
291
  specifier: string;
282
292
  }
293
+ /** Build-time metadata witness for a non-node extractor input. */
294
+ export interface GraphExtractorInputWitness {
295
+ /** Normalized workspace-relative path. */
296
+ file: string;
297
+ kind: 'manifest' | 'stable-skip';
298
+ sizeBytes: number;
299
+ mtimeMs: number;
300
+ }
283
301
  export interface RepoGraphDiagnostics {
284
302
  extractionFailures?: GraphExtractionFailure[];
285
303
  unresolvedImports?: GraphUnresolvedImport[];
@@ -287,6 +305,14 @@ export interface RepoGraphDiagnostics {
287
305
  unsupportedFiles?: string[];
288
306
  binaryFiles?: string[];
289
307
  unreadableFiles?: string[];
308
+ /** Source files intentionally skipped because their extracted node failed validation. */
309
+ validationSkippedFiles?: string[];
310
+ /**
311
+ * Build-time witnesses for manifests and deterministic non-node skips.
312
+ * Persistence compares them against its live walk so an edit between graph
313
+ * extraction and sidecar persistence cannot be blessed as clean.
314
+ */
315
+ extractorInputWitnesses?: GraphExtractorInputWitness[];
290
316
  lowConfidenceEdgeCount?: number;
291
317
  /**
292
318
  * True when the last workspace walk was truncated by the file cap or wall-
@@ -306,6 +332,7 @@ export interface RepoGraphDiagnostics {
306
332
  export interface GraphHealthResult {
307
333
  schemaVersion: string | null;
308
334
  fresh: boolean;
335
+ probeState: FreshnessProbeState;
309
336
  staleFiles: string[];
310
337
  extractionFailures: GraphExtractionFailure[];
311
338
  unresolvedImports: GraphUnresolvedImport[];
@@ -313,12 +340,15 @@ export interface GraphHealthResult {
313
340
  unsupportedFiles: string[];
314
341
  binaryFiles: string[];
315
342
  unreadableFiles: string[];
343
+ validationSkippedFiles: string[];
316
344
  lowConfidenceEdgeCount: number;
317
345
  walkTruncated: boolean;
318
346
  walkTruncationReason: 'budget' | 'cap' | null;
319
347
  incrementalFallbacks: number;
320
348
  notes: string[];
321
349
  }
350
+ /** Authoritative states returned by the bounded repository freshness probe. */
351
+ export type FreshnessProbeState = 'clean' | 'drifted' | 'no-fingerprint' | 'inconclusive';
322
352
  export interface BlastRadiusResult {
323
353
  target: string[];
324
354
  directDependents: string[];
@@ -14,15 +14,17 @@
14
14
  *
15
15
  * All existing imports of this module continue to work unchanged.
16
16
  */
17
- export type { ScanResult } from './repo-graph/builder';
18
- export { addEdge, buildWorkspaceGraph, buildWorkspaceGraphAsync, isScannableSourcePath, resolveModuleSpecifier, upsertNode, } from './repo-graph/builder';
17
+ export type { RepoGraphInputMetadata, RepoGraphInputWalkOptions, RepoGraphInputWalkResult, ScanResult, } from './repo-graph/builder';
18
+ export { addEdge, buildWorkspaceGraph, buildWorkspaceGraphAsync, isGraphWideInputPath, isScannableSourcePath, resolveModuleSpecifier, upsertNode, walkRepoGraphInputs, } from './repo-graph/builder';
19
19
  export { clearCache, getCachedGraph, getCachedMtime, isDirty, markDirty, setCachedGraph, } from './repo-graph/cache';
20
+ export type { FreshnessOptions, FreshnessProbe, } from './repo-graph/freshness';
21
+ export { EXTRACTOR_STAMP, FINGERPRINT_SCHEMA_VERSION, invalidateFreshnessCache, probeFreshness, REPO_GRAPH_FINGERPRINT_FILENAME, writeFingerprint, } from './repo-graph/freshness';
20
22
  export { updateGraphForFiles } from './repo-graph/incremental';
21
23
  export type { ExtractFileOntologyInput } from './repo-graph/ontology';
22
24
  export { extractFileOntology } from './repo-graph/ontology';
23
25
  export type { DeadExportsOptions } from './repo-graph/query';
24
26
  export { buildOntologyPreflightPacket, getBlastRadius, getCallers, getContextPack, getDeadExports, getDependencies, getFileOntology, getGraphHealth, getGraphNode, getImporters, getKeyFiles, getLocalizationContext, getPackageBoundaries, getSymbolConsumers, isGraphFresh, resetQueryCache, } from './repo-graph/query';
25
27
  export { getGraphPath, loadGraph, loadGraphSync, loadOrCreateGraph, saveGraph, saveIfDirty, } from './repo-graph/storage';
26
- export type { BlastRadiusResult, BuildWorkspaceGraphOptions, CallerReference, ContextPackResult, ContextPackSpan, ConventionFact, DataOperationFact, DeadExportCandidate, DeadExportsResult, FileOntology, FileReference, FileRole, GraphEdge, GraphExtractionFailure, GraphHealthResult, GraphNode, GraphUnresolvedImport, LocalizationBlock, OntologyFinding, PackageBoundarySummary, RepoGraph, RepoGraphDiagnostics, RouteFact, RouteMethod, SecurityFact, SymbolEdge, SymbolReference, } from './repo-graph/types';
28
+ export type { BlastRadiusResult, BuildWorkspaceGraphOptions, CallerReference, ContextPackResult, ContextPackSpan, ConventionFact, DataOperationFact, DeadExportCandidate, DeadExportsResult, FileOntology, FileReference, FileRole, FreshnessProbeState, GraphEdge, GraphExtractionFailure, GraphExtractorInputWitness, GraphHealthResult, GraphNode, GraphUnresolvedImport, LocalizationBlock, OntologyFinding, PackageBoundarySummary, RepoGraph, RepoGraphDiagnostics, RouteFact, RouteMethod, SecurityFact, SymbolEdge, SymbolReference, } from './repo-graph/types';
27
29
  export { createEmptyGraph, GRAPH_SCHEMA_VERSION, isSchemaVersionAtLeast, normalizeGraphPath, REPO_GRAPH_FILENAME, updateGraphMetadata, } from './repo-graph/types';
28
30
  export { validateGraphEdge, validateGraphNode, validateWorkspace, } from './repo-graph/validation';
@@ -1,2 +1,10 @@
1
+ import { loadPluginConfigWithMeta } from '../config/loader';
1
2
  import { createSwarmTool } from './create-tool';
3
+ import { probeFreshness, updateGraphForFiles, writeFingerprint } from './repo-graph';
4
+ export declare const _internals: {
5
+ loadPluginConfigWithMeta: typeof loadPluginConfigWithMeta;
6
+ probeFreshness: typeof probeFreshness;
7
+ updateGraphForFiles: typeof updateGraphForFiles;
8
+ writeFingerprint: typeof writeFingerprint;
9
+ };
2
10
  export declare const repo_map: ReturnType<typeof createSwarmTool>;
@@ -43,6 +43,28 @@ export declare function validateDirectory(directory: string): void;
43
43
  * both fallback branches keeps the comparison basis consistent whether
44
44
  * realpathSync succeeds or not, independent of incidental filesystem state.
45
45
  *
46
+ * Not-yet-existing targets (e.g. a file about to be created by an atomic
47
+ * write) are handled the same way: realpathSync on the full target throws
48
+ * ENOENT, so resolution falls back to `resolveNearestExistingCanonical`,
49
+ * which walks up to the nearest existing ancestor, resolves symlinks on
50
+ * that ancestor (and everything above it), and rejoins the not-yet-existing
51
+ * tail. Without this, a target under a workspace root that itself sits
52
+ * behind a symlink (e.g. macOS `/tmp` and `/var`, which are symlinks to
53
+ * `/private/tmp` and `/private/var`) would resolve to its unresolved literal
54
+ * path while the (already-existing) root resolves to its `/private/...`
55
+ * form, producing a spurious boundary-escape error even though the target
56
+ * is genuinely inside the root. See issue #1986.
57
+ *
58
+ * This also TIGHTENS containment versus the pre-#1986-fix behavior in one
59
+ * case: if `.swarm/` or any other ancestor between the target and the
60
+ * workspace root is itself a symlink/junction pointing outside the
61
+ * workspace, the old fallback (unresolved `path.resolve`) could let a
62
+ * not-yet-existing target through on its first write; the ancestor walk now
63
+ * resolves that symlinked ancestor and correctly throws. If a deployment
64
+ * relies on a symlinked `.swarm/` (or similar) pointing outside the
65
+ * workspace root, that setup will now be rejected — this is the intended,
66
+ * correct behavior, not a regression.
67
+ *
46
68
  * @param targetPath - The path to validate (absolute)
47
69
  * @param rootPath - The root directory boundary (absolute)
48
70
  * @throws Error if the resolved target escapes the root boundary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.135.4",
3
+ "version": "7.136.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",