opencode-swarm 7.107.2 → 7.107.4
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/consult/SKILL.md +10 -0
- package/.opencode/skills/council/SKILL.md +10 -0
- package/.opencode/skills/engineering-conventions/SKILL.md +20 -0
- package/README.md +2 -2
- package/dist/agents/agent-output-schema.d.ts +1 -1
- package/dist/cli/{config-doctor-cntnpyvj.js → config-doctor-kdq3vae4.js} +3 -2
- package/dist/cli/{curator-drift-6ad8mxxb.js → curator-drift-ed7p5mfy.js} +2 -2
- package/dist/cli/{curator-llm-factory-r3m5e7n8.js → curator-llm-factory-abw56kg0.js} +18 -13
- package/dist/cli/{curator-6zvpn7fs.js → curator-rb05fjjk.js} +18 -13
- package/dist/cli/{dispatch-e4ejrsz8.js → dispatch-anmxxhen.js} +56 -13
- package/dist/cli/{evidence-summary-service-7nwhd8s4.js → evidence-summary-service-nwdfnbz1.js} +4 -4
- package/dist/cli/gate-evidence-ywys9vfs.js +1 -1
- package/dist/cli/guardrail-explain-dayy7zw4.js +37 -0
- package/dist/cli/{guardrail-log-fsc85hwa.js → guardrail-log-fjypsmek.js} +4 -3
- package/dist/cli/{hive-promoter-nwcsha2j.js → hive-promoter-34bdmw1w.js} +18 -13
- package/dist/cli/{index-r87xhtmx.js → index-19vxtwa6.js} +22 -17
- package/dist/cli/{index-t4hbye3v.js → index-4r5z8sgw.js} +4 -4
- package/dist/cli/{index-fxtrk7y8.js → index-4vsgp5a8.js} +2 -2
- package/dist/cli/{index-mpe0yk9s.js → index-57ymmh7h.js} +5 -3
- package/dist/cli/{index-357p0baj.js → index-91j1sqzm.js} +14 -2
- package/dist/cli/{index-f12bmedv.js → index-9b7a6agd.js} +91 -34
- package/dist/cli/index-bfwt3abw.js +14 -0
- package/dist/cli/{index-9wstcavp.js → index-bpgqbwmf.js} +115 -1019
- package/dist/cli/index-bq8kd9r9.js +199 -0
- package/dist/cli/index-dfdg4ws5.js +741 -0
- package/dist/cli/{index-jr54w7pb.js → index-f45hbd5x.js} +2 -2
- package/dist/cli/{index-168p3bfr.js → index-gyzxeza3.js} +910 -608
- package/dist/cli/index-kxm3bdjh.js +631 -0
- package/dist/cli/index-n1sptn1w.js +147 -0
- package/dist/cli/{index-2560cctg.js → index-pchpahdf.js} +11 -0
- package/dist/cli/{index-esg1554h.js → index-wvxhynxq.js} +1 -1
- package/dist/cli/{index-8w4d325g.js → index-xg18az81.js} +61 -22
- package/dist/cli/{index-f7nma02k.js → index-xmarctsf.js} +137 -175
- package/dist/cli/{index-w8dzxnx4.js → index-zej8cy0j.js} +1 -1
- package/dist/cli/index.js +18 -13
- package/dist/cli/knowledge-escalator-3sgwrgy9.js +32 -0
- package/dist/cli/knowledge-events-kfc6xmkw.js +62 -0
- package/dist/cli/{knowledge-store-tsa8ezka.js → knowledge-store-kyacem71.js} +3 -1
- package/dist/cli/knowledge-validator-ez3ws8ef.js +57 -0
- package/dist/cli/{pending-delegations-46xf2n2e.js → pending-delegations-vfnpm8zt.js} +4 -4
- package/dist/cli/{pr-subscriptions-3c34rnm1.js → pr-subscriptions-bpvazmsw.js} +3 -3
- package/dist/cli/{schema-vw2ffhe9.js → schema-x0ekqzvs.js} +2 -1
- package/dist/cli/{skill-generator-y6mmq8n5.js → skill-generator-x83re96d.js} +6 -2
- package/dist/commands/knowledge.d.ts +5 -1
- package/dist/commands/registry.d.ts +2 -2
- package/dist/config/evidence-schema.d.ts +9 -9
- package/dist/config/schema.d.ts +42 -12
- package/dist/hooks/guardrails/file-authority.d.ts +1 -1
- package/dist/hooks/knowledge-curator.d.ts +27 -0
- package/dist/hooks/knowledge-escalator.d.ts +16 -0
- package/dist/hooks/knowledge-events.d.ts +11 -0
- package/dist/hooks/knowledge-injector.d.ts +3 -0
- package/dist/hooks/knowledge-store.d.ts +16 -1
- package/dist/hooks/knowledge-types.d.ts +85 -0
- package/dist/hooks/knowledge-validator.d.ts +15 -0
- package/dist/hooks/semantic-diff-injection.d.ts +19 -0
- package/dist/hooks/skill-usage-log.d.ts +3 -0
- package/dist/index.js +354 -353
- package/dist/memory/consolidation.d.ts +1 -1
- package/dist/memory/schema.d.ts +4 -4
- package/dist/sast/rules/rust.d.ts +6 -0
- package/dist/services/directive-predicate-runner.d.ts +1 -1
- package/dist/tools/knowledge-archive.d.ts +6 -2
- package/dist/tools/knowledge-remove.d.ts +11 -0
- package/dist/tools/lint.d.ts +2 -2
- package/dist/tools/secretscan.d.ts +16 -0
- package/dist/tools/test-runner.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cli/guardrail-explain-zajegz3a.js +0 -32
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
getGlobalEventBus
|
|
4
|
+
} from "./index-c8s9a3zh.js";
|
|
2
5
|
import {
|
|
3
6
|
detectStraySwarmDirs,
|
|
4
7
|
readDoctorArtifact,
|
|
5
8
|
removeStraySwarmDir,
|
|
6
9
|
runConfigDoctor
|
|
7
|
-
} from "./index-
|
|
10
|
+
} from "./index-wvxhynxq.js";
|
|
8
11
|
import {
|
|
9
12
|
MAX_TRANSIENT_RETRIES,
|
|
10
13
|
PlanSchema,
|
|
@@ -44,13 +47,22 @@ import {
|
|
|
44
47
|
savePlan,
|
|
45
48
|
transientBackoff,
|
|
46
49
|
validateProjectRoot
|
|
47
|
-
} from "./index-
|
|
50
|
+
} from "./index-9b7a6agd.js";
|
|
51
|
+
import {
|
|
52
|
+
buildOpenSpecProjectionSync,
|
|
53
|
+
detectSpeckit,
|
|
54
|
+
loadSddStatusSync,
|
|
55
|
+
readEffectiveSpecSync,
|
|
56
|
+
resolveSpeckitProjection,
|
|
57
|
+
validateSpeckit,
|
|
58
|
+
writeProjectedSpecSync
|
|
59
|
+
} from "./index-91j1sqzm.js";
|
|
48
60
|
import {
|
|
49
61
|
_internals as _internals2,
|
|
50
62
|
_internals1 as _internals3,
|
|
51
63
|
isCommandAvailable,
|
|
52
64
|
tool
|
|
53
|
-
} from "./index-
|
|
65
|
+
} from "./index-xg18az81.js";
|
|
54
66
|
import {
|
|
55
67
|
CURATOR_INIT_PROMPT,
|
|
56
68
|
CURATOR_PHASE_PROMPT,
|
|
@@ -69,33 +81,42 @@ import {
|
|
|
69
81
|
getCanonicalAgentRole,
|
|
70
82
|
resolveExternalSkillsConfig,
|
|
71
83
|
stripKnownSwarmPrefix
|
|
72
|
-
} from "./index-
|
|
84
|
+
} from "./index-pchpahdf.js";
|
|
73
85
|
import {
|
|
74
86
|
DEFAULT_SKILL_MIN_CONFIDENCE,
|
|
75
87
|
DEFAULT_SKILL_MIN_CONFIRMATIONS,
|
|
76
88
|
appendRejectedSkillEdit,
|
|
77
89
|
appendSkillChangelog,
|
|
78
|
-
appendUnactionable,
|
|
79
90
|
autoApplyProposals,
|
|
80
|
-
effectiveRetrievalOutcomes,
|
|
81
91
|
evaluateSkillChange,
|
|
82
92
|
generateSkills,
|
|
83
93
|
listSkills,
|
|
84
94
|
parseDraftFrontmatter,
|
|
85
|
-
quarantineEntry,
|
|
86
|
-
readKnowledgeCounterRollups,
|
|
87
|
-
readKnowledgeEvents,
|
|
88
95
|
regenerateSkill,
|
|
89
|
-
resolveKnowledgeEventsPath,
|
|
90
|
-
resolveUnactionablePath,
|
|
91
|
-
restoreEntry,
|
|
92
96
|
retireOrMarkStale,
|
|
93
97
|
retireSkill,
|
|
94
|
-
selectCandidateEntries
|
|
98
|
+
selectCandidateEntries
|
|
99
|
+
} from "./index-bpgqbwmf.js";
|
|
100
|
+
import {
|
|
101
|
+
appendUnactionable,
|
|
102
|
+
quarantineEntry,
|
|
103
|
+
resolveUnactionablePath,
|
|
104
|
+
restoreEntry,
|
|
105
|
+
unarchiveEntry,
|
|
95
106
|
validateActionability,
|
|
96
107
|
validateActionableFields,
|
|
97
108
|
validateLesson
|
|
98
|
-
} from "./index-
|
|
109
|
+
} from "./index-dfdg4ws5.js";
|
|
110
|
+
import {
|
|
111
|
+
readRecentEscalations
|
|
112
|
+
} from "./index-bq8kd9r9.js";
|
|
113
|
+
import {
|
|
114
|
+
effectiveRetrievalOutcomes,
|
|
115
|
+
readKnowledgeCounterRollups,
|
|
116
|
+
readKnowledgeEvents,
|
|
117
|
+
recordKnowledgeEvent,
|
|
118
|
+
resolveKnowledgeEventsPath
|
|
119
|
+
} from "./index-kxm3bdjh.js";
|
|
99
120
|
import {
|
|
100
121
|
appendKnowledge,
|
|
101
122
|
appendRejectedLesson,
|
|
@@ -107,36 +128,31 @@ import {
|
|
|
107
128
|
findNearDuplicate,
|
|
108
129
|
getArchivedKnowledgeIds,
|
|
109
130
|
inferTags,
|
|
110
|
-
isLinked,
|
|
111
131
|
normalize,
|
|
112
132
|
readKnowledge,
|
|
113
|
-
readLinkPointer,
|
|
114
133
|
readRejectedLessons,
|
|
115
134
|
readRetractionRecords,
|
|
116
|
-
removeLinkPointer,
|
|
117
135
|
resolveHiveKnowledgePath,
|
|
118
136
|
resolveHiveRejectedPath,
|
|
119
|
-
resolveKnowledgeStoreDir,
|
|
120
|
-
resolveLinkDir,
|
|
121
137
|
resolveSwarmKnowledgePath,
|
|
122
138
|
rewriteKnowledge,
|
|
123
|
-
sanitizeLinkId,
|
|
124
139
|
transactFile,
|
|
125
|
-
transactKnowledge
|
|
126
|
-
|
|
127
|
-
} from "./index-f7nma02k.js";
|
|
140
|
+
transactKnowledge
|
|
141
|
+
} from "./index-xmarctsf.js";
|
|
128
142
|
import {
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
isLinked,
|
|
144
|
+
readLinkPointer,
|
|
145
|
+
removeLinkPointer,
|
|
146
|
+
resolveKnowledgeStoreDir,
|
|
147
|
+
resolveLinkDir,
|
|
148
|
+
sanitizeLinkId,
|
|
149
|
+
writeLinkPointer
|
|
150
|
+
} from "./index-n1sptn1w.js";
|
|
131
151
|
import {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
resolveSpeckitProjection,
|
|
137
|
-
validateSpeckit,
|
|
138
|
-
writeProjectedSpecSync
|
|
139
|
-
} from "./index-357p0baj.js";
|
|
152
|
+
KNOWLEDGE_SCHEMA_VERSION,
|
|
153
|
+
OUTCOME_BLOCK_THRESHOLD,
|
|
154
|
+
isActiveStatus
|
|
155
|
+
} from "./index-bfwt3abw.js";
|
|
140
156
|
import {
|
|
141
157
|
SandboxCapabilityProbe,
|
|
142
158
|
_internals,
|
|
@@ -154,12 +170,12 @@ import {
|
|
|
154
170
|
listActive,
|
|
155
171
|
subscribe,
|
|
156
172
|
unsubscribe
|
|
157
|
-
} from "./index-
|
|
173
|
+
} from "./index-4r5z8sgw.js";
|
|
158
174
|
import {
|
|
159
175
|
readSwarmFileAsync,
|
|
160
176
|
safeHook,
|
|
161
177
|
validateSwarmPath
|
|
162
|
-
} from "./index-
|
|
178
|
+
} from "./index-57ymmh7h.js";
|
|
163
179
|
import {
|
|
164
180
|
deepMerge
|
|
165
181
|
} from "./index-p0arc26j.js";
|
|
@@ -169,13 +185,13 @@ import {
|
|
|
169
185
|
log,
|
|
170
186
|
warn
|
|
171
187
|
} from "./index-zgwm4ryv.js";
|
|
188
|
+
import {
|
|
189
|
+
exports_external
|
|
190
|
+
} from "./index-293f68mj.js";
|
|
172
191
|
import {
|
|
173
192
|
require_proper_lockfile,
|
|
174
193
|
tryAcquireLock
|
|
175
194
|
} from "./index-3naa2ajc.js";
|
|
176
|
-
import {
|
|
177
|
-
exports_external
|
|
178
|
-
} from "./index-293f68mj.js";
|
|
179
195
|
import {
|
|
180
196
|
bunSpawn,
|
|
181
197
|
bunWrite
|
|
@@ -329,7 +345,7 @@ var init_bubblewrap = __esm(() => {
|
|
|
329
345
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
330
346
|
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
331
347
|
import * as os8 from "os";
|
|
332
|
-
import * as
|
|
348
|
+
import * as path35 from "path";
|
|
333
349
|
function probeSandboxExec() {
|
|
334
350
|
try {
|
|
335
351
|
const result = spawnSync4("sandbox-exec", ["--version"], {
|
|
@@ -357,8 +373,8 @@ function probeSandboxExec() {
|
|
|
357
373
|
function shellEscape2(s) {
|
|
358
374
|
return s.replace(/'/g, "'\\''");
|
|
359
375
|
}
|
|
360
|
-
function sbplEscapePath(
|
|
361
|
-
const withoutControlChars =
|
|
376
|
+
function sbplEscapePath(path36) {
|
|
377
|
+
const withoutControlChars = path36.split("").filter((ch) => {
|
|
362
378
|
const cp = ch.codePointAt(0);
|
|
363
379
|
return cp >= 32 && cp !== 127;
|
|
364
380
|
}).join("");
|
|
@@ -434,8 +450,8 @@ class MacOSSandboxExecutor {
|
|
|
434
450
|
const profile = buildSandboxProfile(allScopes, temp);
|
|
435
451
|
let profilePath;
|
|
436
452
|
try {
|
|
437
|
-
const profileDir = mkdtempSync2(
|
|
438
|
-
profilePath =
|
|
453
|
+
const profileDir = mkdtempSync2(path35.join(os8.tmpdir(), "sandbox-"));
|
|
454
|
+
profilePath = path35.join(profileDir, `profile-${process.pid}-${Date.now()}.sb`);
|
|
439
455
|
writeFileSync6(profilePath, profile, { mode: 384 });
|
|
440
456
|
} catch (err) {
|
|
441
457
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -542,7 +558,7 @@ var init_edge_cases = () => {};
|
|
|
542
558
|
// src/sandbox/win32/restricted-environment-executor.ts
|
|
543
559
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
544
560
|
import * as os9 from "os";
|
|
545
|
-
import * as
|
|
561
|
+
import * as path36 from "path";
|
|
546
562
|
function probeWindowsSandbox() {
|
|
547
563
|
try {
|
|
548
564
|
const result = spawnSync5("cmd", ["/c", "echo", "ok"], {
|
|
@@ -589,7 +605,7 @@ function isPathInScopes(command, scopes) {
|
|
|
589
605
|
const paths = command.match(pathPattern) || [];
|
|
590
606
|
if (paths.length === 0)
|
|
591
607
|
return true;
|
|
592
|
-
const normalizedPaths = paths.map((p) =>
|
|
608
|
+
const normalizedPaths = paths.map((p) => path36.win32.resolve(p));
|
|
593
609
|
const normalizedScopes = scopes.map((s) => s.toLowerCase().replace(/\\+$/, ""));
|
|
594
610
|
return normalizedPaths.every((p) => {
|
|
595
611
|
const lower = p.toLowerCase();
|
|
@@ -726,7 +742,7 @@ var init_restricted_environment_executor = __esm(() => {
|
|
|
726
742
|
import * as crypto3 from "crypto";
|
|
727
743
|
import * as fs12 from "fs";
|
|
728
744
|
import * as os10 from "os";
|
|
729
|
-
import * as
|
|
745
|
+
import * as path37 from "path";
|
|
730
746
|
|
|
731
747
|
class NativeWindowsSandboxExecutor {
|
|
732
748
|
mechanism;
|
|
@@ -788,11 +804,11 @@ class NativeWindowsSandboxExecutor {
|
|
|
788
804
|
policy.workspace_roots = scopePaths.length > 0 ? scopePaths : [workspaceRoot];
|
|
789
805
|
policy.writable_roots = policy.workspace_roots;
|
|
790
806
|
const policyJson = JSON.stringify(policy);
|
|
791
|
-
const policyDir =
|
|
807
|
+
const policyDir = path37.join(os10.tmpdir(), "swarm-sandbox-policies");
|
|
792
808
|
try {
|
|
793
809
|
fs12.mkdirSync(policyDir, { recursive: true });
|
|
794
810
|
} catch {}
|
|
795
|
-
const policyFile =
|
|
811
|
+
const policyFile = path37.join(policyDir, `${runId}.json`);
|
|
796
812
|
fs12.writeFileSync(policyFile, policyJson, "utf-8");
|
|
797
813
|
const mode = this._probeResult.mode === "none" ? "auto" : this._probeResult.mode;
|
|
798
814
|
const escapedBinary = binary.includes(" ") ? `"${binary}"` : binary;
|
|
@@ -925,7 +941,7 @@ var init_executor = __esm(() => {
|
|
|
925
941
|
|
|
926
942
|
// src/state.ts
|
|
927
943
|
import * as fs32 from "fs/promises";
|
|
928
|
-
import * as
|
|
944
|
+
import * as path69 from "path";
|
|
929
945
|
|
|
930
946
|
// src/db/qa-gate-profile.ts
|
|
931
947
|
import { createHash } from "crypto";
|
|
@@ -6940,7 +6956,9 @@ function handleRestore(label, directory) {
|
|
|
6940
6956
|
error: `checkpoint not found: "${label}"`
|
|
6941
6957
|
}, null, 2);
|
|
6942
6958
|
}
|
|
6959
|
+
const logBeforeReset = log2;
|
|
6943
6960
|
gitExec(["reset", "--hard", checkpoint.sha], directory);
|
|
6961
|
+
writeCheckpointLog(logBeforeReset, directory);
|
|
6944
6962
|
return JSON.stringify({
|
|
6945
6963
|
action: "restore",
|
|
6946
6964
|
success: true,
|
|
@@ -7199,7 +7217,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
7199
7217
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
7200
7218
|
import * as fsSync from "fs";
|
|
7201
7219
|
import { promises as fs10 } from "fs";
|
|
7202
|
-
import
|
|
7220
|
+
import path28 from "path";
|
|
7203
7221
|
|
|
7204
7222
|
// src/hooks/curator-postmortem.ts
|
|
7205
7223
|
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
@@ -7914,15 +7932,15 @@ var _internals8 = {
|
|
|
7914
7932
|
executePostMortemActions,
|
|
7915
7933
|
repairPostMortemActions,
|
|
7916
7934
|
loadDefaultKnowledgeConfig: async () => {
|
|
7917
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
7935
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-x0ekqzvs.js");
|
|
7918
7936
|
return KnowledgeConfigSchema2.parse({});
|
|
7919
7937
|
},
|
|
7920
7938
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
7921
|
-
const { applyCuratorKnowledgeUpdates } = await import("./curator-
|
|
7939
|
+
const { applyCuratorKnowledgeUpdates } = await import("./curator-rb05fjjk.js");
|
|
7922
7940
|
return applyCuratorKnowledgeUpdates(directory, recommendations, knowledgeConfig);
|
|
7923
7941
|
},
|
|
7924
7942
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
7925
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
7943
|
+
const { checkHivePromotions } = await import("./hive-promoter-34bdmw1w.js");
|
|
7926
7944
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
7927
7945
|
},
|
|
7928
7946
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -7931,7 +7949,7 @@ var _internals8 = {
|
|
|
7931
7949
|
activateProposal,
|
|
7932
7950
|
listSkills: listSkills2,
|
|
7933
7951
|
sanitizeSlug
|
|
7934
|
-
} = await import("./skill-generator-
|
|
7952
|
+
} = await import("./skill-generator-x83re96d.js");
|
|
7935
7953
|
const result = {
|
|
7936
7954
|
approved: [],
|
|
7937
7955
|
rejected: [],
|
|
@@ -7972,7 +7990,7 @@ var _internals8 = {
|
|
|
7972
7990
|
return result;
|
|
7973
7991
|
},
|
|
7974
7992
|
readPriorDriftReports: async (directory) => {
|
|
7975
|
-
const { readPriorDriftReports } = await import("./curator-drift-
|
|
7993
|
+
const { readPriorDriftReports } = await import("./curator-drift-ed7p5mfy.js");
|
|
7976
7994
|
return readPriorDriftReports(directory);
|
|
7977
7995
|
},
|
|
7978
7996
|
readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
|
|
@@ -7986,34 +8004,6 @@ import { randomUUID as randomUUID5 } from "crypto";
|
|
|
7986
8004
|
import * as fs5 from "fs";
|
|
7987
8005
|
import * as path15 from "path";
|
|
7988
8006
|
|
|
7989
|
-
// src/hooks/knowledge-escalator.ts
|
|
7990
|
-
var ESCALATION_DISPLAY_WINDOW_DAYS = 7;
|
|
7991
|
-
async function readRecentEscalations(directory, windowDays = ESCALATION_DISPLAY_WINDOW_DAYS, now = new Date) {
|
|
7992
|
-
try {
|
|
7993
|
-
const cutoff = now.getTime() - windowDays * 24 * 60 * 60 * 1000;
|
|
7994
|
-
const events = await readKnowledgeEvents(directory);
|
|
7995
|
-
const out = [];
|
|
7996
|
-
for (const e of events) {
|
|
7997
|
-
if (e.type !== "escalation")
|
|
7998
|
-
continue;
|
|
7999
|
-
const t = Date.parse(e.timestamp);
|
|
8000
|
-
if (Number.isNaN(t) || t < cutoff)
|
|
8001
|
-
continue;
|
|
8002
|
-
out.push({
|
|
8003
|
-
entry_id: e.entry_id,
|
|
8004
|
-
from: e.from,
|
|
8005
|
-
to: e.to,
|
|
8006
|
-
reason: e.reason,
|
|
8007
|
-
at: e.timestamp
|
|
8008
|
-
});
|
|
8009
|
-
}
|
|
8010
|
-
out.sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : 0);
|
|
8011
|
-
return out;
|
|
8012
|
-
} catch {
|
|
8013
|
-
return [];
|
|
8014
|
-
}
|
|
8015
|
-
}
|
|
8016
|
-
|
|
8017
8007
|
// src/services/learning-metrics.ts
|
|
8018
8008
|
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
8019
8009
|
var THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
|
|
@@ -9329,7 +9319,7 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
9329
9319
|
delta: Math.max(-VIOLATION_DECAY, Math.min(COMPLIANCE_BOOST, netDelta))
|
|
9330
9320
|
}));
|
|
9331
9321
|
if (clampedDeltas.length > 0) {
|
|
9332
|
-
await bumpKnowledgeConfidenceBatch(directory, clampedDeltas);
|
|
9322
|
+
await bumpKnowledgeConfidenceBatch(directory, clampedDeltas, options?.floorOptions);
|
|
9333
9323
|
appendFeedbackAppliedMarker(directory, processedEntryIds);
|
|
9334
9324
|
}
|
|
9335
9325
|
} catch (err) {
|
|
@@ -9411,13 +9401,25 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
9411
9401
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9412
9402
|
continue;
|
|
9413
9403
|
}
|
|
9414
|
-
|
|
9415
|
-
if (
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9404
|
+
let archivedSourceMatched = false;
|
|
9405
|
+
if (allArchivedIds.size > 0) {
|
|
9406
|
+
try {
|
|
9407
|
+
const content = await _internals11.readFileAsync(active.path, "utf-8");
|
|
9408
|
+
const sourceIds = _internals11.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
|
|
9409
|
+
archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
|
|
9410
|
+
} catch {
|
|
9411
|
+
archivedSourceMatched = false;
|
|
9412
|
+
}
|
|
9413
|
+
}
|
|
9414
|
+
if (archivedSourceMatched) {
|
|
9415
|
+
const result = await _internals11.retireOrMarkStale(directory, path15.dirname(active.path), allArchivedIds);
|
|
9416
|
+
if (result.action === "retire") {
|
|
9417
|
+
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
9418
|
+
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9419
|
+
} else if (result.action === "stale") {
|
|
9420
|
+
observations.push(`Skill '${active.slug}' marked stale: some source knowledge entries archived`);
|
|
9421
|
+
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
9422
|
+
}
|
|
9421
9423
|
}
|
|
9422
9424
|
}
|
|
9423
9425
|
} catch (autoRetireErr) {
|
|
@@ -9442,6 +9444,29 @@ function parseKnowledgeRecommendationsWithDiagnostics(llmOutput) {
|
|
|
9442
9444
|
continue;
|
|
9443
9445
|
const match = trimmed.match(/^-\s+entry\s+(\S+)\s+\(([^)]+)\):\s+(.+)$/i);
|
|
9444
9446
|
if (!match) {
|
|
9447
|
+
const newCandidate = trimmed.match(/^-\s+new candidate:\s+(.+)$/i);
|
|
9448
|
+
if (newCandidate) {
|
|
9449
|
+
const text2 = newCandidate[1].trim().replace(/\s+\([^)]+\)$/, "");
|
|
9450
|
+
recommendations.push({
|
|
9451
|
+
action: "promote",
|
|
9452
|
+
entry_id: undefined,
|
|
9453
|
+
lesson: text2,
|
|
9454
|
+
reason: text2
|
|
9455
|
+
});
|
|
9456
|
+
continue;
|
|
9457
|
+
}
|
|
9458
|
+
const staleEntry = trimmed.match(/^-\s+entry\s+(\S+)\s+appears stale:\s+(.+)$/i);
|
|
9459
|
+
if (staleEntry) {
|
|
9460
|
+
const uuid2 = staleEntry[1];
|
|
9461
|
+
const text2 = staleEntry[2].trim().replace(/\s+\([^)]+\)$/, "");
|
|
9462
|
+
recommendations.push({
|
|
9463
|
+
action: "archive",
|
|
9464
|
+
entry_id: UUID_V4.test(uuid2) ? uuid2 : undefined,
|
|
9465
|
+
lesson: text2,
|
|
9466
|
+
reason: text2
|
|
9467
|
+
});
|
|
9468
|
+
continue;
|
|
9469
|
+
}
|
|
9445
9470
|
diagnostics.push({
|
|
9446
9471
|
section: "OBSERVATIONS",
|
|
9447
9472
|
line: trimmed,
|
|
@@ -10092,7 +10117,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
10092
10117
|
}
|
|
10093
10118
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
10094
10119
|
try {
|
|
10095
|
-
const skillModule = await import("./skill-generator-
|
|
10120
|
+
const skillModule = await import("./skill-generator-x83re96d.js");
|
|
10096
10121
|
for (const cand of skillCandidates) {
|
|
10097
10122
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
10098
10123
|
continue;
|
|
@@ -10260,9 +10285,11 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
10260
10285
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
10261
10286
|
const appliedIds = new Set;
|
|
10262
10287
|
const foundIds = new Set;
|
|
10288
|
+
const contradictedEntries = [];
|
|
10263
10289
|
await transactKnowledge(knowledgePath, (entries) => {
|
|
10264
10290
|
appliedIds.clear();
|
|
10265
10291
|
foundIds.clear();
|
|
10292
|
+
contradictedEntries.length = 0;
|
|
10266
10293
|
let txApplied = 0;
|
|
10267
10294
|
let modified = false;
|
|
10268
10295
|
for (const e of entries)
|
|
@@ -10282,19 +10309,29 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
10282
10309
|
confidence: Math.min(1, (entry.confidence ?? 0) + 0.1),
|
|
10283
10310
|
updated_at: new Date().toISOString()
|
|
10284
10311
|
};
|
|
10285
|
-
case "archive":
|
|
10312
|
+
case "archive": {
|
|
10313
|
+
if (entry.status === "archived") {
|
|
10314
|
+
return entry;
|
|
10315
|
+
}
|
|
10286
10316
|
appliedIds.add(entry.id);
|
|
10287
10317
|
txApplied++;
|
|
10288
10318
|
modified = true;
|
|
10289
10319
|
return {
|
|
10290
10320
|
...entry,
|
|
10291
10321
|
status: "archived",
|
|
10322
|
+
archived_from: entry.status,
|
|
10323
|
+
archived_at: new Date().toISOString(),
|
|
10292
10324
|
updated_at: new Date().toISOString()
|
|
10293
10325
|
};
|
|
10326
|
+
}
|
|
10294
10327
|
case "flag_contradiction":
|
|
10295
10328
|
appliedIds.add(entry.id);
|
|
10296
10329
|
txApplied++;
|
|
10297
10330
|
modified = true;
|
|
10331
|
+
contradictedEntries.push({
|
|
10332
|
+
id: entry.id,
|
|
10333
|
+
reason: (rec.reason ?? "").slice(0, 200)
|
|
10334
|
+
});
|
|
10298
10335
|
return {
|
|
10299
10336
|
...entry,
|
|
10300
10337
|
tags: [
|
|
@@ -10336,6 +10373,27 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
10336
10373
|
applied += txApplied;
|
|
10337
10374
|
return modified ? updatedEntries : null;
|
|
10338
10375
|
});
|
|
10376
|
+
for (const { id, reason } of contradictedEntries) {
|
|
10377
|
+
try {
|
|
10378
|
+
await recordKnowledgeEvent(directory, {
|
|
10379
|
+
type: "contradicted",
|
|
10380
|
+
knowledge_id: id,
|
|
10381
|
+
trace_id: `curator-${randomUUID5()}`,
|
|
10382
|
+
session_id: "curator",
|
|
10383
|
+
agent: "curator",
|
|
10384
|
+
reason: `flag_contradiction: ${reason}`,
|
|
10385
|
+
evidence: { summary: reason }
|
|
10386
|
+
});
|
|
10387
|
+
} catch {}
|
|
10388
|
+
}
|
|
10389
|
+
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
10390
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-3sgwrgy9.js");
|
|
10391
|
+
for (const { id } of contradictedEntries) {
|
|
10392
|
+
try {
|
|
10393
|
+
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
10394
|
+
} catch {}
|
|
10395
|
+
}
|
|
10396
|
+
}
|
|
10339
10397
|
for (const rec of validRecommendations) {
|
|
10340
10398
|
if (rec.entry_id !== undefined && !appliedIds.has(rec.entry_id)) {
|
|
10341
10399
|
if (!foundIds.has(rec.entry_id)) {
|
|
@@ -10458,7 +10516,7 @@ function isHiveEligible(entry, autoPromoteDays) {
|
|
|
10458
10516
|
return false;
|
|
10459
10517
|
}
|
|
10460
10518
|
function isActiveForHivePromotion(entry) {
|
|
10461
|
-
return
|
|
10519
|
+
return isActiveStatus(entry.status);
|
|
10462
10520
|
}
|
|
10463
10521
|
function countDistinctProjects(confirmedBy) {
|
|
10464
10522
|
const projectNames = new Set;
|
|
@@ -10897,13 +10955,8 @@ async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIR
|
|
|
10897
10955
|
init_logger();
|
|
10898
10956
|
|
|
10899
10957
|
// src/hooks/knowledge-reinforcement.ts
|
|
10900
|
-
var INACTIVE_STATUSES = new Set([
|
|
10901
|
-
"archived",
|
|
10902
|
-
"quarantined",
|
|
10903
|
-
"quarantined_unactionable"
|
|
10904
|
-
]);
|
|
10905
10958
|
function isActiveSwarmKnowledgeEntry(entry) {
|
|
10906
|
-
return
|
|
10959
|
+
return isActiveStatus(entry.status);
|
|
10907
10960
|
}
|
|
10908
10961
|
function findActiveSwarmNearDuplicate(lesson, entries, threshold) {
|
|
10909
10962
|
return findNearDuplicate(lesson, entries.filter(isActiveSwarmKnowledgeEntry), threshold);
|
|
@@ -11015,6 +11068,9 @@ function normalizeTriggerList(values) {
|
|
|
11015
11068
|
}
|
|
11016
11069
|
return out;
|
|
11017
11070
|
}
|
|
11071
|
+
function finiteRankValue(value) {
|
|
11072
|
+
return Number.isFinite(value) ? value : 0;
|
|
11073
|
+
}
|
|
11018
11074
|
function parseInlineStringList(rawValue) {
|
|
11019
11075
|
const trimmed = rawValue.trim();
|
|
11020
11076
|
if (!trimmed)
|
|
@@ -11233,15 +11289,19 @@ function rankSkillsForContext(skills, taskContext, directory) {
|
|
|
11233
11289
|
const complianceRate = entriesWithVerdict.length > 0 ? compliantCount / entriesWithVerdict.length : 0;
|
|
11234
11290
|
results.push({
|
|
11235
11291
|
skillPath,
|
|
11236
|
-
score,
|
|
11292
|
+
score: finiteRankValue(score),
|
|
11237
11293
|
usageCount: skillEntries.length,
|
|
11238
11294
|
complianceRate
|
|
11239
11295
|
});
|
|
11240
11296
|
}
|
|
11241
11297
|
results.sort((a, b) => {
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11298
|
+
const scoreDelta = finiteRankValue(b.score) - finiteRankValue(a.score);
|
|
11299
|
+
if (scoreDelta !== 0)
|
|
11300
|
+
return scoreDelta;
|
|
11301
|
+
const usageDelta = b.usageCount - a.usageCount;
|
|
11302
|
+
if (usageDelta !== 0)
|
|
11303
|
+
return usageDelta;
|
|
11304
|
+
return a.skillPath.localeCompare(b.skillPath);
|
|
11245
11305
|
});
|
|
11246
11306
|
return results;
|
|
11247
11307
|
}
|
|
@@ -12720,10 +12780,13 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
12720
12780
|
}
|
|
12721
12781
|
if (!options?.skipAutoPromotion) {
|
|
12722
12782
|
await _internals14.runAutoPromotion(directory, config);
|
|
12783
|
+
if (phaseInfo.phase_number > 0) {
|
|
12784
|
+
await _internals14.runAutoDemotion(directory, config, phaseInfo.phase_number);
|
|
12785
|
+
}
|
|
12723
12786
|
}
|
|
12724
12787
|
return { stored, reinforced, skipped, rejected, quarantined };
|
|
12725
12788
|
}
|
|
12726
|
-
var OUTCOME_PROMOTION_BLOCK =
|
|
12789
|
+
var OUTCOME_PROMOTION_BLOCK = OUTCOME_BLOCK_THRESHOLD;
|
|
12727
12790
|
async function runAutoPromotion(directory, config) {
|
|
12728
12791
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
12729
12792
|
const entries = await readKnowledge(knowledgePath) ?? [];
|
|
@@ -12758,6 +12821,42 @@ async function runAutoPromotion(directory, config) {
|
|
|
12758
12821
|
await rewriteKnowledge(knowledgePath, entries);
|
|
12759
12822
|
}
|
|
12760
12823
|
}
|
|
12824
|
+
async function runAutoDemotion(directory, config, phaseNumber) {
|
|
12825
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
12826
|
+
const entries = await readKnowledge(knowledgePath) ?? [];
|
|
12827
|
+
const counterRollups = await readKnowledgeCounterRollups(directory);
|
|
12828
|
+
let changed = false;
|
|
12829
|
+
for (const entry of entries) {
|
|
12830
|
+
if (entry.status !== "promoted")
|
|
12831
|
+
continue;
|
|
12832
|
+
if (entry.last_demotion_phase === phaseNumber)
|
|
12833
|
+
continue;
|
|
12834
|
+
const signal = computeOutcomeSignal(effectiveRetrievalOutcomes(entry.retrieval_outcomes, counterRollups.get(entry.id)));
|
|
12835
|
+
const threshold = config.promoted_demotion_signal_threshold;
|
|
12836
|
+
const minPhases = config.promoted_demotion_min_negative_phases;
|
|
12837
|
+
const prevCount = entry.recent_negative_phase_count ?? 0;
|
|
12838
|
+
const next = signal <= threshold ? prevCount + 1 : 0;
|
|
12839
|
+
const counterChanged = next !== prevCount;
|
|
12840
|
+
const willDemote = next >= minPhases;
|
|
12841
|
+
if (!counterChanged && !willDemote) {
|
|
12842
|
+
entry.last_demotion_phase = phaseNumber;
|
|
12843
|
+
continue;
|
|
12844
|
+
}
|
|
12845
|
+
entry.recent_negative_phase_count = next;
|
|
12846
|
+
entry.last_demotion_phase = phaseNumber;
|
|
12847
|
+
if (willDemote) {
|
|
12848
|
+
entry.status = "established";
|
|
12849
|
+
entry.hive_eligible = false;
|
|
12850
|
+
entry.confidence_floor_demoted = false;
|
|
12851
|
+
entry.recent_negative_phase_count = 0;
|
|
12852
|
+
}
|
|
12853
|
+
entry.updated_at = new Date().toISOString();
|
|
12854
|
+
changed = true;
|
|
12855
|
+
}
|
|
12856
|
+
if (changed) {
|
|
12857
|
+
await rewriteKnowledge(knowledgePath, entries);
|
|
12858
|
+
}
|
|
12859
|
+
}
|
|
12761
12860
|
function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
12762
12861
|
const handler = async (input, output) => {
|
|
12763
12862
|
pruneSeenRetroSections();
|
|
@@ -12837,6 +12936,7 @@ var _internals14 = {
|
|
|
12837
12936
|
isWriteToEvidenceFile,
|
|
12838
12937
|
curateAndStoreSwarm,
|
|
12839
12938
|
runAutoPromotion,
|
|
12939
|
+
runAutoDemotion,
|
|
12840
12940
|
createKnowledgeCuratorHook,
|
|
12841
12941
|
seenRetroSections,
|
|
12842
12942
|
recordSeenRetroSection,
|
|
@@ -14286,6 +14386,8 @@ function readEarliestSessionStart(directory) {
|
|
|
14286
14386
|
}
|
|
14287
14387
|
|
|
14288
14388
|
// src/tools/write-retro.ts
|
|
14389
|
+
import { existsSync as existsSync17 } from "fs";
|
|
14390
|
+
import path27 from "path";
|
|
14289
14391
|
async function executeWriteRetro(args, directory) {
|
|
14290
14392
|
if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
|
|
14291
14393
|
return JSON.stringify({
|
|
@@ -14293,6 +14395,12 @@ async function executeWriteRetro(args, directory) {
|
|
|
14293
14395
|
message: "Invalid directory: reserved device name"
|
|
14294
14396
|
}, null, 2);
|
|
14295
14397
|
}
|
|
14398
|
+
if (!existsSync17(path27.join(directory, ".swarm"))) {
|
|
14399
|
+
return JSON.stringify({
|
|
14400
|
+
success: false,
|
|
14401
|
+
message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
|
|
14402
|
+
}, null, 2);
|
|
14403
|
+
}
|
|
14296
14404
|
const phase = args.phase;
|
|
14297
14405
|
if (!Number.isInteger(phase) || phase < 1) {
|
|
14298
14406
|
return JSON.stringify({
|
|
@@ -14703,8 +14811,8 @@ async function copyDirRecursiveWithFailures(src, dest) {
|
|
|
14703
14811
|
const entries = await fs10.readdir(src);
|
|
14704
14812
|
await fs10.mkdir(dest, { recursive: true });
|
|
14705
14813
|
for (const entry of entries) {
|
|
14706
|
-
const srcEntry =
|
|
14707
|
-
const destEntry =
|
|
14814
|
+
const srcEntry = path28.join(src, entry);
|
|
14815
|
+
const destEntry = path28.join(dest, entry);
|
|
14708
14816
|
try {
|
|
14709
14817
|
const stat4 = await fs10.stat(srcEntry);
|
|
14710
14818
|
if (stat4.isDirectory()) {
|
|
@@ -14889,18 +14997,18 @@ async function runFinalizeStage(ctx) {
|
|
|
14889
14997
|
ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
14890
14998
|
}
|
|
14891
14999
|
}
|
|
14892
|
-
const lessonsFilePath =
|
|
15000
|
+
const lessonsFilePath = path28.join(ctx.swarmDir, "close-lessons.md");
|
|
14893
15001
|
try {
|
|
14894
15002
|
const lessonsText = await fs10.readFile(lessonsFilePath, "utf-8");
|
|
14895
15003
|
ctx.explicitLessons = lessonsText.split(`
|
|
14896
15004
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
14897
15005
|
} catch {}
|
|
14898
15006
|
try {
|
|
14899
|
-
const evidenceDir =
|
|
15007
|
+
const evidenceDir = path28.join(ctx.swarmDir, "evidence");
|
|
14900
15008
|
const evidenceEntries = await fs10.readdir(evidenceDir);
|
|
14901
15009
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
14902
15010
|
for (const retroDir of retroDirs) {
|
|
14903
|
-
const evidencePath =
|
|
15011
|
+
const evidencePath = path28.join(evidenceDir, retroDir, "evidence.json");
|
|
14904
15012
|
try {
|
|
14905
15013
|
const content = await fs10.readFile(evidencePath, "utf-8");
|
|
14906
15014
|
const parsed = JSON.parse(content);
|
|
@@ -15052,7 +15160,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15052
15160
|
}
|
|
15053
15161
|
}
|
|
15054
15162
|
try {
|
|
15055
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
15163
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-x0ekqzvs.js");
|
|
15056
15164
|
const { config: pmLoadedConfig } = _internals18.loadPluginConfigWithMeta(ctx.directory);
|
|
15057
15165
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
15058
15166
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -15084,7 +15192,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15084
15192
|
let checkpointVerified = false;
|
|
15085
15193
|
try {
|
|
15086
15194
|
const result = spawnSync2("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
15087
|
-
cwd:
|
|
15195
|
+
cwd: path28.dirname(srcPath),
|
|
15088
15196
|
encoding: "utf-8",
|
|
15089
15197
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15090
15198
|
timeout: 1e4,
|
|
@@ -15152,7 +15260,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
15152
15260
|
async function runArchiveStage(ctx) {
|
|
15153
15261
|
ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
15154
15262
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
15155
|
-
ctx.archiveDir =
|
|
15263
|
+
ctx.archiveDir = path28.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
15156
15264
|
try {
|
|
15157
15265
|
await fs10.mkdir(ctx.archiveDir, { recursive: true });
|
|
15158
15266
|
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
@@ -15167,8 +15275,8 @@ async function runArchiveStage(ctx) {
|
|
|
15167
15275
|
if (linkedKnowledgeShared && KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact)) {
|
|
15168
15276
|
continue;
|
|
15169
15277
|
}
|
|
15170
|
-
const srcPath =
|
|
15171
|
-
const destPath =
|
|
15278
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
15279
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
15172
15280
|
if (artifact === "swarm.db") {
|
|
15173
15281
|
const result = await copySqliteSafe(srcPath, destPath);
|
|
15174
15282
|
if (result.skipped) {} else if (result.success) {
|
|
@@ -15201,8 +15309,8 @@ async function runArchiveStage(ctx) {
|
|
|
15201
15309
|
}
|
|
15202
15310
|
const dynamicArchiveArtifacts = (await fs10.readdir(ctx.swarmDir).catch(() => [])).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name) || /^drift-report-phase-\d+\.json$/.test(name));
|
|
15203
15311
|
for (const artifact of dynamicArchiveArtifacts) {
|
|
15204
|
-
const srcPath =
|
|
15205
|
-
const destPath =
|
|
15312
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
15313
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
15206
15314
|
try {
|
|
15207
15315
|
await fs10.copyFile(srcPath, destPath);
|
|
15208
15316
|
ctx.archivedFileCount++;
|
|
@@ -15217,8 +15325,8 @@ async function runArchiveStage(ctx) {
|
|
|
15217
15325
|
}
|
|
15218
15326
|
}
|
|
15219
15327
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
15220
|
-
const srcDir =
|
|
15221
|
-
const destDir =
|
|
15328
|
+
const srcDir = path28.join(ctx.swarmDir, dirName);
|
|
15329
|
+
const destDir = path28.join(ctx.archiveDir, dirName);
|
|
15222
15330
|
try {
|
|
15223
15331
|
const result = await copyDirRecursiveWithFailures(srcDir, destDir);
|
|
15224
15332
|
ctx.archivedFileCount += result.copied;
|
|
@@ -15295,7 +15403,7 @@ async function runCleanStage(ctx) {
|
|
|
15295
15403
|
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
15296
15404
|
continue;
|
|
15297
15405
|
}
|
|
15298
|
-
const filePath =
|
|
15406
|
+
const filePath = path28.join(ctx.swarmDir, artifact);
|
|
15299
15407
|
try {
|
|
15300
15408
|
await fs10.unlink(filePath);
|
|
15301
15409
|
cleanedFiles.push(artifact);
|
|
@@ -15315,7 +15423,7 @@ async function runCleanStage(ctx) {
|
|
|
15315
15423
|
continue;
|
|
15316
15424
|
}
|
|
15317
15425
|
try {
|
|
15318
|
-
await fs10.unlink(
|
|
15426
|
+
await fs10.unlink(path28.join(ctx.swarmDir, artifact));
|
|
15319
15427
|
cleanedFiles.push(artifact);
|
|
15320
15428
|
} catch (err) {
|
|
15321
15429
|
const errno = err?.code;
|
|
@@ -15329,7 +15437,7 @@ async function runCleanStage(ctx) {
|
|
|
15329
15437
|
if (!ctx.archivedActiveStateDirs.has(dirName)) {
|
|
15330
15438
|
continue;
|
|
15331
15439
|
}
|
|
15332
|
-
const dirPath =
|
|
15440
|
+
const dirPath = path28.join(ctx.swarmDir, dirName);
|
|
15333
15441
|
try {
|
|
15334
15442
|
await fs10.rm(dirPath, { recursive: true, force: true });
|
|
15335
15443
|
cleanedFiles.push(`${dirName}/`);
|
|
@@ -15340,7 +15448,7 @@ async function runCleanStage(ctx) {
|
|
|
15340
15448
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
15341
15449
|
for (const backup of configBackups) {
|
|
15342
15450
|
try {
|
|
15343
|
-
await fs10.unlink(
|
|
15451
|
+
await fs10.unlink(path28.join(ctx.swarmDir, backup));
|
|
15344
15452
|
configBackupsRemoved++;
|
|
15345
15453
|
} catch (err) {
|
|
15346
15454
|
const errno = err?.code;
|
|
@@ -15353,7 +15461,7 @@ async function runCleanStage(ctx) {
|
|
|
15353
15461
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
15354
15462
|
for (const sibling of ledgerSiblings) {
|
|
15355
15463
|
try {
|
|
15356
|
-
await fs10.unlink(
|
|
15464
|
+
await fs10.unlink(path28.join(ctx.swarmDir, sibling));
|
|
15357
15465
|
} catch (err) {
|
|
15358
15466
|
const errno = err?.code;
|
|
15359
15467
|
if (errno === "ENOENT") {} else {
|
|
@@ -15371,12 +15479,12 @@ async function runCleanStage(ctx) {
|
|
|
15371
15479
|
}
|
|
15372
15480
|
let swarmPlanFilesRemoved = 0;
|
|
15373
15481
|
const candidates = [
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15482
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
|
|
15483
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
|
|
15484
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
|
|
15485
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
|
|
15486
|
+
path28.join(ctx.directory, "SWARM_PLAN.json"),
|
|
15487
|
+
path28.join(ctx.directory, "SWARM_PLAN.md")
|
|
15380
15488
|
];
|
|
15381
15489
|
for (const candidate of candidates) {
|
|
15382
15490
|
try {
|
|
@@ -15394,7 +15502,7 @@ async function runCleanStage(ctx) {
|
|
|
15394
15502
|
const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
|
|
15395
15503
|
for (const tmp of tmpFiles) {
|
|
15396
15504
|
try {
|
|
15397
|
-
await fs10.unlink(
|
|
15505
|
+
await fs10.unlink(path28.join(ctx.swarmDir, tmp));
|
|
15398
15506
|
tmpFilesRemoved++;
|
|
15399
15507
|
} catch (err) {
|
|
15400
15508
|
const errno = err?.code;
|
|
@@ -15416,7 +15524,7 @@ async function runCleanStage(ctx) {
|
|
|
15416
15524
|
}
|
|
15417
15525
|
for (const terminalFile of TERMINAL_STATE_FILES) {
|
|
15418
15526
|
try {
|
|
15419
|
-
await fs10.unlink(
|
|
15527
|
+
await fs10.unlink(path28.join(ctx.swarmDir, terminalFile));
|
|
15420
15528
|
if (!cleanedFiles.includes(terminalFile)) {
|
|
15421
15529
|
cleanedFiles.push(terminalFile);
|
|
15422
15530
|
}
|
|
@@ -15429,7 +15537,7 @@ async function runCleanStage(ctx) {
|
|
|
15429
15537
|
}
|
|
15430
15538
|
}
|
|
15431
15539
|
clearAllScopes(ctx.directory);
|
|
15432
|
-
const contextPath =
|
|
15540
|
+
const contextPath = path28.join(ctx.swarmDir, "context.md");
|
|
15433
15541
|
const contextContent = [
|
|
15434
15542
|
"# Context",
|
|
15435
15543
|
"",
|
|
@@ -15441,7 +15549,7 @@ async function runCleanStage(ctx) {
|
|
|
15441
15549
|
""
|
|
15442
15550
|
].join(`
|
|
15443
15551
|
`);
|
|
15444
|
-
const contextTempPath =
|
|
15552
|
+
const contextTempPath = path28.join(path28.dirname(contextPath), `${path28.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15445
15553
|
try {
|
|
15446
15554
|
await fs10.writeFile(contextTempPath, contextContent, "utf-8");
|
|
15447
15555
|
fsSync.renameSync(contextTempPath, contextPath);
|
|
@@ -15505,7 +15613,7 @@ async function runAlignStage(ctx) {
|
|
|
15505
15613
|
return { gitAlignResult, prunedBranches };
|
|
15506
15614
|
}
|
|
15507
15615
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
15508
|
-
const swarmDir =
|
|
15616
|
+
const swarmDir = path28.join(directory, ".swarm");
|
|
15509
15617
|
try {
|
|
15510
15618
|
const stat4 = fsSync.lstatSync(swarmDir);
|
|
15511
15619
|
if (stat4.isSymbolicLink()) {
|
|
@@ -15519,7 +15627,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15519
15627
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
15520
15628
|
let planExists = false;
|
|
15521
15629
|
let planData = {
|
|
15522
|
-
title:
|
|
15630
|
+
title: path28.basename(directory) || "Ad-hoc session",
|
|
15523
15631
|
phases: []
|
|
15524
15632
|
};
|
|
15525
15633
|
try {
|
|
@@ -15544,7 +15652,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15544
15652
|
}
|
|
15545
15653
|
try {
|
|
15546
15654
|
if (!planExists) {
|
|
15547
|
-
const archiveDir =
|
|
15655
|
+
const archiveDir = path28.join(swarmDir, "archive");
|
|
15548
15656
|
try {
|
|
15549
15657
|
const archiveEntries = await fs10.readdir(archiveDir);
|
|
15550
15658
|
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
@@ -15552,7 +15660,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15552
15660
|
const hasActiveState = [
|
|
15553
15661
|
...ACTIVE_STATE_TO_CLEAN,
|
|
15554
15662
|
...ACTIVE_STATE_DIRS_TO_CLEAN
|
|
15555
|
-
].some((entry) => fsSync.existsSync(
|
|
15663
|
+
].some((entry) => fsSync.existsSync(path28.join(swarmDir, entry)));
|
|
15556
15664
|
if (!hasActiveState) {
|
|
15557
15665
|
return `\u2705 Already finalized \u2014 nothing to do.
|
|
15558
15666
|
|
|
@@ -15680,7 +15788,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
15680
15788
|
...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
|
|
15681
15789
|
].join(`
|
|
15682
15790
|
`);
|
|
15683
|
-
const closeSummaryTempPath =
|
|
15791
|
+
const closeSummaryTempPath = path28.join(path28.dirname(closeSummaryPath), `${path28.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15684
15792
|
try {
|
|
15685
15793
|
await fs10.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
15686
15794
|
fsSync.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
@@ -16024,14 +16132,14 @@ function buildStatusMessage(session, plan) {
|
|
|
16024
16132
|
|
|
16025
16133
|
// src/commands/config.ts
|
|
16026
16134
|
import * as os6 from "os";
|
|
16027
|
-
import * as
|
|
16135
|
+
import * as path29 from "path";
|
|
16028
16136
|
function getUserConfigDir2() {
|
|
16029
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
16137
|
+
return process.env.XDG_CONFIG_HOME || path29.join(os6.homedir(), ".config");
|
|
16030
16138
|
}
|
|
16031
16139
|
async function handleConfigCommand(directory, _args) {
|
|
16032
16140
|
const config = loadPluginConfig(directory);
|
|
16033
|
-
const userConfigPath =
|
|
16034
|
-
const projectConfigPath =
|
|
16141
|
+
const userConfigPath = path29.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
16142
|
+
const projectConfigPath = path29.join(directory, ".opencode", "opencode-swarm.json");
|
|
16035
16143
|
const lines = [
|
|
16036
16144
|
"## Swarm Configuration",
|
|
16037
16145
|
"",
|
|
@@ -16049,9 +16157,9 @@ async function handleConfigCommand(directory, _args) {
|
|
|
16049
16157
|
}
|
|
16050
16158
|
|
|
16051
16159
|
// src/services/skill-consolidation.ts
|
|
16052
|
-
import { existsSync as
|
|
16160
|
+
import { existsSync as existsSync19 } from "fs";
|
|
16053
16161
|
import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
|
|
16054
|
-
import * as
|
|
16162
|
+
import * as path30 from "path";
|
|
16055
16163
|
|
|
16056
16164
|
// src/utils/timeout.ts
|
|
16057
16165
|
async function withTimeout(promise, ms, timeoutError) {
|
|
@@ -16076,11 +16184,11 @@ var DEFAULT_CONSOLIDATION_MAX_CALLS_PER_RUN = 1;
|
|
|
16076
16184
|
var CONSOLIDATION_RUN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
16077
16185
|
var runningByDirectory = new Map;
|
|
16078
16186
|
function consolidationStatePath(directory) {
|
|
16079
|
-
return
|
|
16187
|
+
return path30.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
|
|
16080
16188
|
}
|
|
16081
16189
|
async function readState2(directory) {
|
|
16082
16190
|
const filePath = consolidationStatePath(directory);
|
|
16083
|
-
if (!
|
|
16191
|
+
if (!existsSync19(filePath))
|
|
16084
16192
|
return {};
|
|
16085
16193
|
try {
|
|
16086
16194
|
const parsed = JSON.parse(await readFile10(filePath, "utf-8"));
|
|
@@ -16092,7 +16200,7 @@ async function readState2(directory) {
|
|
|
16092
16200
|
}
|
|
16093
16201
|
}
|
|
16094
16202
|
async function atomicWrite2(filePath, content) {
|
|
16095
|
-
await mkdir9(
|
|
16203
|
+
await mkdir9(path30.dirname(filePath), { recursive: true });
|
|
16096
16204
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
16097
16205
|
await writeFile11(tmp, content, "utf-8");
|
|
16098
16206
|
await rename7(tmp, filePath);
|
|
@@ -16172,7 +16280,7 @@ async function runSkillConsolidationInner(req) {
|
|
|
16172
16280
|
};
|
|
16173
16281
|
}
|
|
16174
16282
|
async function runSkillConsolidation(req) {
|
|
16175
|
-
const key =
|
|
16283
|
+
const key = path30.resolve(req.directory);
|
|
16176
16284
|
const existing = runningByDirectory.get(key);
|
|
16177
16285
|
if (existing) {
|
|
16178
16286
|
return {
|
|
@@ -16374,7 +16482,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
16374
16482
|
// src/commands/coupling.ts
|
|
16375
16483
|
import { randomBytes } from "crypto";
|
|
16376
16484
|
import * as fs11 from "fs";
|
|
16377
|
-
import * as
|
|
16485
|
+
import * as path32 from "path";
|
|
16378
16486
|
|
|
16379
16487
|
// src/turbo/epic/cochange-source.ts
|
|
16380
16488
|
import * as child_process3 from "child_process";
|
|
@@ -16384,7 +16492,7 @@ import { promisify as promisify2 } from "util";
|
|
|
16384
16492
|
import * as child_process2 from "child_process";
|
|
16385
16493
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
16386
16494
|
import { readdir as readdir2, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
16387
|
-
import * as
|
|
16495
|
+
import * as path31 from "path";
|
|
16388
16496
|
import { promisify } from "util";
|
|
16389
16497
|
function getExecFileAsync() {
|
|
16390
16498
|
return promisify(child_process2.execFile);
|
|
@@ -16488,7 +16596,7 @@ async function scanSourceFiles(dir) {
|
|
|
16488
16596
|
try {
|
|
16489
16597
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
16490
16598
|
for (const entry of entries) {
|
|
16491
|
-
const fullPath =
|
|
16599
|
+
const fullPath = path31.join(dir, entry.name);
|
|
16492
16600
|
if (entry.isDirectory()) {
|
|
16493
16601
|
if (skipDirs.has(entry.name)) {
|
|
16494
16602
|
continue;
|
|
@@ -16496,7 +16604,7 @@ async function scanSourceFiles(dir) {
|
|
|
16496
16604
|
const subFiles = await scanSourceFiles(fullPath);
|
|
16497
16605
|
results.push(...subFiles);
|
|
16498
16606
|
} else if (entry.isFile()) {
|
|
16499
|
-
const ext =
|
|
16607
|
+
const ext = path31.extname(entry.name);
|
|
16500
16608
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
16501
16609
|
results.push(fullPath);
|
|
16502
16610
|
}
|
|
@@ -16518,8 +16626,8 @@ async function getStaticEdges(directory) {
|
|
|
16518
16626
|
continue;
|
|
16519
16627
|
}
|
|
16520
16628
|
try {
|
|
16521
|
-
const sourceDir =
|
|
16522
|
-
const resolvedPath =
|
|
16629
|
+
const sourceDir = path31.dirname(sourceFile);
|
|
16630
|
+
const resolvedPath = path31.resolve(sourceDir, importPath);
|
|
16523
16631
|
const extensions = [
|
|
16524
16632
|
"",
|
|
16525
16633
|
".ts",
|
|
@@ -16544,8 +16652,8 @@ async function getStaticEdges(directory) {
|
|
|
16544
16652
|
if (!targetFile) {
|
|
16545
16653
|
continue;
|
|
16546
16654
|
}
|
|
16547
|
-
const relSource =
|
|
16548
|
-
const relTarget =
|
|
16655
|
+
const relSource = path31.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
16656
|
+
const relTarget = path31.relative(directory, targetFile).replace(/\\/g, "/");
|
|
16549
16657
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
16550
16658
|
edges.add(key);
|
|
16551
16659
|
} catch {}
|
|
@@ -16557,7 +16665,7 @@ async function getStaticEdges(directory) {
|
|
|
16557
16665
|
function isTestImplementationPair(fileA, fileB) {
|
|
16558
16666
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
16559
16667
|
const getBaseName = (filePath) => {
|
|
16560
|
-
const base =
|
|
16668
|
+
const base = path31.basename(filePath);
|
|
16561
16669
|
for (const pattern of testPatterns) {
|
|
16562
16670
|
if (base.endsWith(pattern)) {
|
|
16563
16671
|
return base.slice(0, -pattern.length);
|
|
@@ -16567,16 +16675,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
16567
16675
|
};
|
|
16568
16676
|
const baseA = getBaseName(fileA);
|
|
16569
16677
|
const baseB = getBaseName(fileB);
|
|
16570
|
-
return baseA === baseB && baseA !==
|
|
16678
|
+
return baseA === baseB && baseA !== path31.basename(fileA) && baseA !== path31.basename(fileB);
|
|
16571
16679
|
}
|
|
16572
16680
|
function hasSharedPrefix(fileA, fileB) {
|
|
16573
|
-
const dirA =
|
|
16574
|
-
const dirB =
|
|
16681
|
+
const dirA = path31.dirname(fileA);
|
|
16682
|
+
const dirB = path31.dirname(fileB);
|
|
16575
16683
|
if (dirA !== dirB) {
|
|
16576
16684
|
return false;
|
|
16577
16685
|
}
|
|
16578
|
-
const baseA =
|
|
16579
|
-
const baseB =
|
|
16686
|
+
const baseA = path31.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
16687
|
+
const baseB = path31.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
16580
16688
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
16581
16689
|
return true;
|
|
16582
16690
|
}
|
|
@@ -16631,8 +16739,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
16631
16739
|
const entries = [];
|
|
16632
16740
|
const now = new Date().toISOString();
|
|
16633
16741
|
for (const pair of pairs.slice(0, 10)) {
|
|
16634
|
-
const baseA =
|
|
16635
|
-
const baseB =
|
|
16742
|
+
const baseA = path31.basename(pair.fileA);
|
|
16743
|
+
const baseB = path31.basename(pair.fileB);
|
|
16636
16744
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
16637
16745
|
if (lesson.length > 280) {
|
|
16638
16746
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -17058,9 +17166,9 @@ function parseArgs3(args) {
|
|
|
17058
17166
|
return parsed;
|
|
17059
17167
|
}
|
|
17060
17168
|
function persistReportJson(directory, report) {
|
|
17061
|
-
const epicDir =
|
|
17169
|
+
const epicDir = path32.join(directory, ".swarm", "epic");
|
|
17062
17170
|
fs11.mkdirSync(epicDir, { recursive: true });
|
|
17063
|
-
const filePath =
|
|
17171
|
+
const filePath = path32.join(epicDir, "coupling-report.json");
|
|
17064
17172
|
const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
|
|
17065
17173
|
fs11.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
|
|
17066
17174
|
`, "utf-8");
|
|
@@ -17119,7 +17227,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
17119
17227
|
persistStatus = {
|
|
17120
17228
|
requested: true,
|
|
17121
17229
|
written: true,
|
|
17122
|
-
path:
|
|
17230
|
+
path: path32.relative(directory, writtenAt).replace(/\\/g, "/")
|
|
17123
17231
|
};
|
|
17124
17232
|
} catch (err) {
|
|
17125
17233
|
persistStatus = {
|
|
@@ -17157,9 +17265,9 @@ var _internals22 = {
|
|
|
17157
17265
|
readSwarmFileAsync,
|
|
17158
17266
|
loadCuratorDeps: async () => {
|
|
17159
17267
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17160
|
-
import("./schema-
|
|
17161
|
-
import("./curator-
|
|
17162
|
-
import("./curator-llm-factory-
|
|
17268
|
+
import("./schema-x0ekqzvs.js"),
|
|
17269
|
+
import("./curator-rb05fjjk.js"),
|
|
17270
|
+
import("./curator-llm-factory-abw56kg0.js")
|
|
17163
17271
|
]);
|
|
17164
17272
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17165
17273
|
}
|
|
@@ -17251,7 +17359,7 @@ function formatCurationSummary(summary) {
|
|
|
17251
17359
|
}
|
|
17252
17360
|
|
|
17253
17361
|
// src/commands/dark-matter.ts
|
|
17254
|
-
import
|
|
17362
|
+
import path33 from "path";
|
|
17255
17363
|
async function handleDarkMatterCommand(directory, args) {
|
|
17256
17364
|
const options = {};
|
|
17257
17365
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -17283,7 +17391,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
17283
17391
|
const output = formatDarkMatterOutput(pairs);
|
|
17284
17392
|
if (pairs.length > 0) {
|
|
17285
17393
|
try {
|
|
17286
|
-
const projectName =
|
|
17394
|
+
const projectName = path33.basename(path33.resolve(directory));
|
|
17287
17395
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
17288
17396
|
if (entries.length > 0) {
|
|
17289
17397
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -17649,13 +17757,13 @@ ${USAGE5}`;
|
|
|
17649
17757
|
|
|
17650
17758
|
// src/services/diagnose-service.ts
|
|
17651
17759
|
import * as child_process4 from "child_process";
|
|
17652
|
-
import { existsSync as
|
|
17653
|
-
import
|
|
17760
|
+
import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
|
|
17761
|
+
import * as path38 from "path";
|
|
17654
17762
|
import { fileURLToPath } from "url";
|
|
17655
17763
|
// package.json
|
|
17656
17764
|
var package_default = {
|
|
17657
17765
|
name: "opencode-swarm",
|
|
17658
|
-
version: "7.107.
|
|
17766
|
+
version: "7.107.4",
|
|
17659
17767
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
17660
17768
|
main: "dist/index.js",
|
|
17661
17769
|
types: "dist/index.d.ts",
|
|
@@ -17763,44 +17871,44 @@ var package_default = {
|
|
|
17763
17871
|
|
|
17764
17872
|
// src/config/cache-paths.ts
|
|
17765
17873
|
import * as os7 from "os";
|
|
17766
|
-
import * as
|
|
17874
|
+
import * as path34 from "path";
|
|
17767
17875
|
function getPluginConfigDir() {
|
|
17768
|
-
return
|
|
17876
|
+
return path34.join(process.env.XDG_CONFIG_HOME || path34.join(os7.homedir(), ".config"), "opencode");
|
|
17769
17877
|
}
|
|
17770
17878
|
function getPluginCachePaths() {
|
|
17771
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17879
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os7.homedir(), ".cache");
|
|
17772
17880
|
const configDir = getPluginConfigDir();
|
|
17773
17881
|
const paths = [
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17882
|
+
path34.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
17883
|
+
path34.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
17884
|
+
path34.join(configDir, "node_modules", "opencode-swarm")
|
|
17777
17885
|
];
|
|
17778
17886
|
if (process.platform === "darwin") {
|
|
17779
|
-
const libCaches =
|
|
17780
|
-
paths.push(
|
|
17887
|
+
const libCaches = path34.join(os7.homedir(), "Library", "Caches");
|
|
17888
|
+
paths.push(path34.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path34.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
17781
17889
|
}
|
|
17782
17890
|
if (process.platform === "win32") {
|
|
17783
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17784
|
-
const appData = process.env.APPDATA ||
|
|
17785
|
-
paths.push(
|
|
17891
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os7.homedir(), "AppData", "Local");
|
|
17892
|
+
const appData = process.env.APPDATA || path34.join(os7.homedir(), "AppData", "Roaming");
|
|
17893
|
+
paths.push(path34.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path34.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path34.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
17786
17894
|
}
|
|
17787
17895
|
return paths;
|
|
17788
17896
|
}
|
|
17789
17897
|
function getPluginLockFilePaths() {
|
|
17790
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17898
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os7.homedir(), ".cache");
|
|
17791
17899
|
const configDir = getPluginConfigDir();
|
|
17792
17900
|
const paths = [
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
17901
|
+
path34.join(cacheBase, "opencode", "bun.lock"),
|
|
17902
|
+
path34.join(cacheBase, "opencode", "bun.lockb"),
|
|
17903
|
+
path34.join(configDir, "package-lock.json")
|
|
17796
17904
|
];
|
|
17797
17905
|
if (process.platform === "darwin") {
|
|
17798
|
-
const libCaches =
|
|
17799
|
-
paths.push(
|
|
17906
|
+
const libCaches = path34.join(os7.homedir(), "Library", "Caches");
|
|
17907
|
+
paths.push(path34.join(libCaches, "opencode", "bun.lock"), path34.join(libCaches, "opencode", "bun.lockb"));
|
|
17800
17908
|
}
|
|
17801
17909
|
if (process.platform === "win32") {
|
|
17802
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17803
|
-
paths.push(
|
|
17910
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os7.homedir(), "AppData", "Local");
|
|
17911
|
+
paths.push(path34.join(localAppData, "opencode", "bun.lock"), path34.join(localAppData, "opencode", "bun.lockb"));
|
|
17804
17912
|
}
|
|
17805
17913
|
return paths;
|
|
17806
17914
|
}
|
|
@@ -17810,11 +17918,11 @@ init_capability_probe();
|
|
|
17810
17918
|
init_executor();
|
|
17811
17919
|
|
|
17812
17920
|
// src/services/knowledge-diagnostics.ts
|
|
17813
|
-
import { existsSync as
|
|
17921
|
+
import { existsSync as existsSync21 } from "fs";
|
|
17814
17922
|
import { readFile as readFile12 } from "fs/promises";
|
|
17815
17923
|
|
|
17816
17924
|
// src/services/version-check.ts
|
|
17817
|
-
import { existsSync as
|
|
17925
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
17818
17926
|
import { homedir as homedir6 } from "os";
|
|
17819
17927
|
import { join as join32 } from "path";
|
|
17820
17928
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -17830,10 +17938,10 @@ function cacheFile() {
|
|
|
17830
17938
|
}
|
|
17831
17939
|
function readVersionCache() {
|
|
17832
17940
|
try {
|
|
17833
|
-
const
|
|
17834
|
-
if (!
|
|
17941
|
+
const path38 = cacheFile();
|
|
17942
|
+
if (!existsSync20(path38))
|
|
17835
17943
|
return null;
|
|
17836
|
-
const raw = readFileSync10(
|
|
17944
|
+
const raw = readFileSync10(path38, "utf-8");
|
|
17837
17945
|
const parsed = JSON.parse(raw);
|
|
17838
17946
|
if (typeof parsed?.checkedAt !== "number")
|
|
17839
17947
|
return null;
|
|
@@ -17885,7 +17993,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
|
|
|
17885
17993
|
var UNACTIONABLE_BACKLOG_WARN = 100;
|
|
17886
17994
|
var INSIGHT_BACKLOG_WARN = 50;
|
|
17887
17995
|
async function readRawLines(filePath) {
|
|
17888
|
-
if (!
|
|
17996
|
+
if (!existsSync21(filePath))
|
|
17889
17997
|
return { entries: [], corrupt: 0 };
|
|
17890
17998
|
const content = await readFile12(filePath, "utf-8");
|
|
17891
17999
|
const entries = [];
|
|
@@ -18010,7 +18118,7 @@ async function computeKnowledgeDebug(directory) {
|
|
|
18010
18118
|
};
|
|
18011
18119
|
}
|
|
18012
18120
|
async function safeJsonlCount(filePath) {
|
|
18013
|
-
if (!filePath || !
|
|
18121
|
+
if (!filePath || !existsSync21(filePath))
|
|
18014
18122
|
return 0;
|
|
18015
18123
|
try {
|
|
18016
18124
|
const content = await readFile12(filePath, "utf-8");
|
|
@@ -18088,8 +18196,8 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
|
|
|
18088
18196
|
"tree-sitter-typescript.wasm"
|
|
18089
18197
|
];
|
|
18090
18198
|
function resolveCachePackageRoot(cachePath) {
|
|
18091
|
-
const nestedPackageRoot =
|
|
18092
|
-
return
|
|
18199
|
+
const nestedPackageRoot = path38.join(cachePath, "node_modules", "opencode-swarm");
|
|
18200
|
+
return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
18093
18201
|
}
|
|
18094
18202
|
var _internals26 = {
|
|
18095
18203
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
@@ -18340,7 +18448,7 @@ async function checkConfigBackups(directory) {
|
|
|
18340
18448
|
}
|
|
18341
18449
|
async function checkGitRepository(directory) {
|
|
18342
18450
|
try {
|
|
18343
|
-
if (!
|
|
18451
|
+
if (!existsSync22(directory) || !statSync7(directory).isDirectory()) {
|
|
18344
18452
|
return {
|
|
18345
18453
|
name: "Git Repository",
|
|
18346
18454
|
status: "\u274C",
|
|
@@ -18404,8 +18512,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
18404
18512
|
};
|
|
18405
18513
|
}
|
|
18406
18514
|
async function checkConfigParseability(directory) {
|
|
18407
|
-
const configPath =
|
|
18408
|
-
if (!
|
|
18515
|
+
const configPath = path38.join(directory, ".opencode/opencode-swarm.json");
|
|
18516
|
+
if (!existsSync22(configPath)) {
|
|
18409
18517
|
return {
|
|
18410
18518
|
name: "Config Parseability",
|
|
18411
18519
|
status: "\u2705",
|
|
@@ -18433,7 +18541,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
18433
18541
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
18434
18542
|
const isSource = normalized.endsWith("/src/services");
|
|
18435
18543
|
const isCliBundle = normalized.endsWith("/cli");
|
|
18436
|
-
return isSource || isCliBundle ?
|
|
18544
|
+
return isSource || isCliBundle ? path38.join(thisDir, "..", "lang", "grammars") : path38.join(thisDir, "lang", "grammars");
|
|
18437
18545
|
}
|
|
18438
18546
|
async function checkGrammarWasmFiles() {
|
|
18439
18547
|
const grammarFiles = [
|
|
@@ -18457,14 +18565,14 @@ async function checkGrammarWasmFiles() {
|
|
|
18457
18565
|
"tree-sitter-ini.wasm",
|
|
18458
18566
|
"tree-sitter-regex.wasm"
|
|
18459
18567
|
];
|
|
18460
|
-
const thisDir =
|
|
18568
|
+
const thisDir = path38.dirname(fileURLToPath(import.meta.url));
|
|
18461
18569
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
18462
18570
|
const missing = [];
|
|
18463
|
-
if (!
|
|
18571
|
+
if (!existsSync22(path38.join(grammarDir, "tree-sitter.wasm"))) {
|
|
18464
18572
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
18465
18573
|
}
|
|
18466
18574
|
for (const file of grammarFiles) {
|
|
18467
|
-
if (!
|
|
18575
|
+
if (!existsSync22(path38.join(grammarDir, file))) {
|
|
18468
18576
|
missing.push(file);
|
|
18469
18577
|
}
|
|
18470
18578
|
}
|
|
@@ -18482,8 +18590,8 @@ async function checkGrammarWasmFiles() {
|
|
|
18482
18590
|
};
|
|
18483
18591
|
}
|
|
18484
18592
|
async function checkCheckpointManifest(directory) {
|
|
18485
|
-
const manifestPath =
|
|
18486
|
-
if (!
|
|
18593
|
+
const manifestPath = path38.join(directory, ".swarm/checkpoints.json");
|
|
18594
|
+
if (!existsSync22(manifestPath)) {
|
|
18487
18595
|
return {
|
|
18488
18596
|
name: "Checkpoint Manifest",
|
|
18489
18597
|
status: "\u2705",
|
|
@@ -18534,8 +18642,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
18534
18642
|
}
|
|
18535
18643
|
}
|
|
18536
18644
|
async function checkEventStreamIntegrity(directory) {
|
|
18537
|
-
const eventsPath =
|
|
18538
|
-
if (!
|
|
18645
|
+
const eventsPath = path38.join(directory, ".swarm/events.jsonl");
|
|
18646
|
+
if (!existsSync22(eventsPath)) {
|
|
18539
18647
|
return {
|
|
18540
18648
|
name: "Event Stream",
|
|
18541
18649
|
status: "\u2705",
|
|
@@ -18575,8 +18683,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
18575
18683
|
}
|
|
18576
18684
|
}
|
|
18577
18685
|
async function checkSteeringDirectives(directory) {
|
|
18578
|
-
const eventsPath =
|
|
18579
|
-
if (!
|
|
18686
|
+
const eventsPath = path38.join(directory, ".swarm/events.jsonl");
|
|
18687
|
+
if (!existsSync22(eventsPath)) {
|
|
18580
18688
|
return {
|
|
18581
18689
|
name: "Steering Directives",
|
|
18582
18690
|
status: "\u2705",
|
|
@@ -18631,8 +18739,8 @@ async function checkCurator(directory) {
|
|
|
18631
18739
|
detail: "Disabled (enable via curator.enabled)"
|
|
18632
18740
|
};
|
|
18633
18741
|
}
|
|
18634
|
-
const summaryPath =
|
|
18635
|
-
if (!
|
|
18742
|
+
const summaryPath = path38.join(directory, ".swarm/curator-summary.json");
|
|
18743
|
+
if (!existsSync22(summaryPath)) {
|
|
18636
18744
|
return {
|
|
18637
18745
|
name: "Curator",
|
|
18638
18746
|
status: "\u2705",
|
|
@@ -18833,8 +18941,8 @@ async function getDiagnoseData(directory) {
|
|
|
18833
18941
|
checks.push(await checkCurator(directory));
|
|
18834
18942
|
checks.push(await checkKnowledgeHealth(directory));
|
|
18835
18943
|
try {
|
|
18836
|
-
const evidenceDir =
|
|
18837
|
-
const snapshotFiles =
|
|
18944
|
+
const evidenceDir = path38.join(directory, ".swarm", "evidence");
|
|
18945
|
+
const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
18838
18946
|
if (snapshotFiles.length > 0) {
|
|
18839
18947
|
const latest = snapshotFiles.sort().pop();
|
|
18840
18948
|
checks.push({
|
|
@@ -18867,14 +18975,14 @@ async function getDiagnoseData(directory) {
|
|
|
18867
18975
|
const cacheRows = [];
|
|
18868
18976
|
for (const cachePath of cachePaths) {
|
|
18869
18977
|
try {
|
|
18870
|
-
if (!
|
|
18978
|
+
if (!existsSync22(cachePath)) {
|
|
18871
18979
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
18872
18980
|
continue;
|
|
18873
18981
|
}
|
|
18874
18982
|
const packageRoot = resolveCachePackageRoot(cachePath);
|
|
18875
18983
|
const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
|
|
18876
|
-
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !
|
|
18877
|
-
const pkgJsonPath =
|
|
18984
|
+
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path38.join(packageRoot, "dist", "lang", "grammars", file)));
|
|
18985
|
+
const pkgJsonPath = path38.join(packageRoot, "package.json");
|
|
18878
18986
|
try {
|
|
18879
18987
|
const raw = readFileSync11(pkgJsonPath, "utf-8");
|
|
18880
18988
|
const parsed = JSON.parse(raw);
|
|
@@ -19099,7 +19207,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
19099
19207
|
const result = runConfigDoctor(config, directory);
|
|
19100
19208
|
let output;
|
|
19101
19209
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
19102
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
19210
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-kdq3vae4.js");
|
|
19103
19211
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true);
|
|
19104
19212
|
output = formatDoctorMarkdown(fixResult.result);
|
|
19105
19213
|
} else {
|
|
@@ -19250,9 +19358,9 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
|
|
|
19250
19358
|
// src/turbo/epic/calibration.ts
|
|
19251
19359
|
init_logger();
|
|
19252
19360
|
import * as fs13 from "fs";
|
|
19253
|
-
import * as
|
|
19361
|
+
import * as path39 from "path";
|
|
19254
19362
|
var STATE_FILE = "calibration.json";
|
|
19255
|
-
var STATE_REL_DIR =
|
|
19363
|
+
var STATE_REL_DIR = path39.join(".swarm", "epic");
|
|
19256
19364
|
function nowISO() {
|
|
19257
19365
|
return new Date().toISOString();
|
|
19258
19366
|
}
|
|
@@ -19274,7 +19382,7 @@ function markUnreadable(directory, reason) {
|
|
|
19274
19382
|
error(`[epic/calibration] state file unreadable for ${directory}: ${reason} \u2014 failing closed`);
|
|
19275
19383
|
}
|
|
19276
19384
|
function repairCalibrationUnreadable(directory) {
|
|
19277
|
-
const filePath =
|
|
19385
|
+
const filePath = path39.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19278
19386
|
if (!fs13.existsSync(filePath)) {
|
|
19279
19387
|
stateUnreadableMap.delete(directory);
|
|
19280
19388
|
return;
|
|
@@ -19306,7 +19414,7 @@ function isValidCalibrationShape(candidate) {
|
|
|
19306
19414
|
return true;
|
|
19307
19415
|
}
|
|
19308
19416
|
function ensureSwarmEpicDir(directory) {
|
|
19309
|
-
const dir =
|
|
19417
|
+
const dir = path39.resolve(directory, STATE_REL_DIR);
|
|
19310
19418
|
if (!fs13.existsSync(dir)) {
|
|
19311
19419
|
fs13.mkdirSync(dir, { recursive: true });
|
|
19312
19420
|
}
|
|
@@ -19318,7 +19426,7 @@ function loadCalibrationState(directory) {
|
|
|
19318
19426
|
if (stateUnreadableMap.get(directory))
|
|
19319
19427
|
return null;
|
|
19320
19428
|
}
|
|
19321
|
-
const filePath =
|
|
19429
|
+
const filePath = path39.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
19322
19430
|
try {
|
|
19323
19431
|
if (!fs13.existsSync(filePath)) {
|
|
19324
19432
|
const seed = emptyCalibrationState();
|
|
@@ -19345,12 +19453,12 @@ function loadCalibrationState(directory) {
|
|
|
19345
19453
|
// src/turbo/epic/divergence-recorder.ts
|
|
19346
19454
|
init_logger();
|
|
19347
19455
|
import * as fs14 from "fs";
|
|
19348
|
-
import * as
|
|
19349
|
-
var EVIDENCE_REL_DIR =
|
|
19456
|
+
import * as path40 from "path";
|
|
19457
|
+
var EVIDENCE_REL_DIR = path40.join(".swarm", "epic");
|
|
19350
19458
|
var EVIDENCE_FILE = "divergence.jsonl";
|
|
19351
19459
|
var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
|
|
19352
19460
|
function readDivergenceHistory(directory, options) {
|
|
19353
|
-
const filePath =
|
|
19461
|
+
const filePath = path40.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
|
|
19354
19462
|
if (!fs14.existsSync(filePath)) {
|
|
19355
19463
|
return [];
|
|
19356
19464
|
}
|
|
@@ -19399,11 +19507,11 @@ function readDivergenceHistory(directory, options) {
|
|
|
19399
19507
|
|
|
19400
19508
|
// src/turbo/epic/promotion-evidence.ts
|
|
19401
19509
|
import * as fs15 from "fs";
|
|
19402
|
-
import * as
|
|
19403
|
-
var EVIDENCE_REL_DIR2 =
|
|
19510
|
+
import * as path41 from "path";
|
|
19511
|
+
var EVIDENCE_REL_DIR2 = path41.join(".swarm", "evidence");
|
|
19404
19512
|
var EVIDENCE_FILE2 = "epic-promotions.jsonl";
|
|
19405
19513
|
function readPromotionEvidence(directory) {
|
|
19406
|
-
const filePath =
|
|
19514
|
+
const filePath = path41.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
|
|
19407
19515
|
if (!fs15.existsSync(filePath)) {
|
|
19408
19516
|
return [];
|
|
19409
19517
|
}
|
|
@@ -19912,7 +20020,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
19912
20020
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
19913
20021
|
}
|
|
19914
20022
|
async function handleEvidenceSummaryCommand(directory) {
|
|
19915
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
20023
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-nwdfnbz1.js");
|
|
19916
20024
|
const artifact = await buildEvidenceSummary(directory);
|
|
19917
20025
|
if (!artifact) {
|
|
19918
20026
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -19977,7 +20085,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
19977
20085
|
// src/full-auto/state.ts
|
|
19978
20086
|
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
19979
20087
|
import * as fs16 from "fs";
|
|
19980
|
-
import * as
|
|
20088
|
+
import * as path42 from "path";
|
|
19981
20089
|
init_logger();
|
|
19982
20090
|
var lockfile4 = import_proper_lockfile4.default;
|
|
19983
20091
|
var STATE_FILE2 = "full-auto-state.json";
|
|
@@ -19985,7 +20093,7 @@ function nowISO2() {
|
|
|
19985
20093
|
return new Date().toISOString();
|
|
19986
20094
|
}
|
|
19987
20095
|
function ensureSwarmDir(directory) {
|
|
19988
|
-
const swarmDir =
|
|
20096
|
+
const swarmDir = path42.resolve(directory, ".swarm");
|
|
19989
20097
|
if (!fs16.existsSync(swarmDir)) {
|
|
19990
20098
|
fs16.mkdirSync(swarmDir, { recursive: true });
|
|
19991
20099
|
}
|
|
@@ -20797,7 +20905,7 @@ var _internals29 = {
|
|
|
20797
20905
|
|
|
20798
20906
|
// src/session/snapshot-writer.ts
|
|
20799
20907
|
import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync18, openSync as openSync6, renameSync as renameSync9 } from "fs";
|
|
20800
|
-
import * as
|
|
20908
|
+
import * as path43 from "path";
|
|
20801
20909
|
var _writeInFlight = Promise.resolve();
|
|
20802
20910
|
function serializeAgentSession(s) {
|
|
20803
20911
|
const gateLog = {};
|
|
@@ -20910,7 +21018,7 @@ async function writeSnapshot(directory, state) {
|
|
|
20910
21018
|
}
|
|
20911
21019
|
const content = JSON.stringify(snapshot, null, 2);
|
|
20912
21020
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
20913
|
-
const dir =
|
|
21021
|
+
const dir = path43.dirname(resolvedPath);
|
|
20914
21022
|
mkdirSync18(dir, { recursive: true });
|
|
20915
21023
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
20916
21024
|
await bunWrite(tempPath, content);
|
|
@@ -21421,23 +21529,18 @@ ${USAGE6}`;
|
|
|
21421
21529
|
}
|
|
21422
21530
|
|
|
21423
21531
|
// src/commands/knowledge.ts
|
|
21424
|
-
import { join as
|
|
21532
|
+
import { join as join38 } from "path";
|
|
21425
21533
|
|
|
21426
21534
|
// src/hooks/knowledge-migrator.ts
|
|
21427
21535
|
init_logger();
|
|
21428
21536
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
21429
|
-
import { existsSync as
|
|
21537
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16 } from "fs";
|
|
21430
21538
|
import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
|
|
21431
21539
|
import * as os11 from "os";
|
|
21432
|
-
import * as
|
|
21433
|
-
|
|
21434
|
-
// src/hooks/knowledge-types.ts
|
|
21435
|
-
var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
21436
|
-
|
|
21437
|
-
// src/hooks/knowledge-migrator.ts
|
|
21540
|
+
import * as path44 from "path";
|
|
21438
21541
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
21439
|
-
const externalSentinelPath =
|
|
21440
|
-
const contextPath =
|
|
21542
|
+
const externalSentinelPath = path44.join(_directory, ".swarm", ".knowledge-external-migrated");
|
|
21543
|
+
const contextPath = path44.join(_directory, ".swarm", "context.md");
|
|
21441
21544
|
if (_internals32.existsSync(externalSentinelPath)) {
|
|
21442
21545
|
return {
|
|
21443
21546
|
migrated: false,
|
|
@@ -21495,17 +21598,17 @@ var _internals32 = {
|
|
|
21495
21598
|
inferProjectName,
|
|
21496
21599
|
writeSentinel,
|
|
21497
21600
|
resolveLegacyHiveKnowledgePath,
|
|
21498
|
-
existsSync:
|
|
21601
|
+
existsSync: existsSync27,
|
|
21499
21602
|
readFileSync: readFileSync16,
|
|
21500
21603
|
readFile: readFile13,
|
|
21501
21604
|
mkdir: mkdir10,
|
|
21502
21605
|
writeFile: writeFile12
|
|
21503
21606
|
};
|
|
21504
21607
|
async function migrateContextToKnowledge(directory, config) {
|
|
21505
|
-
const sentinelPath =
|
|
21506
|
-
const contextPath =
|
|
21608
|
+
const sentinelPath = path44.join(directory, ".swarm", ".knowledge-migrated");
|
|
21609
|
+
const contextPath = path44.join(directory, ".swarm", "context.md");
|
|
21507
21610
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
21508
|
-
if (
|
|
21611
|
+
if (existsSync27(sentinelPath)) {
|
|
21509
21612
|
return {
|
|
21510
21613
|
migrated: false,
|
|
21511
21614
|
entriesMigrated: 0,
|
|
@@ -21514,7 +21617,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21514
21617
|
skippedReason: "sentinel-exists"
|
|
21515
21618
|
};
|
|
21516
21619
|
}
|
|
21517
|
-
if (!
|
|
21620
|
+
if (!existsSync27(contextPath)) {
|
|
21518
21621
|
return {
|
|
21519
21622
|
migrated: false,
|
|
21520
21623
|
entriesMigrated: 0,
|
|
@@ -21605,8 +21708,8 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
21605
21708
|
async function migrateHiveKnowledgeLegacy(config) {
|
|
21606
21709
|
const legacyHivePath = _internals32.resolveLegacyHiveKnowledgePath();
|
|
21607
21710
|
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
21608
|
-
const sentinelPath =
|
|
21609
|
-
if (
|
|
21711
|
+
const sentinelPath = path44.join(path44.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
21712
|
+
if (existsSync27(sentinelPath)) {
|
|
21610
21713
|
return {
|
|
21611
21714
|
migrated: false,
|
|
21612
21715
|
entriesMigrated: 0,
|
|
@@ -21615,7 +21718,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
21615
21718
|
skippedReason: "sentinel-exists"
|
|
21616
21719
|
};
|
|
21617
21720
|
}
|
|
21618
|
-
if (!
|
|
21721
|
+
if (!existsSync27(legacyHivePath)) {
|
|
21619
21722
|
return {
|
|
21620
21723
|
migrated: false,
|
|
21621
21724
|
entriesMigrated: 0,
|
|
@@ -21816,8 +21919,8 @@ function truncateLesson2(text) {
|
|
|
21816
21919
|
return `${text.slice(0, 277)}...`;
|
|
21817
21920
|
}
|
|
21818
21921
|
function inferProjectName(directory) {
|
|
21819
|
-
const packageJsonPath =
|
|
21820
|
-
if (
|
|
21922
|
+
const packageJsonPath = path44.join(directory, "package.json");
|
|
21923
|
+
if (existsSync27(packageJsonPath)) {
|
|
21821
21924
|
try {
|
|
21822
21925
|
const pkg = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
|
|
21823
21926
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -21825,7 +21928,7 @@ function inferProjectName(directory) {
|
|
|
21825
21928
|
}
|
|
21826
21929
|
} catch {}
|
|
21827
21930
|
}
|
|
21828
|
-
return
|
|
21931
|
+
return path44.basename(directory);
|
|
21829
21932
|
}
|
|
21830
21933
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
21831
21934
|
const sentinel = {
|
|
@@ -21837,7 +21940,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
21837
21940
|
schema_version: 1,
|
|
21838
21941
|
migration_tool: "knowledge-migrator.ts"
|
|
21839
21942
|
};
|
|
21840
|
-
await _internals32.mkdir(
|
|
21943
|
+
await _internals32.mkdir(path44.dirname(sentinelPath), { recursive: true });
|
|
21841
21944
|
await _internals32.writeFile(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
21842
21945
|
}
|
|
21843
21946
|
function resolveLegacyHiveKnowledgePath() {
|
|
@@ -21845,13 +21948,13 @@ function resolveLegacyHiveKnowledgePath() {
|
|
|
21845
21948
|
const home = process.env.HOME || os11.homedir();
|
|
21846
21949
|
let dataDir;
|
|
21847
21950
|
if (platform === "win32") {
|
|
21848
|
-
dataDir =
|
|
21951
|
+
dataDir = path44.join(process.env.LOCALAPPDATA || path44.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
21849
21952
|
} else if (platform === "darwin") {
|
|
21850
|
-
dataDir =
|
|
21953
|
+
dataDir = path44.join(home, "Library", "Application Support", "opencode-swarm");
|
|
21851
21954
|
} else {
|
|
21852
|
-
dataDir =
|
|
21955
|
+
dataDir = path44.join(process.env.XDG_DATA_HOME || path44.join(home, ".local", "share"), "opencode-swarm");
|
|
21853
21956
|
}
|
|
21854
|
-
return
|
|
21957
|
+
return path44.join(dataDir, "hive-knowledge.jsonl");
|
|
21855
21958
|
}
|
|
21856
21959
|
|
|
21857
21960
|
// src/commands/knowledge.ts
|
|
@@ -21905,10 +22008,23 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
21905
22008
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
21906
22009
|
}
|
|
21907
22010
|
try {
|
|
21908
|
-
const
|
|
22011
|
+
const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
22012
|
+
const swarmResolved = resolveEntryByPrefix(swarmEntries, inputId);
|
|
22013
|
+
if ("entry" in swarmResolved && swarmResolved.entry.status === "archived") {
|
|
22014
|
+
const fullId2 = swarmResolved.entry.id;
|
|
22015
|
+
const result = await unarchiveEntry(directory, fullId2);
|
|
22016
|
+
if (result.restored) {
|
|
22017
|
+
return `\u2705 Archived entry ${fullId2} restored to '${result.restored_to}'.`;
|
|
22018
|
+
}
|
|
22019
|
+
return `\u274C Entry ${fullId2} could not be unarchived${result.reason ? ` (${result.reason})` : ""}.`;
|
|
22020
|
+
}
|
|
22021
|
+
const quarantinePath = join38(resolveKnowledgeStoreDir(directory), "knowledge-quarantined.jsonl");
|
|
21909
22022
|
const entries = await readKnowledge(quarantinePath);
|
|
21910
22023
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
21911
22024
|
if ("error" in resolved) {
|
|
22025
|
+
if ("entry" in swarmResolved) {
|
|
22026
|
+
return `\u274C Entry ${swarmResolved.entry.id} is neither archived nor quarantined (status: '${swarmResolved.entry.status}'). Only archived or quarantined entries can be restored.`;
|
|
22027
|
+
}
|
|
21912
22028
|
return `\u274C ${resolved.error}`;
|
|
21913
22029
|
}
|
|
21914
22030
|
const fullId = resolved.entry.id;
|
|
@@ -22156,15 +22272,15 @@ var _internals33 = {
|
|
|
22156
22272
|
};
|
|
22157
22273
|
|
|
22158
22274
|
// src/commands/link.ts
|
|
22159
|
-
import { existsSync as
|
|
22160
|
-
import * as
|
|
22275
|
+
import { existsSync as existsSync28 } from "fs";
|
|
22276
|
+
import * as path46 from "path";
|
|
22161
22277
|
|
|
22162
22278
|
// src/knowledge/identity.ts
|
|
22163
22279
|
import * as child_process5 from "child_process";
|
|
22164
22280
|
import { createHash as createHash5 } from "crypto";
|
|
22165
|
-
import * as
|
|
22281
|
+
import * as path45 from "path";
|
|
22166
22282
|
function deriveProjectHash(directory) {
|
|
22167
|
-
const absolutePath =
|
|
22283
|
+
const absolutePath = path45.resolve(directory);
|
|
22168
22284
|
let hashInput;
|
|
22169
22285
|
try {
|
|
22170
22286
|
const remoteUrl = child_process5.execSync("git remote get-url origin", {
|
|
@@ -22184,9 +22300,9 @@ function deriveProjectHash(directory) {
|
|
|
22184
22300
|
// src/commands/link.ts
|
|
22185
22301
|
var DEDUP_THRESHOLD = 0.6;
|
|
22186
22302
|
async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
|
|
22187
|
-
const localPath =
|
|
22188
|
-
const sharedPath =
|
|
22189
|
-
if (!
|
|
22303
|
+
const localPath = path46.join(localSwarmDir, "knowledge.jsonl");
|
|
22304
|
+
const sharedPath = path46.join(linkDir, "knowledge.jsonl");
|
|
22305
|
+
if (!existsSync28(localPath))
|
|
22190
22306
|
return { merged: 0, skipped: 0 };
|
|
22191
22307
|
let merged = 0;
|
|
22192
22308
|
let skipped = 0;
|
|
@@ -22283,7 +22399,7 @@ ${formatStatus(directory)}`;
|
|
|
22283
22399
|
const linkDir = resolveLinkDir(linkId);
|
|
22284
22400
|
let merge;
|
|
22285
22401
|
try {
|
|
22286
|
-
merge = await mergeLocalKnowledgeIntoLink(
|
|
22402
|
+
merge = await mergeLocalKnowledgeIntoLink(path46.join(directory, ".swarm"), linkDir);
|
|
22287
22403
|
} catch (error2) {
|
|
22288
22404
|
return `\u274C Failed to merge local knowledge into the link store: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
22289
22405
|
}
|
|
@@ -22479,13 +22595,13 @@ ${USAGE7}`;
|
|
|
22479
22595
|
}
|
|
22480
22596
|
|
|
22481
22597
|
// src/commands/memory.ts
|
|
22482
|
-
import { existsSync as
|
|
22483
|
-
import * as
|
|
22598
|
+
import { existsSync as existsSync29 } from "fs";
|
|
22599
|
+
import * as path49 from "path";
|
|
22484
22600
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22485
22601
|
// src/memory/evaluation.ts
|
|
22486
22602
|
import * as fs17 from "fs/promises";
|
|
22487
22603
|
import * as os12 from "os";
|
|
22488
|
-
import * as
|
|
22604
|
+
import * as path47 from "path";
|
|
22489
22605
|
var DEFAULT_PROVIDERS = [
|
|
22490
22606
|
"local-jsonl",
|
|
22491
22607
|
"sqlite"
|
|
@@ -22497,7 +22613,7 @@ var DEFAULT_MODES = [
|
|
|
22497
22613
|
];
|
|
22498
22614
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
22499
22615
|
async function evaluateMemoryRecallFixtures(options) {
|
|
22500
|
-
const fixtureDirectory =
|
|
22616
|
+
const fixtureDirectory = path47.resolve(options.fixtureDirectory);
|
|
22501
22617
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
22502
22618
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
22503
22619
|
const generatedAt = new Date().toISOString();
|
|
@@ -22506,7 +22622,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
22506
22622
|
for (const fixture of fixtures) {
|
|
22507
22623
|
const materialized = materializeFixture(fixture);
|
|
22508
22624
|
for (const providerName of providers) {
|
|
22509
|
-
const tempRoot = await fs17.realpath(await fs17.mkdtemp(
|
|
22625
|
+
const tempRoot = await fs17.realpath(await fs17.mkdtemp(path47.join(os12.tmpdir(), "swarm-memory-eval-")));
|
|
22510
22626
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
22511
22627
|
try {
|
|
22512
22628
|
await provider.initialize?.();
|
|
@@ -22563,7 +22679,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
|
22563
22679
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
22564
22680
|
const fixtures = [];
|
|
22565
22681
|
for (const file of files) {
|
|
22566
|
-
const raw = await fs17.readFile(
|
|
22682
|
+
const raw = await fs17.readFile(path47.join(fixtureDirectory, file), "utf-8");
|
|
22567
22683
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
22568
22684
|
}
|
|
22569
22685
|
return fixtures;
|
|
@@ -22840,8 +22956,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
22840
22956
|
}).passthrough();
|
|
22841
22957
|
// src/memory/consolidation-log.ts
|
|
22842
22958
|
import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
|
|
22843
|
-
import * as
|
|
22844
|
-
var LOG_RELATIVE_PATH =
|
|
22959
|
+
import * as path48 from "path";
|
|
22960
|
+
var LOG_RELATIVE_PATH = path48.join("memory", "consolidation-log.jsonl");
|
|
22845
22961
|
async function readConsolidationLog(directory) {
|
|
22846
22962
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
22847
22963
|
let raw;
|
|
@@ -22864,7 +22980,7 @@ async function readConsolidationLog(directory) {
|
|
|
22864
22980
|
}
|
|
22865
22981
|
|
|
22866
22982
|
// src/commands/memory.ts
|
|
22867
|
-
var PACKAGE_ROOT =
|
|
22983
|
+
var PACKAGE_ROOT = path49.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
22868
22984
|
async function handleMemoryCommand(_directory, _args) {
|
|
22869
22985
|
return [
|
|
22870
22986
|
"## Swarm Memory",
|
|
@@ -22923,7 +23039,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
22923
23039
|
`- Provider: \`${config.provider}\``,
|
|
22924
23040
|
`- Storage: \`${storageDir}\``,
|
|
22925
23041
|
`- SQLite path: \`${sqlitePath}\``,
|
|
22926
|
-
`- SQLite database exists: \`${
|
|
23042
|
+
`- SQLite database exists: \`${existsSync29(sqlitePath)}\``,
|
|
22927
23043
|
`- Automatic destructive cleanup: \`disabled\``,
|
|
22928
23044
|
"",
|
|
22929
23045
|
"### Legacy JSONL"
|
|
@@ -23221,7 +23337,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
23221
23337
|
}
|
|
23222
23338
|
function parseEvaluateArgs(directory, args) {
|
|
23223
23339
|
let json = false;
|
|
23224
|
-
let fixtureDirectory =
|
|
23340
|
+
let fixtureDirectory = path49.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
23225
23341
|
for (let i = 0;i < args.length; i++) {
|
|
23226
23342
|
const arg = args[i];
|
|
23227
23343
|
if (arg === "--json") {
|
|
@@ -23235,10 +23351,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
23235
23351
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
23236
23352
|
};
|
|
23237
23353
|
}
|
|
23238
|
-
const resolvedFixtures =
|
|
23239
|
-
const canonical =
|
|
23240
|
-
const allowedRootA =
|
|
23241
|
-
const allowedRootB =
|
|
23354
|
+
const resolvedFixtures = path49.resolve(directory, next);
|
|
23355
|
+
const canonical = path49.normalize(resolvedFixtures) + path49.sep;
|
|
23356
|
+
const allowedRootA = path49.normalize(directory) + path49.sep;
|
|
23357
|
+
const allowedRootB = path49.normalize(path49.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path49.sep;
|
|
23242
23358
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
23243
23359
|
return {
|
|
23244
23360
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -23277,15 +23393,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
23277
23393
|
return { limit, confirm };
|
|
23278
23394
|
}
|
|
23279
23395
|
function resolvePackageRootFromModule(modulePath) {
|
|
23280
|
-
const moduleDir =
|
|
23281
|
-
const leaf =
|
|
23396
|
+
const moduleDir = path49.dirname(modulePath);
|
|
23397
|
+
const leaf = path49.basename(moduleDir);
|
|
23282
23398
|
if (leaf === "commands" || leaf === "cli") {
|
|
23283
|
-
return
|
|
23399
|
+
return path49.resolve(moduleDir, "..", "..");
|
|
23284
23400
|
}
|
|
23285
23401
|
if (leaf === "dist") {
|
|
23286
|
-
return
|
|
23402
|
+
return path49.resolve(moduleDir, "..");
|
|
23287
23403
|
}
|
|
23288
|
-
return
|
|
23404
|
+
return path49.resolve(moduleDir, "..");
|
|
23289
23405
|
}
|
|
23290
23406
|
function formatMigrationResult(label, report) {
|
|
23291
23407
|
if (!report) {
|
|
@@ -24020,11 +24136,11 @@ var _internals39 = {
|
|
|
24020
24136
|
|
|
24021
24137
|
// src/services/preflight-service.ts
|
|
24022
24138
|
import * as fs24 from "fs";
|
|
24023
|
-
import * as
|
|
24139
|
+
import * as path56 from "path";
|
|
24024
24140
|
|
|
24025
24141
|
// src/tools/lint.ts
|
|
24026
24142
|
import * as fs18 from "fs";
|
|
24027
|
-
import * as
|
|
24143
|
+
import * as path50 from "path";
|
|
24028
24144
|
|
|
24029
24145
|
// src/utils/path-security.ts
|
|
24030
24146
|
function containsPathTraversal(str) {
|
|
@@ -24080,9 +24196,9 @@ function validateArgs(args) {
|
|
|
24080
24196
|
}
|
|
24081
24197
|
function getLinterCommand(linter, mode, projectDir) {
|
|
24082
24198
|
const isWindows = process.platform === "win32";
|
|
24083
|
-
const binDir =
|
|
24084
|
-
const biomeBin = isWindows ?
|
|
24085
|
-
const eslintBin = isWindows ?
|
|
24199
|
+
const binDir = path50.join(projectDir, "node_modules", ".bin");
|
|
24200
|
+
const biomeBin = isWindows ? path50.join(binDir, "biome.EXE") : path50.join(binDir, "biome");
|
|
24201
|
+
const eslintBin = isWindows ? path50.join(binDir, "eslint.cmd") : path50.join(binDir, "eslint");
|
|
24086
24202
|
switch (linter) {
|
|
24087
24203
|
case "biome":
|
|
24088
24204
|
if (mode === "fix") {
|
|
@@ -24098,7 +24214,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
24098
24214
|
}
|
|
24099
24215
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
24100
24216
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
24101
|
-
const gradlew = fs18.existsSync(
|
|
24217
|
+
const gradlew = fs18.existsSync(path50.join(cwd, gradlewName)) ? path50.join(cwd, gradlewName) : null;
|
|
24102
24218
|
switch (linter) {
|
|
24103
24219
|
case "ruff":
|
|
24104
24220
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -24129,13 +24245,21 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
24129
24245
|
const base = useBundle ? ["bundle", "exec", "rubocop"] : ["rubocop"];
|
|
24130
24246
|
return mode === "fix" ? [...base, "-A"] : base;
|
|
24131
24247
|
}
|
|
24248
|
+
case "phpstan":
|
|
24249
|
+
return [phpVendorBin(cwd, "phpstan"), "analyse"];
|
|
24250
|
+
case "pint":
|
|
24251
|
+
return mode === "fix" ? [phpVendorBin(cwd, "pint")] : [phpVendorBin(cwd, "pint"), "--test"];
|
|
24252
|
+
case "php-cs-fixer":
|
|
24253
|
+
return mode === "fix" ? [phpVendorBin(cwd, "php-cs-fixer"), "fix"] : [phpVendorBin(cwd, "php-cs-fixer"), "fix", "--dry-run", "--diff"];
|
|
24254
|
+
case "phpcs":
|
|
24255
|
+
return [phpVendorBin(cwd, "phpcs")];
|
|
24132
24256
|
}
|
|
24133
24257
|
}
|
|
24134
24258
|
function detectRuff(cwd) {
|
|
24135
|
-
if (fs18.existsSync(
|
|
24259
|
+
if (fs18.existsSync(path50.join(cwd, "ruff.toml")))
|
|
24136
24260
|
return isCommandAvailable("ruff");
|
|
24137
24261
|
try {
|
|
24138
|
-
const pyproject =
|
|
24262
|
+
const pyproject = path50.join(cwd, "pyproject.toml");
|
|
24139
24263
|
if (fs18.existsSync(pyproject)) {
|
|
24140
24264
|
const content = fs18.readFileSync(pyproject, "utf-8");
|
|
24141
24265
|
if (content.includes("[tool.ruff]"))
|
|
@@ -24145,27 +24269,64 @@ function detectRuff(cwd) {
|
|
|
24145
24269
|
return false;
|
|
24146
24270
|
}
|
|
24147
24271
|
function detectClippy(cwd) {
|
|
24148
|
-
return fs18.existsSync(
|
|
24272
|
+
return fs18.existsSync(path50.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
24149
24273
|
}
|
|
24150
24274
|
function detectGolangciLint(cwd) {
|
|
24151
|
-
return fs18.existsSync(
|
|
24275
|
+
return fs18.existsSync(path50.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
24276
|
+
}
|
|
24277
|
+
function readTextFileSafe(filePath) {
|
|
24278
|
+
try {
|
|
24279
|
+
return fs18.readFileSync(filePath, "utf-8");
|
|
24280
|
+
} catch {
|
|
24281
|
+
return "";
|
|
24282
|
+
}
|
|
24283
|
+
}
|
|
24284
|
+
function phpVendorBin(_cwd, name) {
|
|
24285
|
+
const fileName = process.platform === "win32" ? `${name}.bat` : name;
|
|
24286
|
+
return path50.join("vendor", "bin", fileName);
|
|
24287
|
+
}
|
|
24288
|
+
function phpVendorBinExists(cwd, name) {
|
|
24289
|
+
const local = path50.join(cwd, "vendor", "bin", name);
|
|
24290
|
+
const localWin = path50.join(cwd, "vendor", "bin", `${name}.bat`);
|
|
24291
|
+
return fs18.existsSync(local) || fs18.existsSync(localWin);
|
|
24152
24292
|
}
|
|
24153
24293
|
function detectCheckstyle(cwd) {
|
|
24154
|
-
const hasMaven = fs18.existsSync(
|
|
24155
|
-
const
|
|
24156
|
-
const
|
|
24157
|
-
|
|
24294
|
+
const hasMaven = fs18.existsSync(path50.join(cwd, "pom.xml"));
|
|
24295
|
+
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path50.join(cwd, file)).filter((file) => fs18.existsSync(file));
|
|
24296
|
+
const hasGradleCheckstyleSignal = fs18.existsSync(path50.join(cwd, "checkstyle.xml")) || fs18.existsSync(path50.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
|
|
24297
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs18.existsSync(path50.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
24298
|
+
return (hasMaven || hasGradleCheckstyleSignal) && hasBinary;
|
|
24299
|
+
}
|
|
24300
|
+
function hasRootKotlinFile(cwd) {
|
|
24301
|
+
try {
|
|
24302
|
+
return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
24303
|
+
} catch {
|
|
24304
|
+
return false;
|
|
24305
|
+
}
|
|
24306
|
+
}
|
|
24307
|
+
function buildGradleHasKotlinSignal(cwd) {
|
|
24308
|
+
const content = readTextFileSafe(path50.join(cwd, "build.gradle"));
|
|
24309
|
+
return /\b(kotlin|org\.jetbrains\.kotlin|ktlint)\b/i.test(content);
|
|
24158
24310
|
}
|
|
24159
24311
|
function detectKtlint(cwd) {
|
|
24160
|
-
const hasKotlin = fs18.existsSync(
|
|
24161
|
-
try {
|
|
24162
|
-
return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
24163
|
-
} catch {
|
|
24164
|
-
return false;
|
|
24165
|
-
}
|
|
24166
|
-
})();
|
|
24312
|
+
const hasKotlin = fs18.existsSync(path50.join(cwd, "build.gradle.kts")) || fs18.existsSync(path50.join(cwd, "build.gradle")) && buildGradleHasKotlinSignal(cwd) || hasRootKotlinFile(cwd);
|
|
24167
24313
|
return hasKotlin && isCommandAvailable("ktlint");
|
|
24168
24314
|
}
|
|
24315
|
+
function detectPhpLinter(cwd) {
|
|
24316
|
+
if ((fs18.existsSync(path50.join(cwd, "phpstan.neon")) || fs18.existsSync(path50.join(cwd, "phpstan.neon.dist"))) && phpVendorBinExists(cwd, "phpstan")) {
|
|
24317
|
+
return "phpstan";
|
|
24318
|
+
}
|
|
24319
|
+
if (fs18.existsSync(path50.join(cwd, "pint.json")) && phpVendorBinExists(cwd, "pint")) {
|
|
24320
|
+
return "pint";
|
|
24321
|
+
}
|
|
24322
|
+
if (fs18.existsSync(path50.join(cwd, ".php-cs-fixer.php")) && phpVendorBinExists(cwd, "php-cs-fixer")) {
|
|
24323
|
+
return "php-cs-fixer";
|
|
24324
|
+
}
|
|
24325
|
+
if (fs18.existsSync(path50.join(cwd, "phpcs.xml")) && phpVendorBinExists(cwd, "phpcs")) {
|
|
24326
|
+
return "phpcs";
|
|
24327
|
+
}
|
|
24328
|
+
return null;
|
|
24329
|
+
}
|
|
24169
24330
|
function detectDotnetFormat(cwd) {
|
|
24170
24331
|
try {
|
|
24171
24332
|
const files = fs18.readdirSync(cwd);
|
|
@@ -24176,11 +24337,11 @@ function detectDotnetFormat(cwd) {
|
|
|
24176
24337
|
}
|
|
24177
24338
|
}
|
|
24178
24339
|
function detectCppcheck(cwd) {
|
|
24179
|
-
if (fs18.existsSync(
|
|
24340
|
+
if (fs18.existsSync(path50.join(cwd, "CMakeLists.txt"))) {
|
|
24180
24341
|
return isCommandAvailable("cppcheck");
|
|
24181
24342
|
}
|
|
24182
24343
|
try {
|
|
24183
|
-
const dirsToCheck = [cwd,
|
|
24344
|
+
const dirsToCheck = [cwd, path50.join(cwd, "src")];
|
|
24184
24345
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
24185
24346
|
try {
|
|
24186
24347
|
return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -24194,13 +24355,13 @@ function detectCppcheck(cwd) {
|
|
|
24194
24355
|
}
|
|
24195
24356
|
}
|
|
24196
24357
|
function detectSwiftlint(cwd) {
|
|
24197
|
-
return fs18.existsSync(
|
|
24358
|
+
return fs18.existsSync(path50.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
24198
24359
|
}
|
|
24199
24360
|
function detectDartAnalyze(cwd) {
|
|
24200
|
-
return fs18.existsSync(
|
|
24361
|
+
return fs18.existsSync(path50.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
24201
24362
|
}
|
|
24202
24363
|
function detectRubocop(cwd) {
|
|
24203
|
-
return (fs18.existsSync(
|
|
24364
|
+
return (fs18.existsSync(path50.join(cwd, "Gemfile")) || fs18.existsSync(path50.join(cwd, "gems.rb")) || fs18.existsSync(path50.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
24204
24365
|
}
|
|
24205
24366
|
function detectAdditionalLinter(cwd) {
|
|
24206
24367
|
if (detectRuff(cwd))
|
|
@@ -24209,10 +24370,13 @@ function detectAdditionalLinter(cwd) {
|
|
|
24209
24370
|
return "clippy";
|
|
24210
24371
|
if (detectGolangciLint(cwd))
|
|
24211
24372
|
return "golangci-lint";
|
|
24212
|
-
|
|
24213
|
-
|
|
24373
|
+
const phpLinter = detectPhpLinter(cwd);
|
|
24374
|
+
if (phpLinter)
|
|
24375
|
+
return phpLinter;
|
|
24214
24376
|
if (detectKtlint(cwd))
|
|
24215
24377
|
return "ktlint";
|
|
24378
|
+
if (detectCheckstyle(cwd))
|
|
24379
|
+
return "checkstyle";
|
|
24216
24380
|
if (detectDotnetFormat(cwd))
|
|
24217
24381
|
return "dotnet-format";
|
|
24218
24382
|
if (detectCppcheck(cwd))
|
|
@@ -24228,10 +24392,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
24228
24392
|
function findBinInAncestors(startDir, binName) {
|
|
24229
24393
|
let dir = startDir;
|
|
24230
24394
|
while (true) {
|
|
24231
|
-
const candidate =
|
|
24395
|
+
const candidate = path50.join(dir, "node_modules", ".bin", binName);
|
|
24232
24396
|
if (fs18.existsSync(candidate))
|
|
24233
24397
|
return candidate;
|
|
24234
|
-
const parent =
|
|
24398
|
+
const parent = path50.dirname(dir);
|
|
24235
24399
|
if (parent === dir)
|
|
24236
24400
|
break;
|
|
24237
24401
|
dir = parent;
|
|
@@ -24240,10 +24404,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
24240
24404
|
}
|
|
24241
24405
|
function findBinInEnvPath(binName) {
|
|
24242
24406
|
const searchPath = process.env.PATH ?? "";
|
|
24243
|
-
for (const dir of searchPath.split(
|
|
24407
|
+
for (const dir of searchPath.split(path50.delimiter)) {
|
|
24244
24408
|
if (!dir)
|
|
24245
24409
|
continue;
|
|
24246
|
-
const candidate =
|
|
24410
|
+
const candidate = path50.join(dir, binName);
|
|
24247
24411
|
if (fs18.existsSync(candidate))
|
|
24248
24412
|
return candidate;
|
|
24249
24413
|
}
|
|
@@ -24256,13 +24420,13 @@ async function detectAvailableLinter(directory) {
|
|
|
24256
24420
|
return null;
|
|
24257
24421
|
const projectDir = directory;
|
|
24258
24422
|
const isWindows = process.platform === "win32";
|
|
24259
|
-
const biomeBin = isWindows ?
|
|
24260
|
-
const eslintBin = isWindows ?
|
|
24423
|
+
const biomeBin = isWindows ? path50.join(projectDir, "node_modules", ".bin", "biome.EXE") : path50.join(projectDir, "node_modules", ".bin", "biome");
|
|
24424
|
+
const eslintBin = isWindows ? path50.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path50.join(projectDir, "node_modules", ".bin", "eslint");
|
|
24261
24425
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
24262
24426
|
if (localResult)
|
|
24263
24427
|
return localResult;
|
|
24264
|
-
const biomeAncestor = findBinInAncestors(
|
|
24265
|
-
const eslintAncestor = findBinInAncestors(
|
|
24428
|
+
const biomeAncestor = findBinInAncestors(path50.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
24429
|
+
const eslintAncestor = findBinInAncestors(path50.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
24266
24430
|
if (biomeAncestor || eslintAncestor) {
|
|
24267
24431
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
24268
24432
|
}
|
|
@@ -24476,7 +24640,7 @@ var _internals40 = {
|
|
|
24476
24640
|
|
|
24477
24641
|
// src/tools/secretscan.ts
|
|
24478
24642
|
import * as fs19 from "fs";
|
|
24479
|
-
import * as
|
|
24643
|
+
import * as path51 from "path";
|
|
24480
24644
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
24481
24645
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
24482
24646
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -24703,7 +24867,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
24703
24867
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
24704
24868
|
}
|
|
24705
24869
|
function loadSecretScanIgnore(scanDir) {
|
|
24706
|
-
const ignorePath =
|
|
24870
|
+
const ignorePath = path51.join(scanDir, ".secretscanignore");
|
|
24707
24871
|
try {
|
|
24708
24872
|
if (!fs19.existsSync(ignorePath))
|
|
24709
24873
|
return [];
|
|
@@ -24726,7 +24890,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
24726
24890
|
if (exactNames.has(entry))
|
|
24727
24891
|
return true;
|
|
24728
24892
|
for (const pattern of globPatterns) {
|
|
24729
|
-
if (
|
|
24893
|
+
if (path51.matchesGlob(relPath, pattern))
|
|
24730
24894
|
return true;
|
|
24731
24895
|
}
|
|
24732
24896
|
return false;
|
|
@@ -24747,7 +24911,7 @@ function validateDirectoryInput(dir) {
|
|
|
24747
24911
|
return null;
|
|
24748
24912
|
}
|
|
24749
24913
|
function isBinaryFile(filePath, buffer) {
|
|
24750
|
-
const ext =
|
|
24914
|
+
const ext = path51.extname(filePath).toLowerCase();
|
|
24751
24915
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24752
24916
|
return true;
|
|
24753
24917
|
}
|
|
@@ -24884,9 +25048,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
24884
25048
|
return false;
|
|
24885
25049
|
}
|
|
24886
25050
|
function isPathWithinScope(realPath, scanDir) {
|
|
24887
|
-
const resolvedScanDir =
|
|
24888
|
-
const resolvedRealPath =
|
|
24889
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
25051
|
+
const resolvedScanDir = path51.resolve(scanDir);
|
|
25052
|
+
const resolvedRealPath = path51.resolve(realPath);
|
|
25053
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path51.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
24890
25054
|
}
|
|
24891
25055
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
24892
25056
|
skippedDirs: 0,
|
|
@@ -24912,8 +25076,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24912
25076
|
return a.localeCompare(b);
|
|
24913
25077
|
});
|
|
24914
25078
|
for (const entry of entries) {
|
|
24915
|
-
const fullPath =
|
|
24916
|
-
const relPath =
|
|
25079
|
+
const fullPath = path51.join(dir, entry);
|
|
25080
|
+
const relPath = path51.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
24917
25081
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
24918
25082
|
stats.skippedDirs++;
|
|
24919
25083
|
continue;
|
|
@@ -24948,7 +25112,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24948
25112
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
24949
25113
|
files.push(...subFiles);
|
|
24950
25114
|
} else if (lstat2.isFile()) {
|
|
24951
|
-
const ext =
|
|
25115
|
+
const ext = path51.extname(fullPath).toLowerCase();
|
|
24952
25116
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24953
25117
|
files.push(fullPath);
|
|
24954
25118
|
} else {
|
|
@@ -25014,7 +25178,7 @@ var secretscan = createSwarmTool({
|
|
|
25014
25178
|
}
|
|
25015
25179
|
}
|
|
25016
25180
|
try {
|
|
25017
|
-
const _scanDirRaw =
|
|
25181
|
+
const _scanDirRaw = path51.resolve(directory);
|
|
25018
25182
|
const scanDir = (() => {
|
|
25019
25183
|
try {
|
|
25020
25184
|
return fs19.realpathSync(_scanDirRaw);
|
|
@@ -25170,18 +25334,77 @@ async function runSecretscan(directory) {
|
|
|
25170
25334
|
return errorResult;
|
|
25171
25335
|
}
|
|
25172
25336
|
}
|
|
25337
|
+
async function runSecretscanOnFiles(files, directory) {
|
|
25338
|
+
try {
|
|
25339
|
+
const findings = [];
|
|
25340
|
+
let filesScanned = 0;
|
|
25341
|
+
let skippedFiles = 0;
|
|
25342
|
+
for (const file of files) {
|
|
25343
|
+
if (typeof file !== "string") {
|
|
25344
|
+
skippedFiles++;
|
|
25345
|
+
continue;
|
|
25346
|
+
}
|
|
25347
|
+
const resolvedPath = path51.isAbsolute(file) ? path51.resolve(file) : path51.resolve(directory, file);
|
|
25348
|
+
if (!isPathWithinScope(resolvedPath, directory)) {
|
|
25349
|
+
skippedFiles++;
|
|
25350
|
+
continue;
|
|
25351
|
+
}
|
|
25352
|
+
const ext = path51.extname(resolvedPath).toLowerCase();
|
|
25353
|
+
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
25354
|
+
skippedFiles++;
|
|
25355
|
+
continue;
|
|
25356
|
+
}
|
|
25357
|
+
if (!fs19.existsSync(resolvedPath)) {
|
|
25358
|
+
skippedFiles++;
|
|
25359
|
+
continue;
|
|
25360
|
+
}
|
|
25361
|
+
const fileFindings = scanFileForSecrets(resolvedPath);
|
|
25362
|
+
filesScanned++;
|
|
25363
|
+
findings.push(...fileFindings);
|
|
25364
|
+
if (findings.length >= MAX_FINDINGS) {
|
|
25365
|
+
findings.length = MAX_FINDINGS;
|
|
25366
|
+
break;
|
|
25367
|
+
}
|
|
25368
|
+
}
|
|
25369
|
+
findings.sort((a, b) => {
|
|
25370
|
+
if (a.path < b.path)
|
|
25371
|
+
return -1;
|
|
25372
|
+
if (a.path > b.path)
|
|
25373
|
+
return 1;
|
|
25374
|
+
return a.line - b.line;
|
|
25375
|
+
});
|
|
25376
|
+
return {
|
|
25377
|
+
scan_dir: directory,
|
|
25378
|
+
findings,
|
|
25379
|
+
count: findings.length,
|
|
25380
|
+
files_scanned: filesScanned,
|
|
25381
|
+
skipped_files: skippedFiles
|
|
25382
|
+
};
|
|
25383
|
+
} catch (e) {
|
|
25384
|
+
return {
|
|
25385
|
+
error: e instanceof Error ? `scan failed: ${e.message}` : "scan failed: unknown error",
|
|
25386
|
+
scan_dir: directory,
|
|
25387
|
+
findings: [],
|
|
25388
|
+
count: 0,
|
|
25389
|
+
files_scanned: 0,
|
|
25390
|
+
skipped_files: 0
|
|
25391
|
+
};
|
|
25392
|
+
}
|
|
25393
|
+
}
|
|
25173
25394
|
var _internals41 = {
|
|
25174
25395
|
secretscan,
|
|
25175
|
-
runSecretscan
|
|
25396
|
+
runSecretscan,
|
|
25397
|
+
runSecretscanOnFiles,
|
|
25398
|
+
SECRET_PATTERNS: SECRET_PATTERNS2
|
|
25176
25399
|
};
|
|
25177
25400
|
|
|
25178
25401
|
// src/tools/test-runner.ts
|
|
25179
25402
|
import * as fs23 from "fs";
|
|
25180
|
-
import * as
|
|
25403
|
+
import * as path55 from "path";
|
|
25181
25404
|
|
|
25182
25405
|
// src/test-impact/analyzer.ts
|
|
25183
25406
|
import fs20 from "fs";
|
|
25184
|
-
import
|
|
25407
|
+
import path52 from "path";
|
|
25185
25408
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
25186
25409
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
25187
25410
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -25222,8 +25445,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
25222
25445
|
if (!importPath.startsWith(".")) {
|
|
25223
25446
|
return null;
|
|
25224
25447
|
}
|
|
25225
|
-
const resolved =
|
|
25226
|
-
if (
|
|
25448
|
+
const resolved = path52.resolve(fromDir, importPath);
|
|
25449
|
+
if (path52.extname(resolved)) {
|
|
25227
25450
|
if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
|
|
25228
25451
|
return normalizePath2(resolved);
|
|
25229
25452
|
}
|
|
@@ -25243,20 +25466,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25243
25466
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
25244
25467
|
let baseDir = fromDir;
|
|
25245
25468
|
for (let i = 1;i < leadingDots; i++) {
|
|
25246
|
-
baseDir =
|
|
25469
|
+
baseDir = path52.dirname(baseDir);
|
|
25247
25470
|
}
|
|
25248
25471
|
const rest = module.slice(leadingDots);
|
|
25249
25472
|
if (rest.length === 0) {
|
|
25250
|
-
const initPath =
|
|
25473
|
+
const initPath = path52.join(baseDir, "__init__.py");
|
|
25251
25474
|
if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
|
|
25252
25475
|
return normalizePath2(initPath);
|
|
25253
25476
|
}
|
|
25254
25477
|
return null;
|
|
25255
25478
|
}
|
|
25256
|
-
const subpath = rest.replace(/\./g,
|
|
25479
|
+
const subpath = rest.replace(/\./g, path52.sep);
|
|
25257
25480
|
const candidates = [
|
|
25258
|
-
`${
|
|
25259
|
-
|
|
25481
|
+
`${path52.join(baseDir, subpath)}.py`,
|
|
25482
|
+
path52.join(baseDir, subpath, "__init__.py")
|
|
25260
25483
|
];
|
|
25261
25484
|
for (const c of candidates) {
|
|
25262
25485
|
if (fs20.existsSync(c) && fs20.statSync(c).isFile())
|
|
@@ -25266,7 +25489,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25266
25489
|
}
|
|
25267
25490
|
var goModuleCache = new Map;
|
|
25268
25491
|
function findGoModule(fromDir) {
|
|
25269
|
-
const resolved =
|
|
25492
|
+
const resolved = path52.resolve(fromDir);
|
|
25270
25493
|
let cur = resolved;
|
|
25271
25494
|
const walked = [];
|
|
25272
25495
|
for (let i = 0;i < 16; i++) {
|
|
@@ -25278,7 +25501,7 @@ function findGoModule(fromDir) {
|
|
|
25278
25501
|
}
|
|
25279
25502
|
walked.push(cur);
|
|
25280
25503
|
try {
|
|
25281
|
-
const goMod =
|
|
25504
|
+
const goMod = path52.join(cur, "go.mod");
|
|
25282
25505
|
const content = fs20.readFileSync(goMod, "utf-8");
|
|
25283
25506
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
25284
25507
|
if (moduleMatch) {
|
|
@@ -25289,10 +25512,10 @@ function findGoModule(fromDir) {
|
|
|
25289
25512
|
}
|
|
25290
25513
|
} catch {}
|
|
25291
25514
|
try {
|
|
25292
|
-
fs20.accessSync(
|
|
25515
|
+
fs20.accessSync(path52.join(cur, ".git"));
|
|
25293
25516
|
break;
|
|
25294
25517
|
} catch {}
|
|
25295
|
-
const parent =
|
|
25518
|
+
const parent = path52.dirname(cur);
|
|
25296
25519
|
if (parent === cur)
|
|
25297
25520
|
break;
|
|
25298
25521
|
cur = parent;
|
|
@@ -25304,12 +25527,12 @@ function findGoModule(fromDir) {
|
|
|
25304
25527
|
function resolveGoImport(fromDir, importPath) {
|
|
25305
25528
|
let dir = null;
|
|
25306
25529
|
if (importPath.startsWith(".")) {
|
|
25307
|
-
dir =
|
|
25530
|
+
dir = path52.resolve(fromDir, importPath);
|
|
25308
25531
|
} else {
|
|
25309
25532
|
const mod = findGoModule(fromDir);
|
|
25310
25533
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
25311
25534
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
25312
|
-
dir =
|
|
25535
|
+
dir = path52.join(mod.moduleRoot, subpath);
|
|
25313
25536
|
}
|
|
25314
25537
|
}
|
|
25315
25538
|
if (dir === null)
|
|
@@ -25317,7 +25540,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
25317
25540
|
if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
|
|
25318
25541
|
return [];
|
|
25319
25542
|
try {
|
|
25320
|
-
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(
|
|
25543
|
+
return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path52.join(dir, f)));
|
|
25321
25544
|
} catch {
|
|
25322
25545
|
return [];
|
|
25323
25546
|
}
|
|
@@ -25356,15 +25579,15 @@ function findTestFilesSync(cwd) {
|
|
|
25356
25579
|
for (const entry of entries) {
|
|
25357
25580
|
if (entry.isDirectory()) {
|
|
25358
25581
|
if (!skipDirs.has(entry.name)) {
|
|
25359
|
-
walk(
|
|
25582
|
+
walk(path52.join(dir, entry.name), visitedInodes);
|
|
25360
25583
|
}
|
|
25361
25584
|
} else if (entry.isFile()) {
|
|
25362
25585
|
const name = entry.name;
|
|
25363
25586
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
25364
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
25587
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path52.sep}tests${path52.sep}`) && name.endsWith(".py");
|
|
25365
25588
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
25366
25589
|
if (isTsTest || isPyTest || isGoTest) {
|
|
25367
|
-
testFiles.push(normalizePath2(
|
|
25590
|
+
testFiles.push(normalizePath2(path52.join(dir, entry.name)));
|
|
25368
25591
|
}
|
|
25369
25592
|
}
|
|
25370
25593
|
}
|
|
@@ -25389,8 +25612,8 @@ function extractImports(content) {
|
|
|
25389
25612
|
];
|
|
25390
25613
|
}
|
|
25391
25614
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
25392
|
-
const ext =
|
|
25393
|
-
const testDir =
|
|
25615
|
+
const ext = path52.extname(testFile).toLowerCase();
|
|
25616
|
+
const testDir = path52.dirname(testFile);
|
|
25394
25617
|
function addEdge(source) {
|
|
25395
25618
|
if (!impactMap[source])
|
|
25396
25619
|
impactMap[source] = [];
|
|
@@ -25427,6 +25650,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
|
25427
25650
|
}
|
|
25428
25651
|
}
|
|
25429
25652
|
async function buildImpactMapInternal(cwd) {
|
|
25653
|
+
_clearGoModuleCache();
|
|
25430
25654
|
const testFiles = findTestFilesSync(cwd);
|
|
25431
25655
|
const impactMap = {};
|
|
25432
25656
|
for (const testFile of testFiles) {
|
|
@@ -25463,7 +25687,7 @@ async function buildImpactMap(cwd) {
|
|
|
25463
25687
|
return impactMap;
|
|
25464
25688
|
}
|
|
25465
25689
|
async function loadImpactMap(cwd, options) {
|
|
25466
|
-
const cachePath =
|
|
25690
|
+
const cachePath = path52.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
25467
25691
|
if (fs20.existsSync(cachePath)) {
|
|
25468
25692
|
try {
|
|
25469
25693
|
const content = fs20.readFileSync(cachePath, "utf-8");
|
|
@@ -25496,12 +25720,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
25496
25720
|
return _internals42.buildImpactMap(cwd);
|
|
25497
25721
|
}
|
|
25498
25722
|
async function saveImpactMap(cwd, impactMap) {
|
|
25499
|
-
if (!
|
|
25723
|
+
if (!path52.isAbsolute(cwd)) {
|
|
25500
25724
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
25501
25725
|
}
|
|
25502
25726
|
_internals42.validateProjectRoot(cwd);
|
|
25503
|
-
const cacheDir2 =
|
|
25504
|
-
const cachePath =
|
|
25727
|
+
const cacheDir2 = path52.join(cwd, ".swarm", "cache");
|
|
25728
|
+
const cachePath = path52.join(cacheDir2, "impact-map.json");
|
|
25505
25729
|
if (!fs20.existsSync(cacheDir2)) {
|
|
25506
25730
|
fs20.mkdirSync(cacheDir2, { recursive: true });
|
|
25507
25731
|
}
|
|
@@ -25533,7 +25757,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25533
25757
|
budgetExceeded = true;
|
|
25534
25758
|
break;
|
|
25535
25759
|
}
|
|
25536
|
-
const normalizedChanged = normalizePath2(
|
|
25760
|
+
const normalizedChanged = normalizePath2(path52.resolve(changedFile));
|
|
25537
25761
|
const tests = impactMap[normalizedChanged];
|
|
25538
25762
|
if (tests && tests.length > 0) {
|
|
25539
25763
|
for (const test of tests) {
|
|
@@ -25547,13 +25771,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25547
25771
|
if (budgetExceeded)
|
|
25548
25772
|
break;
|
|
25549
25773
|
} else {
|
|
25550
|
-
const changedDir = normalizePath2(
|
|
25551
|
-
const changedInputDir = normalizePath2(
|
|
25774
|
+
const changedDir = normalizePath2(path52.dirname(normalizedChanged));
|
|
25775
|
+
const changedInputDir = normalizePath2(path52.dirname(changedFile));
|
|
25552
25776
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
25553
25777
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
25554
25778
|
}).sort(([sourceA], [sourceB]) => {
|
|
25555
|
-
const sourceDirA = normalizePath2(
|
|
25556
|
-
const sourceDirB = normalizePath2(
|
|
25779
|
+
const sourceDirA = normalizePath2(path52.dirname(sourceA));
|
|
25780
|
+
const sourceDirB = normalizePath2(path52.dirname(sourceB));
|
|
25557
25781
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
25558
25782
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
25559
25783
|
if (exactA !== exactB)
|
|
@@ -25880,7 +26104,7 @@ function detectFlakyTests(allHistory) {
|
|
|
25880
26104
|
|
|
25881
26105
|
// src/test-impact/history-store.ts
|
|
25882
26106
|
import fs21 from "fs";
|
|
25883
|
-
import
|
|
26107
|
+
import path53 from "path";
|
|
25884
26108
|
var MAX_HISTORY_PER_TEST = 20;
|
|
25885
26109
|
var MAX_ERROR_LENGTH = 500;
|
|
25886
26110
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -25892,10 +26116,10 @@ function getHistoryPath(workingDir) {
|
|
|
25892
26116
|
if (!workingDir) {
|
|
25893
26117
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
25894
26118
|
}
|
|
25895
|
-
if (!
|
|
26119
|
+
if (!path53.isAbsolute(workingDir)) {
|
|
25896
26120
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
25897
26121
|
}
|
|
25898
|
-
return
|
|
26122
|
+
return path53.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
25899
26123
|
}
|
|
25900
26124
|
function sanitizeErrorMessage(errorMessage) {
|
|
25901
26125
|
if (errorMessage === undefined) {
|
|
@@ -25987,7 +26211,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
25987
26211
|
}
|
|
25988
26212
|
}
|
|
25989
26213
|
const historyPath = getHistoryPath(workingDir);
|
|
25990
|
-
const historyDir =
|
|
26214
|
+
const historyDir = path53.dirname(historyPath);
|
|
25991
26215
|
_internals43.validateProjectRoot(workingDir);
|
|
25992
26216
|
if (!fs21.existsSync(historyDir)) {
|
|
25993
26217
|
fs21.mkdirSync(historyDir, { recursive: true });
|
|
@@ -26117,7 +26341,7 @@ var _internals43 = {
|
|
|
26117
26341
|
|
|
26118
26342
|
// src/tools/resolve-working-directory.ts
|
|
26119
26343
|
import * as fs22 from "fs";
|
|
26120
|
-
import * as
|
|
26344
|
+
import * as path54 from "path";
|
|
26121
26345
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
26122
26346
|
if (workingDirectory == null || workingDirectory === "") {
|
|
26123
26347
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -26140,14 +26364,12 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26140
26364
|
message: "Invalid working_directory: null bytes are not allowed"
|
|
26141
26365
|
};
|
|
26142
26366
|
}
|
|
26143
|
-
|
|
26144
|
-
|
|
26145
|
-
|
|
26146
|
-
|
|
26147
|
-
|
|
26148
|
-
|
|
26149
|
-
};
|
|
26150
|
-
}
|
|
26367
|
+
const reservedDevicePattern = /^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i;
|
|
26368
|
+
if (workingDirectory.startsWith("\\\\") || process.platform === "win32" && reservedDevicePattern.test(workingDirectory)) {
|
|
26369
|
+
return {
|
|
26370
|
+
success: false,
|
|
26371
|
+
message: "Invalid working_directory: Windows device paths are not allowed"
|
|
26372
|
+
};
|
|
26151
26373
|
}
|
|
26152
26374
|
const rawPathParts = workingDirectory.split(/[\\/]/);
|
|
26153
26375
|
if (rawPathParts.includes("..")) {
|
|
@@ -26156,8 +26378,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26156
26378
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
26157
26379
|
};
|
|
26158
26380
|
}
|
|
26159
|
-
const normalizedDir =
|
|
26160
|
-
const resolvedDir =
|
|
26381
|
+
const normalizedDir = path54.normalize(workingDirectory);
|
|
26382
|
+
const resolvedDir = path54.resolve(normalizedDir);
|
|
26161
26383
|
let statResult;
|
|
26162
26384
|
try {
|
|
26163
26385
|
statResult = fs22.statSync(resolvedDir);
|
|
@@ -26176,7 +26398,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26176
26398
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
26177
26399
|
return { success: true, directory: resolvedDir };
|
|
26178
26400
|
}
|
|
26179
|
-
const resolvedFallback =
|
|
26401
|
+
const resolvedFallback = path54.resolve(fallbackDirectory);
|
|
26180
26402
|
let fallbackExists = false;
|
|
26181
26403
|
try {
|
|
26182
26404
|
fs22.statSync(resolvedFallback);
|
|
@@ -26185,7 +26407,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26185
26407
|
fallbackExists = false;
|
|
26186
26408
|
}
|
|
26187
26409
|
if (fallbackExists) {
|
|
26188
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
26410
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path54.sep);
|
|
26189
26411
|
if (isSubdirectory) {
|
|
26190
26412
|
return {
|
|
26191
26413
|
success: false,
|
|
@@ -26208,7 +26430,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
26208
26430
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
26209
26431
|
const uniqueTestFiles = new Set;
|
|
26210
26432
|
for (const sourceFile of sourceFiles) {
|
|
26211
|
-
const resolvedPath =
|
|
26433
|
+
const resolvedPath = path55.resolve(cwd, sourceFile);
|
|
26212
26434
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
26213
26435
|
const testFiles = impactMap[normalizedPath];
|
|
26214
26436
|
if (testFiles) {
|
|
@@ -26293,14 +26515,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
26293
26515
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
26294
26516
|
}
|
|
26295
26517
|
function detectGoTest(cwd) {
|
|
26296
|
-
return fs23.existsSync(
|
|
26518
|
+
return fs23.existsSync(path55.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
26297
26519
|
}
|
|
26298
26520
|
function detectJavaMaven(cwd) {
|
|
26299
|
-
return fs23.existsSync(
|
|
26521
|
+
return fs23.existsSync(path55.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
26300
26522
|
}
|
|
26301
26523
|
function detectGradle(cwd) {
|
|
26302
|
-
const hasBuildFile = fs23.existsSync(
|
|
26303
|
-
const hasGradlew = fs23.existsSync(
|
|
26524
|
+
const hasBuildFile = fs23.existsSync(path55.join(cwd, "build.gradle")) || fs23.existsSync(path55.join(cwd, "build.gradle.kts"));
|
|
26525
|
+
const hasGradlew = fs23.existsSync(path55.join(cwd, "gradlew")) || fs23.existsSync(path55.join(cwd, "gradlew.bat"));
|
|
26304
26526
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
26305
26527
|
}
|
|
26306
26528
|
function detectDotnetTest(cwd) {
|
|
@@ -26313,25 +26535,25 @@ function detectDotnetTest(cwd) {
|
|
|
26313
26535
|
}
|
|
26314
26536
|
}
|
|
26315
26537
|
function detectCTest(cwd) {
|
|
26316
|
-
const hasSource = fs23.existsSync(
|
|
26317
|
-
const hasBuildCache = fs23.existsSync(
|
|
26538
|
+
const hasSource = fs23.existsSync(path55.join(cwd, "CMakeLists.txt"));
|
|
26539
|
+
const hasBuildCache = fs23.existsSync(path55.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path55.join(cwd, "build", "CMakeCache.txt"));
|
|
26318
26540
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
26319
26541
|
}
|
|
26320
26542
|
function detectSwiftTest(cwd) {
|
|
26321
|
-
return fs23.existsSync(
|
|
26543
|
+
return fs23.existsSync(path55.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
26322
26544
|
}
|
|
26323
26545
|
function detectDartTest(cwd) {
|
|
26324
|
-
return fs23.existsSync(
|
|
26546
|
+
return fs23.existsSync(path55.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
26325
26547
|
}
|
|
26326
26548
|
function detectRSpec(cwd) {
|
|
26327
|
-
const hasRSpecFile = fs23.existsSync(
|
|
26328
|
-
const hasGemfile = fs23.existsSync(
|
|
26329
|
-
const hasSpecDir = fs23.existsSync(
|
|
26549
|
+
const hasRSpecFile = fs23.existsSync(path55.join(cwd, ".rspec"));
|
|
26550
|
+
const hasGemfile = fs23.existsSync(path55.join(cwd, "Gemfile"));
|
|
26551
|
+
const hasSpecDir = fs23.existsSync(path55.join(cwd, "spec"));
|
|
26330
26552
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
26331
26553
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
26332
26554
|
}
|
|
26333
26555
|
function detectMinitest(cwd) {
|
|
26334
|
-
return fs23.existsSync(
|
|
26556
|
+
return fs23.existsSync(path55.join(cwd, "test")) && (fs23.existsSync(path55.join(cwd, "Gemfile")) || fs23.existsSync(path55.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
26335
26557
|
}
|
|
26336
26558
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
26337
26559
|
bun: "bun",
|
|
@@ -26350,14 +26572,19 @@ var DISPATCH_FRAMEWORK_MAP = {
|
|
|
26350
26572
|
"dart-test": "dart-test",
|
|
26351
26573
|
rspec: "rspec",
|
|
26352
26574
|
minitest: "minitest",
|
|
26575
|
+
pest: "pest",
|
|
26576
|
+
phpunit: "phpunit",
|
|
26577
|
+
"php-artisan": "php-artisan",
|
|
26353
26578
|
"bun:test": "bun",
|
|
26354
26579
|
"xcodebuild-test": "swift-test",
|
|
26355
26580
|
"flutter test": "dart-test",
|
|
26356
|
-
"dart test": "dart-test"
|
|
26581
|
+
"dart test": "dart-test",
|
|
26582
|
+
Pest: "pest",
|
|
26583
|
+
PHPUnit: "phpunit"
|
|
26357
26584
|
};
|
|
26358
26585
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
26359
26586
|
try {
|
|
26360
|
-
const { pickBackend } = await import("./dispatch-
|
|
26587
|
+
const { pickBackend } = await import("./dispatch-anmxxhen.js");
|
|
26361
26588
|
const backend = await pickBackend(cwd);
|
|
26362
26589
|
if (!backend?.selectTestFramework)
|
|
26363
26590
|
return "none";
|
|
@@ -26373,7 +26600,7 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
|
|
|
26373
26600
|
if (framework === "none")
|
|
26374
26601
|
return null;
|
|
26375
26602
|
try {
|
|
26376
|
-
const { pickBackend } = await import("./dispatch-
|
|
26603
|
+
const { pickBackend } = await import("./dispatch-anmxxhen.js");
|
|
26377
26604
|
const backend = await pickBackend(baseDir);
|
|
26378
26605
|
if (backend?.buildTestCommand) {
|
|
26379
26606
|
const cmd = backend.buildTestCommand(framework, files, baseDir, {
|
|
@@ -26393,7 +26620,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
26393
26620
|
if (framework === "none")
|
|
26394
26621
|
return null;
|
|
26395
26622
|
try {
|
|
26396
|
-
const { pickBackend } = await import("./dispatch-
|
|
26623
|
+
const { pickBackend } = await import("./dispatch-anmxxhen.js");
|
|
26397
26624
|
const backend = await pickBackend(baseDir);
|
|
26398
26625
|
if (!backend?.parseTestOutput)
|
|
26399
26626
|
return null;
|
|
@@ -26416,7 +26643,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
26416
26643
|
async function detectTestFramework(cwd) {
|
|
26417
26644
|
const baseDir = cwd;
|
|
26418
26645
|
try {
|
|
26419
|
-
const packageJsonPath =
|
|
26646
|
+
const packageJsonPath = path55.join(baseDir, "package.json");
|
|
26420
26647
|
if (fs23.existsSync(packageJsonPath)) {
|
|
26421
26648
|
const content = fs23.readFileSync(packageJsonPath, "utf-8");
|
|
26422
26649
|
const pkg = JSON.parse(content);
|
|
@@ -26437,16 +26664,16 @@ async function detectTestFramework(cwd) {
|
|
|
26437
26664
|
return "jest";
|
|
26438
26665
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
26439
26666
|
return "mocha";
|
|
26440
|
-
if (fs23.existsSync(
|
|
26667
|
+
if (fs23.existsSync(path55.join(baseDir, "bun.lockb")) || fs23.existsSync(path55.join(baseDir, "bun.lock"))) {
|
|
26441
26668
|
if (scripts.test?.includes("bun"))
|
|
26442
26669
|
return "bun";
|
|
26443
26670
|
}
|
|
26444
26671
|
}
|
|
26445
26672
|
} catch {}
|
|
26446
26673
|
try {
|
|
26447
|
-
const pyprojectTomlPath =
|
|
26448
|
-
const setupCfgPath =
|
|
26449
|
-
const requirementsTxtPath =
|
|
26674
|
+
const pyprojectTomlPath = path55.join(baseDir, "pyproject.toml");
|
|
26675
|
+
const setupCfgPath = path55.join(baseDir, "setup.cfg");
|
|
26676
|
+
const requirementsTxtPath = path55.join(baseDir, "requirements.txt");
|
|
26450
26677
|
if (fs23.existsSync(pyprojectTomlPath)) {
|
|
26451
26678
|
const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
|
|
26452
26679
|
if (content.includes("[tool.pytest"))
|
|
@@ -26466,7 +26693,7 @@ async function detectTestFramework(cwd) {
|
|
|
26466
26693
|
}
|
|
26467
26694
|
} catch {}
|
|
26468
26695
|
try {
|
|
26469
|
-
const cargoTomlPath =
|
|
26696
|
+
const cargoTomlPath = path55.join(baseDir, "Cargo.toml");
|
|
26470
26697
|
if (fs23.existsSync(cargoTomlPath)) {
|
|
26471
26698
|
const content = fs23.readFileSync(cargoTomlPath, "utf-8");
|
|
26472
26699
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -26477,13 +26704,16 @@ async function detectTestFramework(cwd) {
|
|
|
26477
26704
|
}
|
|
26478
26705
|
} catch {}
|
|
26479
26706
|
try {
|
|
26480
|
-
const pesterConfigPath =
|
|
26481
|
-
const pesterConfigJsonPath =
|
|
26482
|
-
const pesterPs1Path =
|
|
26707
|
+
const pesterConfigPath = path55.join(baseDir, "pester.config.ps1");
|
|
26708
|
+
const pesterConfigJsonPath = path55.join(baseDir, "pester.config.ps1.json");
|
|
26709
|
+
const pesterPs1Path = path55.join(baseDir, "tests.ps1");
|
|
26483
26710
|
if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
|
|
26484
26711
|
return "pester";
|
|
26485
26712
|
}
|
|
26486
26713
|
} catch {}
|
|
26714
|
+
const phpFramework = detectPhpTest(baseDir);
|
|
26715
|
+
if (phpFramework)
|
|
26716
|
+
return phpFramework;
|
|
26487
26717
|
if (detectGoTest(baseDir))
|
|
26488
26718
|
return "go-test";
|
|
26489
26719
|
if (detectJavaMaven(baseDir))
|
|
@@ -26504,6 +26734,17 @@ async function detectTestFramework(cwd) {
|
|
|
26504
26734
|
return "minitest";
|
|
26505
26735
|
return "none";
|
|
26506
26736
|
}
|
|
26737
|
+
function detectPhpTest(cwd) {
|
|
26738
|
+
if (fs23.existsSync(path55.join(cwd, "artisan")) && fs23.existsSync(path55.join(cwd, "composer.json"))) {
|
|
26739
|
+
return "php-artisan";
|
|
26740
|
+
}
|
|
26741
|
+
if (fs23.existsSync(path55.join(cwd, "Pest.php")))
|
|
26742
|
+
return "pest";
|
|
26743
|
+
if (fs23.existsSync(path55.join(cwd, "phpunit.xml")) || fs23.existsSync(path55.join(cwd, "phpunit.xml.dist"))) {
|
|
26744
|
+
return "phpunit";
|
|
26745
|
+
}
|
|
26746
|
+
return null;
|
|
26747
|
+
}
|
|
26507
26748
|
var COMPOUND_TEST_EXTENSIONS = [
|
|
26508
26749
|
".test.ts",
|
|
26509
26750
|
".test.tsx",
|
|
@@ -26522,12 +26763,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
26522
26763
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
26523
26764
|
}
|
|
26524
26765
|
function resolveWorkspacePath(file, workingDir) {
|
|
26525
|
-
return
|
|
26766
|
+
return path55.isAbsolute(file) ? path55.resolve(file) : path55.resolve(workingDir, file);
|
|
26526
26767
|
}
|
|
26527
26768
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
26528
26769
|
if (!preferRelative)
|
|
26529
26770
|
return absolutePath;
|
|
26530
|
-
return
|
|
26771
|
+
return path55.relative(workingDir, absolutePath);
|
|
26531
26772
|
}
|
|
26532
26773
|
function dedupePush(target, value) {
|
|
26533
26774
|
if (!target.includes(value)) {
|
|
@@ -26557,6 +26798,12 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
26557
26798
|
`${nameWithoutExt}Tests.kt`,
|
|
26558
26799
|
`Test${nameWithoutExt}.kt`
|
|
26559
26800
|
];
|
|
26801
|
+
case ".php":
|
|
26802
|
+
return [
|
|
26803
|
+
`${nameWithoutExt}Test.php`,
|
|
26804
|
+
`${nameWithoutExt}Tests.php`,
|
|
26805
|
+
`Test${nameWithoutExt}.php`
|
|
26806
|
+
];
|
|
26560
26807
|
case ".ps1":
|
|
26561
26808
|
return [`${nameWithoutExt}.Tests.ps1`, `${nameWithoutExt}.tests.ps1`];
|
|
26562
26809
|
default:
|
|
@@ -26564,18 +26811,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
26564
26811
|
}
|
|
26565
26812
|
}
|
|
26566
26813
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
26567
|
-
const relativeDir =
|
|
26814
|
+
const relativeDir = path55.dirname(relativePath);
|
|
26568
26815
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
26569
26816
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
26570
|
-
const rootDir =
|
|
26571
|
-
return nestedRelativeDir ? [rootDir,
|
|
26817
|
+
const rootDir = path55.join(workingDir, dirName);
|
|
26818
|
+
return nestedRelativeDir ? [rootDir, path55.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
26572
26819
|
});
|
|
26573
26820
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
26574
26821
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
26575
|
-
directories.push(
|
|
26822
|
+
directories.push(path55.join(workingDir, "src/test/java", path55.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
26576
26823
|
}
|
|
26577
26824
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
26578
|
-
directories.push(
|
|
26825
|
+
directories.push(path55.join(workingDir, "src/test/kotlin", path55.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
26579
26826
|
}
|
|
26580
26827
|
return [...new Set(directories)];
|
|
26581
26828
|
}
|
|
@@ -26597,29 +26844,31 @@ function isLanguageSpecificTestFile(basename11) {
|
|
|
26597
26844
|
return true;
|
|
26598
26845
|
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename11) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
26599
26846
|
return true;
|
|
26847
|
+
if (lower.endsWith(".php") && (/^Test[A-Z]/.test(basename11) || basename11.endsWith("Test.php") || basename11.endsWith("Tests.php")))
|
|
26848
|
+
return true;
|
|
26600
26849
|
if (lower.endsWith(".tests.ps1"))
|
|
26601
26850
|
return true;
|
|
26602
26851
|
return false;
|
|
26603
26852
|
}
|
|
26604
26853
|
function isConventionTestFilePath(filePath) {
|
|
26605
26854
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26606
|
-
const basename11 =
|
|
26855
|
+
const basename11 = path55.basename(filePath);
|
|
26607
26856
|
return hasCompoundTestExtension(basename11) || basename11.includes(".spec.") || basename11.includes(".test.") || isLanguageSpecificTestFile(basename11) || isTestDirectoryPath(normalizedPath);
|
|
26608
26857
|
}
|
|
26609
26858
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
26610
26859
|
const testFiles = [];
|
|
26611
26860
|
for (const file of sourceFiles) {
|
|
26612
26861
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
26613
|
-
const relativeFile =
|
|
26614
|
-
const basename11 =
|
|
26615
|
-
const
|
|
26616
|
-
const preferRelativeOutput = !
|
|
26862
|
+
const relativeFile = path55.relative(workingDir, absoluteFile);
|
|
26863
|
+
const basename11 = path55.basename(absoluteFile);
|
|
26864
|
+
const dirname25 = path55.dirname(absoluteFile);
|
|
26865
|
+
const preferRelativeOutput = !path55.isAbsolute(file);
|
|
26617
26866
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
26618
26867
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
26619
26868
|
continue;
|
|
26620
26869
|
}
|
|
26621
26870
|
const nameWithoutExt = basename11.replace(/\.[^.]+$/, "");
|
|
26622
|
-
const ext =
|
|
26871
|
+
const ext = path55.extname(basename11);
|
|
26623
26872
|
const genericTestNames = [
|
|
26624
26873
|
`${nameWithoutExt}.spec${ext}`,
|
|
26625
26874
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -26628,7 +26877,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26628
26877
|
const colocatedCandidates = [
|
|
26629
26878
|
...genericTestNames,
|
|
26630
26879
|
...languageSpecificTestNames
|
|
26631
|
-
].map((candidateName) =>
|
|
26880
|
+
].map((candidateName) => path55.join(dirname25, candidateName));
|
|
26632
26881
|
const testDirectoryNames = [
|
|
26633
26882
|
basename11,
|
|
26634
26883
|
...genericTestNames,
|
|
@@ -26637,8 +26886,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26637
26886
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
26638
26887
|
const possibleTestFiles = [
|
|
26639
26888
|
...colocatedCandidates,
|
|
26640
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
26641
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
26889
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path55.join(dirname25, dirName, candidateName))),
|
|
26890
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path55.join(candidateDir, candidateName)))
|
|
26642
26891
|
];
|
|
26643
26892
|
for (const testFile of possibleTestFiles) {
|
|
26644
26893
|
if (fs23.existsSync(testFile)) {
|
|
@@ -26659,7 +26908,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26659
26908
|
try {
|
|
26660
26909
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
26661
26910
|
const content = fs23.readFileSync(absoluteTestFile, "utf-8");
|
|
26662
|
-
const testDir =
|
|
26911
|
+
const testDir = path55.dirname(absoluteTestFile);
|
|
26663
26912
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
26664
26913
|
let match;
|
|
26665
26914
|
match = importRegex.exec(content);
|
|
@@ -26667,8 +26916,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26667
26916
|
const importPath = match[1];
|
|
26668
26917
|
let resolvedImport;
|
|
26669
26918
|
if (importPath.startsWith(".")) {
|
|
26670
|
-
resolvedImport =
|
|
26671
|
-
const existingExt =
|
|
26919
|
+
resolvedImport = path55.resolve(testDir, importPath);
|
|
26920
|
+
const existingExt = path55.extname(resolvedImport);
|
|
26672
26921
|
if (!existingExt) {
|
|
26673
26922
|
for (const extToTry of [
|
|
26674
26923
|
".ts",
|
|
@@ -26688,12 +26937,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26688
26937
|
} else {
|
|
26689
26938
|
continue;
|
|
26690
26939
|
}
|
|
26691
|
-
const importBasename =
|
|
26692
|
-
const importDir =
|
|
26940
|
+
const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
|
|
26941
|
+
const importDir = path55.dirname(resolvedImport);
|
|
26693
26942
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26694
|
-
const sourceDir =
|
|
26695
|
-
const sourceBasename =
|
|
26696
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26943
|
+
const sourceDir = path55.dirname(sourceFile);
|
|
26944
|
+
const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
|
|
26945
|
+
const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
|
|
26697
26946
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26698
26947
|
dedupePush(testFiles, testFile);
|
|
26699
26948
|
break;
|
|
@@ -26706,8 +26955,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26706
26955
|
while (match !== null) {
|
|
26707
26956
|
const importPath = match[1];
|
|
26708
26957
|
if (importPath.startsWith(".")) {
|
|
26709
|
-
let resolvedImport =
|
|
26710
|
-
const existingExt =
|
|
26958
|
+
let resolvedImport = path55.resolve(testDir, importPath);
|
|
26959
|
+
const existingExt = path55.extname(resolvedImport);
|
|
26711
26960
|
if (!existingExt) {
|
|
26712
26961
|
for (const extToTry of [
|
|
26713
26962
|
".ts",
|
|
@@ -26724,12 +26973,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26724
26973
|
}
|
|
26725
26974
|
}
|
|
26726
26975
|
}
|
|
26727
|
-
const importDir =
|
|
26728
|
-
const importBasename =
|
|
26976
|
+
const importDir = path55.dirname(resolvedImport);
|
|
26977
|
+
const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
|
|
26729
26978
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26730
|
-
const sourceDir =
|
|
26731
|
-
const sourceBasename =
|
|
26732
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26979
|
+
const sourceDir = path55.dirname(sourceFile);
|
|
26980
|
+
const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
|
|
26981
|
+
const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
|
|
26733
26982
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26734
26983
|
dedupePush(testFiles, testFile);
|
|
26735
26984
|
break;
|
|
@@ -26849,8 +27098,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26849
27098
|
return ["mvn", "test"];
|
|
26850
27099
|
case "gradle": {
|
|
26851
27100
|
const isWindows = process.platform === "win32";
|
|
26852
|
-
const hasGradlewBat = fs23.existsSync(
|
|
26853
|
-
const hasGradlew = fs23.existsSync(
|
|
27101
|
+
const hasGradlewBat = fs23.existsSync(path55.join(baseDir, "gradlew.bat"));
|
|
27102
|
+
const hasGradlew = fs23.existsSync(path55.join(baseDir, "gradlew"));
|
|
26854
27103
|
if (hasGradlewBat && isWindows)
|
|
26855
27104
|
return ["gradlew.bat", "test"];
|
|
26856
27105
|
if (hasGradlew)
|
|
@@ -26867,7 +27116,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26867
27116
|
"cmake-build-release",
|
|
26868
27117
|
"out"
|
|
26869
27118
|
];
|
|
26870
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(
|
|
27119
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path55.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
26871
27120
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
26872
27121
|
}
|
|
26873
27122
|
case "swift-test":
|
|
@@ -26894,10 +27143,31 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26894
27143
|
"-e",
|
|
26895
27144
|
'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'
|
|
26896
27145
|
];
|
|
27146
|
+
case "pest": {
|
|
27147
|
+
const args = [phpVendorBin2("pest")];
|
|
27148
|
+
if (scope !== "all" && files.length > 0)
|
|
27149
|
+
args.push(...files);
|
|
27150
|
+
return args;
|
|
27151
|
+
}
|
|
27152
|
+
case "phpunit": {
|
|
27153
|
+
const args = [phpVendorBin2("phpunit")];
|
|
27154
|
+
if (scope !== "all" && files.length > 0)
|
|
27155
|
+
args.push(...files);
|
|
27156
|
+
return args;
|
|
27157
|
+
}
|
|
27158
|
+
case "php-artisan": {
|
|
27159
|
+
const args = ["php", "artisan", "test"];
|
|
27160
|
+
if (scope !== "all" && files.length > 0)
|
|
27161
|
+
args.push(...files);
|
|
27162
|
+
return args;
|
|
27163
|
+
}
|
|
26897
27164
|
default:
|
|
26898
27165
|
return null;
|
|
26899
27166
|
}
|
|
26900
27167
|
}
|
|
27168
|
+
function phpVendorBin2(name) {
|
|
27169
|
+
return path55.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
|
|
27170
|
+
}
|
|
26901
27171
|
function mapFrameworkStatusToResult(status) {
|
|
26902
27172
|
if (typeof status !== "string")
|
|
26903
27173
|
return null;
|
|
@@ -27221,6 +27491,24 @@ function parseTestOutput(framework, output) {
|
|
|
27221
27491
|
}
|
|
27222
27492
|
break;
|
|
27223
27493
|
}
|
|
27494
|
+
case "pest":
|
|
27495
|
+
case "phpunit":
|
|
27496
|
+
case "php-artisan": {
|
|
27497
|
+
const phpunitMatch = output.match(/Tests:\s*(\d+),\s*Assertions:\s*\d+(?:,\s*Failures:\s*(\d+))?(?:,\s*Errors:\s*(\d+))?(?:,\s*Skipped:\s*(\d+))?/);
|
|
27498
|
+
const okMatch = output.match(/OK\s*\((\d+)\s+tests?/);
|
|
27499
|
+
if (phpunitMatch) {
|
|
27500
|
+
totals.total = parseInt(phpunitMatch[1], 10);
|
|
27501
|
+
const failures = phpunitMatch[2] ? parseInt(phpunitMatch[2], 10) : 0;
|
|
27502
|
+
const errors = phpunitMatch[3] ? parseInt(phpunitMatch[3], 10) : 0;
|
|
27503
|
+
totals.skipped = phpunitMatch[4] ? parseInt(phpunitMatch[4], 10) : 0;
|
|
27504
|
+
totals.failed = failures + errors;
|
|
27505
|
+
totals.passed = totals.total - totals.failed - totals.skipped;
|
|
27506
|
+
} else if (okMatch) {
|
|
27507
|
+
totals.total = parseInt(okMatch[1], 10);
|
|
27508
|
+
totals.passed = totals.total;
|
|
27509
|
+
}
|
|
27510
|
+
break;
|
|
27511
|
+
}
|
|
27224
27512
|
default:
|
|
27225
27513
|
break;
|
|
27226
27514
|
}
|
|
@@ -27301,11 +27589,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27301
27589
|
};
|
|
27302
27590
|
}
|
|
27303
27591
|
const startTime = Date.now();
|
|
27304
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
27592
|
+
const vitestJsonOutputPath = framework === "vitest" ? path55.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
27305
27593
|
try {
|
|
27306
27594
|
if (vitestJsonOutputPath) {
|
|
27307
27595
|
try {
|
|
27308
|
-
fs23.mkdirSync(
|
|
27596
|
+
fs23.mkdirSync(path55.dirname(vitestJsonOutputPath), { recursive: true });
|
|
27309
27597
|
if (fs23.existsSync(vitestJsonOutputPath)) {
|
|
27310
27598
|
fs23.unlinkSync(vitestJsonOutputPath);
|
|
27311
27599
|
}
|
|
@@ -27441,6 +27729,7 @@ var SOURCE_EXTENSIONS = new Set([
|
|
|
27441
27729
|
".hpp",
|
|
27442
27730
|
".cc",
|
|
27443
27731
|
".cxx",
|
|
27732
|
+
".php",
|
|
27444
27733
|
".swift",
|
|
27445
27734
|
".dart",
|
|
27446
27735
|
".rb",
|
|
@@ -27473,10 +27762,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
27473
27762
|
]);
|
|
27474
27763
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
27475
27764
|
const normalized = testFile.replace(/\\/g, "/");
|
|
27476
|
-
if (!
|
|
27765
|
+
if (!path55.isAbsolute(testFile))
|
|
27477
27766
|
return normalized;
|
|
27478
|
-
const relative7 =
|
|
27479
|
-
if (relative7.startsWith("..") ||
|
|
27767
|
+
const relative7 = path55.relative(workingDir, testFile);
|
|
27768
|
+
if (relative7.startsWith("..") || path55.isAbsolute(relative7)) {
|
|
27480
27769
|
return normalized;
|
|
27481
27770
|
}
|
|
27482
27771
|
return relative7.replace(/\\/g, "/");
|
|
@@ -27715,7 +28004,7 @@ var test_runner = createSwarmTool({
|
|
|
27715
28004
|
const sourceFiles = args.files.filter((file) => {
|
|
27716
28005
|
if (directTestFiles.includes(file))
|
|
27717
28006
|
return false;
|
|
27718
|
-
const ext =
|
|
28007
|
+
const ext = path55.extname(file).toLowerCase();
|
|
27719
28008
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27720
28009
|
});
|
|
27721
28010
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -27761,7 +28050,7 @@ var test_runner = createSwarmTool({
|
|
|
27761
28050
|
if (isConventionTestFilePath(f)) {
|
|
27762
28051
|
return false;
|
|
27763
28052
|
}
|
|
27764
|
-
const ext =
|
|
28053
|
+
const ext = path55.extname(f).toLowerCase();
|
|
27765
28054
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27766
28055
|
});
|
|
27767
28056
|
if (sourceFiles.length === 0) {
|
|
@@ -27811,7 +28100,7 @@ var test_runner = createSwarmTool({
|
|
|
27811
28100
|
if (isConventionTestFilePath(f)) {
|
|
27812
28101
|
return false;
|
|
27813
28102
|
}
|
|
27814
|
-
const ext =
|
|
28103
|
+
const ext = path55.extname(f).toLowerCase();
|
|
27815
28104
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27816
28105
|
});
|
|
27817
28106
|
if (sourceFiles.length === 0) {
|
|
@@ -27863,8 +28152,8 @@ var test_runner = createSwarmTool({
|
|
|
27863
28152
|
}
|
|
27864
28153
|
if (impactResult.impactedTests.length > 0) {
|
|
27865
28154
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
27866
|
-
const relativePath =
|
|
27867
|
-
return
|
|
28155
|
+
const relativePath = path55.relative(workingDir, absPath);
|
|
28156
|
+
return path55.isAbsolute(relativePath) ? absPath : relativePath;
|
|
27868
28157
|
});
|
|
27869
28158
|
} else {
|
|
27870
28159
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -27959,8 +28248,8 @@ function validateDirectoryPath(dir) {
|
|
|
27959
28248
|
if (dir.includes("..")) {
|
|
27960
28249
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
27961
28250
|
}
|
|
27962
|
-
const normalized =
|
|
27963
|
-
const absolutePath =
|
|
28251
|
+
const normalized = path56.normalize(dir);
|
|
28252
|
+
const absolutePath = path56.isAbsolute(normalized) ? normalized : path56.resolve(normalized);
|
|
27964
28253
|
return absolutePath;
|
|
27965
28254
|
}
|
|
27966
28255
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -27983,7 +28272,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
27983
28272
|
}
|
|
27984
28273
|
function getPackageVersion(dir) {
|
|
27985
28274
|
try {
|
|
27986
|
-
const packagePath =
|
|
28275
|
+
const packagePath = path56.join(dir, "package.json");
|
|
27987
28276
|
if (fs24.existsSync(packagePath)) {
|
|
27988
28277
|
const content = fs24.readFileSync(packagePath, "utf-8");
|
|
27989
28278
|
const pkg = JSON.parse(content);
|
|
@@ -27994,7 +28283,7 @@ function getPackageVersion(dir) {
|
|
|
27994
28283
|
}
|
|
27995
28284
|
function getChangelogVersion(dir) {
|
|
27996
28285
|
try {
|
|
27997
|
-
const changelogPath =
|
|
28286
|
+
const changelogPath = path56.join(dir, "CHANGELOG.md");
|
|
27998
28287
|
if (fs24.existsSync(changelogPath)) {
|
|
27999
28288
|
const content = fs24.readFileSync(changelogPath, "utf-8");
|
|
28000
28289
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -28008,7 +28297,7 @@ function getChangelogVersion(dir) {
|
|
|
28008
28297
|
function getVersionFileVersion(dir) {
|
|
28009
28298
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
28010
28299
|
for (const file of possibleFiles) {
|
|
28011
|
-
const filePath =
|
|
28300
|
+
const filePath = path56.join(dir, file);
|
|
28012
28301
|
if (fs24.existsSync(filePath)) {
|
|
28013
28302
|
try {
|
|
28014
28303
|
const content = fs24.readFileSync(filePath, "utf-8").trim();
|
|
@@ -28746,7 +29035,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
28746
29035
|
|
|
28747
29036
|
// src/commands/reset.ts
|
|
28748
29037
|
import * as fs25 from "fs";
|
|
28749
|
-
import * as
|
|
29038
|
+
import * as path57 from "path";
|
|
28750
29039
|
|
|
28751
29040
|
// src/background/circuit-breaker.ts
|
|
28752
29041
|
class CircuitBreaker {
|
|
@@ -29465,7 +29754,7 @@ async function handleResetCommand(directory, args) {
|
|
|
29465
29754
|
}
|
|
29466
29755
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
29467
29756
|
try {
|
|
29468
|
-
const rootPath =
|
|
29757
|
+
const rootPath = path57.join(directory, filename);
|
|
29469
29758
|
if (fs25.existsSync(rootPath)) {
|
|
29470
29759
|
fs25.unlinkSync(rootPath);
|
|
29471
29760
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -29503,14 +29792,14 @@ async function handleResetCommand(directory, args) {
|
|
|
29503
29792
|
|
|
29504
29793
|
// src/commands/reset-session.ts
|
|
29505
29794
|
import * as fs28 from "fs";
|
|
29506
|
-
import * as
|
|
29795
|
+
import * as path60 from "path";
|
|
29507
29796
|
|
|
29508
29797
|
// src/prm/trajectory-store.ts
|
|
29509
29798
|
import * as fs26 from "fs/promises";
|
|
29510
|
-
import * as
|
|
29799
|
+
import * as path58 from "path";
|
|
29511
29800
|
var MAX_TRACKED_TRAJECTORY_SESSIONS = 500;
|
|
29512
29801
|
function getTrajectoryPath(sessionId, directory) {
|
|
29513
|
-
const relativePath =
|
|
29802
|
+
const relativePath = path58.join("trajectories", `${sessionId}.jsonl`);
|
|
29514
29803
|
return validateSwarmPath(directory, relativePath);
|
|
29515
29804
|
}
|
|
29516
29805
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -29569,7 +29858,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
29569
29858
|
for (const entry of entries) {
|
|
29570
29859
|
if (!entry.isFile())
|
|
29571
29860
|
continue;
|
|
29572
|
-
const filePath =
|
|
29861
|
+
const filePath = path58.join(dirPath, entry.name);
|
|
29573
29862
|
try {
|
|
29574
29863
|
const stat6 = await fs26.stat(filePath);
|
|
29575
29864
|
if (now - stat6.mtimeMs > cutoffMs) {
|
|
@@ -29996,16 +30285,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
29996
30285
|
}
|
|
29997
30286
|
// src/prm/replay.ts
|
|
29998
30287
|
import { promises as fs27 } from "fs";
|
|
29999
|
-
import
|
|
30288
|
+
import path59 from "path";
|
|
30000
30289
|
function isPathSafe(targetPath, basePath) {
|
|
30001
|
-
const resolvedTarget =
|
|
30002
|
-
const resolvedBase =
|
|
30003
|
-
const rel =
|
|
30004
|
-
return !rel.startsWith("..") && !
|
|
30290
|
+
const resolvedTarget = path59.resolve(targetPath);
|
|
30291
|
+
const resolvedBase = path59.resolve(basePath);
|
|
30292
|
+
const rel = path59.relative(resolvedBase, resolvedTarget);
|
|
30293
|
+
return !rel.startsWith("..") && !path59.isAbsolute(rel);
|
|
30005
30294
|
}
|
|
30006
30295
|
function isWithinReplaysDir(targetPath) {
|
|
30007
|
-
const resolved =
|
|
30008
|
-
const parts = resolved.split(
|
|
30296
|
+
const resolved = path59.resolve(targetPath);
|
|
30297
|
+
const parts = resolved.split(path59.sep);
|
|
30009
30298
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
30010
30299
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
30011
30300
|
return true;
|
|
@@ -30018,10 +30307,10 @@ function sanitizeFilename(input) {
|
|
|
30018
30307
|
}
|
|
30019
30308
|
async function startReplayRecording(sessionID, directory) {
|
|
30020
30309
|
try {
|
|
30021
|
-
const replayDir =
|
|
30310
|
+
const replayDir = path59.join(directory, ".swarm", "replays");
|
|
30022
30311
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
30023
30312
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
30024
|
-
const filepath =
|
|
30313
|
+
const filepath = path59.join(replayDir, filename);
|
|
30025
30314
|
if (!isPathSafe(filepath, replayDir)) {
|
|
30026
30315
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
30027
30316
|
return null;
|
|
@@ -30091,8 +30380,9 @@ function errorMessage(err) {
|
|
|
30091
30380
|
}
|
|
30092
30381
|
async function handleResetSessionCommand(directory, _args) {
|
|
30093
30382
|
const results = [];
|
|
30383
|
+
let statePath;
|
|
30094
30384
|
try {
|
|
30095
|
-
|
|
30385
|
+
statePath = validateSwarmPath(directory, "session/state.json");
|
|
30096
30386
|
if (fs28.existsSync(statePath)) {
|
|
30097
30387
|
fs28.unlinkSync(statePath);
|
|
30098
30388
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
@@ -30102,9 +30392,9 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30102
30392
|
} catch {
|
|
30103
30393
|
results.push("\u274C Failed to delete state.json");
|
|
30104
30394
|
}
|
|
30105
|
-
const sessionDir =
|
|
30395
|
+
const sessionDir = statePath ? path60.dirname(statePath) : undefined;
|
|
30106
30396
|
let sessionFiles = [];
|
|
30107
|
-
if (fs28.existsSync(sessionDir)) {
|
|
30397
|
+
if (sessionDir && fs28.existsSync(sessionDir)) {
|
|
30108
30398
|
try {
|
|
30109
30399
|
sessionFiles = fs28.readdirSync(sessionDir);
|
|
30110
30400
|
} catch (err) {
|
|
@@ -30114,7 +30404,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30114
30404
|
for (const file of sessionFiles) {
|
|
30115
30405
|
if (file === "state.json")
|
|
30116
30406
|
continue;
|
|
30117
|
-
const filePath =
|
|
30407
|
+
const filePath = path60.join(sessionDir, file);
|
|
30118
30408
|
try {
|
|
30119
30409
|
if (!fs28.existsSync(filePath))
|
|
30120
30410
|
continue;
|
|
@@ -30136,7 +30426,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30136
30426
|
const chainCount = swarmState.delegationChains.size;
|
|
30137
30427
|
swarmState.delegationChains.clear();
|
|
30138
30428
|
results.push(`\u2705 Cleared ${chainCount} delegation chain(s)`);
|
|
30139
|
-
const worktreesDir =
|
|
30429
|
+
const worktreesDir = path60.resolve(path60.dirname(directory), ".swarm-worktrees");
|
|
30140
30430
|
try {
|
|
30141
30431
|
if (fs28.existsSync(worktreesDir)) {
|
|
30142
30432
|
fs28.rmSync(worktreesDir, { recursive: true, force: true });
|
|
@@ -30169,7 +30459,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30169
30459
|
}
|
|
30170
30460
|
|
|
30171
30461
|
// src/summaries/manager.ts
|
|
30172
|
-
import * as
|
|
30462
|
+
import * as path61 from "path";
|
|
30173
30463
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
30174
30464
|
function sanitizeSummaryId(id) {
|
|
30175
30465
|
if (!id || id.length === 0) {
|
|
@@ -30193,7 +30483,7 @@ function sanitizeSummaryId(id) {
|
|
|
30193
30483
|
}
|
|
30194
30484
|
async function loadFullOutput(directory, id) {
|
|
30195
30485
|
const sanitizedId = sanitizeSummaryId(id);
|
|
30196
|
-
const relativePath =
|
|
30486
|
+
const relativePath = path61.join("summaries", `${sanitizedId}.json`);
|
|
30197
30487
|
validateSwarmPath(directory, relativePath);
|
|
30198
30488
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
30199
30489
|
if (content === null) {
|
|
@@ -30246,7 +30536,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
30246
30536
|
|
|
30247
30537
|
// src/commands/rollback.ts
|
|
30248
30538
|
import * as fs29 from "fs";
|
|
30249
|
-
import * as
|
|
30539
|
+
import * as path62 from "path";
|
|
30250
30540
|
function safeParseToolJson(result) {
|
|
30251
30541
|
try {
|
|
30252
30542
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
@@ -30401,8 +30691,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30401
30691
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
30402
30692
|
continue;
|
|
30403
30693
|
}
|
|
30404
|
-
const src =
|
|
30405
|
-
const dest =
|
|
30694
|
+
const src = path62.join(checkpointDir, file);
|
|
30695
|
+
const dest = path62.join(swarmDir, file);
|
|
30406
30696
|
try {
|
|
30407
30697
|
fs29.cpSync(src, dest, { recursive: true, force: true });
|
|
30408
30698
|
successes.push(file);
|
|
@@ -30421,7 +30711,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30421
30711
|
].join(`
|
|
30422
30712
|
`);
|
|
30423
30713
|
}
|
|
30424
|
-
const existingLedgerPath =
|
|
30714
|
+
const existingLedgerPath = path62.join(swarmDir, "plan-ledger.jsonl");
|
|
30425
30715
|
let ledgerDeletionFailed = false;
|
|
30426
30716
|
if (fs29.existsSync(existingLedgerPath)) {
|
|
30427
30717
|
try {
|
|
@@ -30434,7 +30724,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30434
30724
|
}
|
|
30435
30725
|
if (!ledgerDeletionFailed) {
|
|
30436
30726
|
try {
|
|
30437
|
-
const planJsonPath =
|
|
30727
|
+
const planJsonPath = path62.join(swarmDir, "plan.json");
|
|
30438
30728
|
if (fs29.existsSync(planJsonPath)) {
|
|
30439
30729
|
const planRaw = fs29.readFileSync(planJsonPath, "utf-8");
|
|
30440
30730
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -30482,8 +30772,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30482
30772
|
|
|
30483
30773
|
// src/commands/sdd.ts
|
|
30484
30774
|
import * as fs30 from "fs";
|
|
30485
|
-
import * as
|
|
30486
|
-
var SWARM_SPEC_REL =
|
|
30775
|
+
import * as path63 from "path";
|
|
30776
|
+
var SWARM_SPEC_REL = path63.join(".swarm", "spec.md");
|
|
30487
30777
|
var USAGE9 = `Usage:
|
|
30488
30778
|
/swarm sdd status [--json] [--source <provider>]
|
|
30489
30779
|
/swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
@@ -30599,7 +30889,7 @@ ${USAGE9}`;
|
|
|
30599
30889
|
}
|
|
30600
30890
|
const speckitDetection = detectSpeckit(directory);
|
|
30601
30891
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
30602
|
-
const nativeSpecExists = fs30.existsSync(
|
|
30892
|
+
const nativeSpecExists = fs30.existsSync(path63.join(directory, SWARM_SPEC_REL));
|
|
30603
30893
|
if (speckitPresent && !parsed.source && !nativeSpecExists) {
|
|
30604
30894
|
const openspecProjection = buildOpenSpecProjectionSync(directory);
|
|
30605
30895
|
if (openspecProjection !== null) {
|
|
@@ -30669,7 +30959,7 @@ ${USAGE9}`;
|
|
|
30669
30959
|
${USAGE9}`;
|
|
30670
30960
|
}
|
|
30671
30961
|
let useSpeckit = false;
|
|
30672
|
-
const nativeSpecExists = fs30.existsSync(
|
|
30962
|
+
const nativeSpecExists = fs30.existsSync(path63.join(directory, SWARM_SPEC_REL));
|
|
30673
30963
|
if (parsed.source === "speckit") {
|
|
30674
30964
|
useSpeckit = true;
|
|
30675
30965
|
} else if (!parsed.source && !nativeSpecExists) {
|
|
@@ -30981,10 +31271,10 @@ Ensure this is a git repository with commit history.`;
|
|
|
30981
31271
|
`);
|
|
30982
31272
|
try {
|
|
30983
31273
|
const fs31 = await import("fs/promises");
|
|
30984
|
-
const
|
|
30985
|
-
const reportPath =
|
|
30986
|
-
await fs31.mkdir(
|
|
30987
|
-
const reportTempPath =
|
|
31274
|
+
const path64 = await import("path");
|
|
31275
|
+
const reportPath = path64.join(directory, ".swarm", "simulate-report.md");
|
|
31276
|
+
await fs31.mkdir(path64.dirname(reportPath), { recursive: true });
|
|
31277
|
+
const reportTempPath = path64.join(path64.dirname(reportPath), `${path64.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
30988
31278
|
try {
|
|
30989
31279
|
await fs31.writeFile(reportTempPath, report, "utf-8");
|
|
30990
31280
|
renameSync11(reportTempPath, reportPath);
|
|
@@ -31013,7 +31303,7 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
31013
31303
|
// src/services/status-service.ts
|
|
31014
31304
|
import * as fsSync2 from "fs";
|
|
31015
31305
|
import { readFile as readFile17 } from "fs/promises";
|
|
31016
|
-
import * as
|
|
31306
|
+
import * as path65 from "path";
|
|
31017
31307
|
|
|
31018
31308
|
// src/hooks/extractors.ts
|
|
31019
31309
|
function extractCurrentPhase(planContent) {
|
|
@@ -31058,13 +31348,13 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
31058
31348
|
// src/turbo/lean/state.ts
|
|
31059
31349
|
init_logger();
|
|
31060
31350
|
import * as fs31 from "fs";
|
|
31061
|
-
import * as
|
|
31351
|
+
import * as path64 from "path";
|
|
31062
31352
|
var STATE_FILE3 = "turbo-state.json";
|
|
31063
31353
|
function nowISO3() {
|
|
31064
31354
|
return new Date().toISOString();
|
|
31065
31355
|
}
|
|
31066
31356
|
function ensureSwarmDir2(directory) {
|
|
31067
|
-
const swarmDir =
|
|
31357
|
+
const swarmDir = path64.resolve(directory, ".swarm");
|
|
31068
31358
|
if (!fs31.existsSync(swarmDir)) {
|
|
31069
31359
|
fs31.mkdirSync(swarmDir, { recursive: true });
|
|
31070
31360
|
}
|
|
@@ -31109,7 +31399,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
31109
31399
|
}
|
|
31110
31400
|
function readPersisted2(directory) {
|
|
31111
31401
|
try {
|
|
31112
|
-
const filePath =
|
|
31402
|
+
const filePath = path64.join(directory, ".swarm", STATE_FILE3);
|
|
31113
31403
|
if (!fs31.existsSync(filePath)) {
|
|
31114
31404
|
const seed = emptyPersisted2();
|
|
31115
31405
|
try {
|
|
@@ -31145,7 +31435,7 @@ function writePersisted2(directory, persisted) {
|
|
|
31145
31435
|
let payload;
|
|
31146
31436
|
try {
|
|
31147
31437
|
ensureSwarmDir2(directory);
|
|
31148
|
-
filePath =
|
|
31438
|
+
filePath = path64.join(directory, ".swarm", STATE_FILE3);
|
|
31149
31439
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
31150
31440
|
persisted.updatedAt = nowISO3();
|
|
31151
31441
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -31263,7 +31553,7 @@ var _internals47 = {
|
|
|
31263
31553
|
};
|
|
31264
31554
|
function readSpecStalenessSnapshot(directory) {
|
|
31265
31555
|
try {
|
|
31266
|
-
const p =
|
|
31556
|
+
const p = path65.join(directory, ".swarm", "spec-staleness.json");
|
|
31267
31557
|
if (!fsSync2.existsSync(p))
|
|
31268
31558
|
return { stale: false };
|
|
31269
31559
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -31795,13 +32085,13 @@ function buildStatusMessage2(session, directory, sessionID) {
|
|
|
31795
32085
|
}
|
|
31796
32086
|
|
|
31797
32087
|
// src/commands/unlink.ts
|
|
31798
|
-
import { existsSync as
|
|
31799
|
-
import * as
|
|
32088
|
+
import { existsSync as existsSync40 } from "fs";
|
|
32089
|
+
import * as path66 from "path";
|
|
31800
32090
|
var DEDUP_THRESHOLD2 = 0.6;
|
|
31801
32091
|
async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
|
|
31802
|
-
const sharedPath =
|
|
31803
|
-
const localPath =
|
|
31804
|
-
if (!
|
|
32092
|
+
const sharedPath = path66.join(linkDir, "knowledge.jsonl");
|
|
32093
|
+
const localPath = path66.join(localSwarmDir, "knowledge.jsonl");
|
|
32094
|
+
if (!existsSync40(sharedPath))
|
|
31805
32095
|
return 0;
|
|
31806
32096
|
const sharedEntries = await readKnowledge(sharedPath);
|
|
31807
32097
|
if (sharedEntries.length === 0)
|
|
@@ -31835,7 +32125,7 @@ async function handleUnlinkCommand(directory, args) {
|
|
|
31835
32125
|
let copied = 0;
|
|
31836
32126
|
if (copyBack) {
|
|
31837
32127
|
try {
|
|
31838
|
-
copied = await copySharedKnowledgeToLocal(linkDir,
|
|
32128
|
+
copied = await copySharedKnowledgeToLocal(linkDir, path66.join(directory, ".swarm"));
|
|
31839
32129
|
} catch (error2) {
|
|
31840
32130
|
return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
31841
32131
|
}
|
|
@@ -31997,7 +32287,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
31997
32287
|
async function handleHelpCommand(ctx) {
|
|
31998
32288
|
const targetCommand = ctx.args.join(" ");
|
|
31999
32289
|
if (!targetCommand) {
|
|
32000
|
-
const { buildHelpText } = await import("./index-
|
|
32290
|
+
const { buildHelpText } = await import("./index-19vxtwa6.js");
|
|
32001
32291
|
return buildHelpText();
|
|
32002
32292
|
}
|
|
32003
32293
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -32006,7 +32296,7 @@ async function handleHelpCommand(ctx) {
|
|
|
32006
32296
|
return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
|
|
32007
32297
|
}
|
|
32008
32298
|
const similar = _internals49.findSimilarCommands(targetCommand);
|
|
32009
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
32299
|
+
const { buildHelpText: fullHelp } = await import("./index-19vxtwa6.js");
|
|
32010
32300
|
if (similar.length > 0) {
|
|
32011
32301
|
return `Command '/swarm ${targetCommand}' not found.
|
|
32012
32302
|
|
|
@@ -32139,7 +32429,7 @@ var COMMAND_REGISTRY = {
|
|
|
32139
32429
|
},
|
|
32140
32430
|
"guardrail explain": {
|
|
32141
32431
|
handler: async (ctx) => {
|
|
32142
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32432
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-dayy7zw4.js");
|
|
32143
32433
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32144
32434
|
},
|
|
32145
32435
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -32149,7 +32439,7 @@ var COMMAND_REGISTRY = {
|
|
|
32149
32439
|
},
|
|
32150
32440
|
"guardrail-log": {
|
|
32151
32441
|
handler: async (ctx) => {
|
|
32152
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
32442
|
+
const { handleGuardrailLog } = await import("./guardrail-log-fjypsmek.js");
|
|
32153
32443
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
32154
32444
|
},
|
|
32155
32445
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -32751,9 +33041,9 @@ Subcommands:
|
|
|
32751
33041
|
},
|
|
32752
33042
|
"knowledge restore": {
|
|
32753
33043
|
handler: (ctx) => handleKnowledgeRestoreCommand(ctx.directory, ctx.args),
|
|
32754
|
-
description: "Restore a quarantined knowledge entry <id>",
|
|
33044
|
+
description: "Restore a quarantined or archived knowledge entry <id>",
|
|
32755
33045
|
subcommandOf: "knowledge",
|
|
32756
|
-
details: "Restores a quarantined knowledge entry back to the active knowledge store by ID. Validates entry ID format (1-64 alphanumeric/hyphen/underscore).
|
|
33046
|
+
details: "Restores a quarantined or archived knowledge entry back to the active knowledge store by ID. Dispatches by current status: an 'archived' entry is restored to its pre-archive status; a 'quarantined' entry is restored from the quarantine sidecar. Validates entry ID format (1-64 alphanumeric/hyphen/underscore).",
|
|
32757
33047
|
args: "<entry-id>",
|
|
32758
33048
|
category: "utility"
|
|
32759
33049
|
},
|
|
@@ -32922,24 +33212,24 @@ function validateAliases() {
|
|
|
32922
33212
|
continue;
|
|
32923
33213
|
}
|
|
32924
33214
|
const visited = new Set;
|
|
32925
|
-
const
|
|
33215
|
+
const path67 = [];
|
|
32926
33216
|
let current = target;
|
|
32927
33217
|
while (current) {
|
|
32928
33218
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
32929
33219
|
if (!currentEntry)
|
|
32930
33220
|
break;
|
|
32931
33221
|
if (visited.has(current)) {
|
|
32932
|
-
const cycleStart =
|
|
33222
|
+
const cycleStart = path67.indexOf(current);
|
|
32933
33223
|
const fullChain = [
|
|
32934
33224
|
name,
|
|
32935
|
-
...
|
|
33225
|
+
...path67.slice(0, cycleStart > 0 ? cycleStart : path67.length),
|
|
32936
33226
|
current
|
|
32937
33227
|
].join(" \u2192 ");
|
|
32938
33228
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
32939
33229
|
break;
|
|
32940
33230
|
}
|
|
32941
33231
|
visited.add(current);
|
|
32942
|
-
|
|
33232
|
+
path67.push(current);
|
|
32943
33233
|
current = currentEntry.aliasOf || "";
|
|
32944
33234
|
}
|
|
32945
33235
|
}
|
|
@@ -34278,7 +34568,7 @@ init_logger();
|
|
|
34278
34568
|
|
|
34279
34569
|
// src/hooks/guardrails/destructive-command.ts
|
|
34280
34570
|
import * as fsSync3 from "fs";
|
|
34281
|
-
import * as
|
|
34571
|
+
import * as path67 from "path";
|
|
34282
34572
|
var DC_MAX_UNWRAP_DEPTH = 5;
|
|
34283
34573
|
var DC_SAFE_TARGETS = new Set([
|
|
34284
34574
|
"node_modules",
|
|
@@ -34442,16 +34732,16 @@ function dcIsRemotePath(p) {
|
|
|
34442
34732
|
return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
|
|
34443
34733
|
}
|
|
34444
34734
|
function dcLstatAncestorWalk(targetPath, cwd) {
|
|
34445
|
-
const normalizedTarget =
|
|
34446
|
-
const normalizedCwd =
|
|
34735
|
+
const normalizedTarget = path67.resolve(cwd, targetPath);
|
|
34736
|
+
const normalizedCwd = path67.resolve(cwd);
|
|
34447
34737
|
const ancestors = [];
|
|
34448
34738
|
let current = normalizedTarget;
|
|
34449
34739
|
while (true) {
|
|
34450
34740
|
ancestors.push(current);
|
|
34451
|
-
const parent =
|
|
34741
|
+
const parent = path67.dirname(current);
|
|
34452
34742
|
if (parent === current)
|
|
34453
34743
|
break;
|
|
34454
|
-
const rel =
|
|
34744
|
+
const rel = path67.relative(normalizedCwd, current);
|
|
34455
34745
|
if (rel === "" || rel.startsWith(".."))
|
|
34456
34746
|
break;
|
|
34457
34747
|
current = parent;
|
|
@@ -34490,14 +34780,14 @@ function dcValidateTargets(targets, cwd) {
|
|
|
34490
34780
|
const lstatBlock = dcLstatAncestorWalk(t, cwd);
|
|
34491
34781
|
if (lstatBlock)
|
|
34492
34782
|
return lstatBlock;
|
|
34493
|
-
const basename12 =
|
|
34783
|
+
const basename12 = path67.basename(t);
|
|
34494
34784
|
if (t === basename12 && DC_SAFE_TARGETS.has(t)) {
|
|
34495
34785
|
continue;
|
|
34496
34786
|
}
|
|
34497
34787
|
if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
|
|
34498
34788
|
return `BLOCKED: Destructive command targets filesystem root "${t}"`;
|
|
34499
34789
|
}
|
|
34500
|
-
if (
|
|
34790
|
+
if (path67.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
|
|
34501
34791
|
for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
|
|
34502
34792
|
if (t.startsWith(blocked)) {
|
|
34503
34793
|
return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
|
|
@@ -34512,9 +34802,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34512
34802
|
if (mklinkMatch) {
|
|
34513
34803
|
const target = mklinkMatch[2].trim();
|
|
34514
34804
|
if (!dcHasUnresolvableVars(target)) {
|
|
34515
|
-
const resolved =
|
|
34516
|
-
const rel =
|
|
34517
|
-
if (rel.startsWith("..") ||
|
|
34805
|
+
const resolved = path67.resolve(cwd, target);
|
|
34806
|
+
const rel = path67.relative(cwd, resolved);
|
|
34807
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34518
34808
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
|
|
34519
34809
|
}
|
|
34520
34810
|
}
|
|
@@ -34526,9 +34816,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34526
34816
|
if (newItemMatch) {
|
|
34527
34817
|
const target = newItemMatch[1].trim();
|
|
34528
34818
|
if (!dcHasUnresolvableVars(target)) {
|
|
34529
|
-
const resolved =
|
|
34530
|
-
const rel =
|
|
34531
|
-
if (rel.startsWith("..") ||
|
|
34819
|
+
const resolved = path67.resolve(cwd, target);
|
|
34820
|
+
const rel = path67.relative(cwd, resolved);
|
|
34821
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34532
34822
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
|
|
34533
34823
|
}
|
|
34534
34824
|
}
|
|
@@ -34538,9 +34828,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34538
34828
|
if (lnMatch) {
|
|
34539
34829
|
const target = lnMatch[1].trim();
|
|
34540
34830
|
if (!dcHasUnresolvableVars(target)) {
|
|
34541
|
-
const resolved =
|
|
34542
|
-
const rel =
|
|
34543
|
-
if (rel.startsWith("..") ||
|
|
34831
|
+
const resolved = path67.resolve(cwd, target);
|
|
34832
|
+
const rel = path67.relative(cwd, resolved);
|
|
34833
|
+
if (rel.startsWith("..") || path67.isAbsolute(rel)) {
|
|
34544
34834
|
return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
|
|
34545
34835
|
}
|
|
34546
34836
|
}
|
|
@@ -34911,10 +35201,10 @@ function classifySwarmCommandChatFallbackUse(resolved) {
|
|
|
34911
35201
|
init_executor();
|
|
34912
35202
|
|
|
34913
35203
|
// src/hooks/shell-write-detect.ts
|
|
34914
|
-
import * as
|
|
35204
|
+
import * as path68 from "path";
|
|
34915
35205
|
import parse from "bash-parser";
|
|
34916
|
-
function buildDedupeKey(category, operator,
|
|
34917
|
-
return `${category}|${operator}|${
|
|
35206
|
+
function buildDedupeKey(category, operator, path69) {
|
|
35207
|
+
return `${category}|${operator}|${path69 ?? "null"}`;
|
|
34918
35208
|
}
|
|
34919
35209
|
var REDIRECT_WRITE_TOKENS = new Set([
|
|
34920
35210
|
"GREAT",
|
|
@@ -34974,16 +35264,16 @@ function detectProcessSubstitutionWrites(command) {
|
|
|
34974
35264
|
results.push(builtinResult);
|
|
34975
35265
|
const appendMatch = stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);
|
|
34976
35266
|
if (appendMatch) {
|
|
34977
|
-
const
|
|
34978
|
-
if (
|
|
34979
|
-
results.push({ category: "redirect", operator: ">>", path:
|
|
35267
|
+
const path69 = appendMatch[3];
|
|
35268
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35269
|
+
results.push({ category: "redirect", operator: ">>", path: path69 });
|
|
34980
35270
|
}
|
|
34981
35271
|
} else {
|
|
34982
35272
|
const writeMatch = stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);
|
|
34983
35273
|
if (writeMatch) {
|
|
34984
|
-
const
|
|
34985
|
-
if (
|
|
34986
|
-
results.push({ category: "redirect", operator: ">", path:
|
|
35274
|
+
const path69 = writeMatch[3];
|
|
35275
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35276
|
+
results.push({ category: "redirect", operator: ">", path: path69 });
|
|
34987
35277
|
}
|
|
34988
35278
|
}
|
|
34989
35279
|
}
|
|
@@ -35157,8 +35447,8 @@ function extractRedirectPath(fileNode) {
|
|
|
35157
35447
|
return null;
|
|
35158
35448
|
return text;
|
|
35159
35449
|
}
|
|
35160
|
-
function isNullDevice(
|
|
35161
|
-
return
|
|
35450
|
+
function isNullDevice(path69) {
|
|
35451
|
+
return path69 === "/dev/null" || path69 === "/dev/zero" || path69 === "/dev/urandom";
|
|
35162
35452
|
}
|
|
35163
35453
|
function isNumeric(s) {
|
|
35164
35454
|
return /^\d+$/.test(s);
|
|
@@ -35178,12 +35468,12 @@ function detectRedirects(cmd) {
|
|
|
35178
35468
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
35179
35469
|
continue;
|
|
35180
35470
|
const fileNode = r.file;
|
|
35181
|
-
const
|
|
35471
|
+
const path69 = extractRedirectPath(fileNode);
|
|
35182
35472
|
const opLabel = operatorLabel(opNode);
|
|
35183
35473
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
35184
|
-
results.push({ category: "redirect", operator: opLabel, path:
|
|
35474
|
+
results.push({ category: "redirect", operator: opLabel, path: path69 });
|
|
35185
35475
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
35186
|
-
results.push({ category: "here_doc", operator: opLabel, path:
|
|
35476
|
+
results.push({ category: "here_doc", operator: opLabel, path: path69 });
|
|
35187
35477
|
}
|
|
35188
35478
|
}
|
|
35189
35479
|
return results;
|
|
@@ -35226,9 +35516,9 @@ function detectBuiltinWrites(cmd) {
|
|
|
35226
35516
|
const suffixWords2 = getSuffixWords(cmd);
|
|
35227
35517
|
for (const word of suffixWords2) {
|
|
35228
35518
|
if (word.startsWith("of=")) {
|
|
35229
|
-
const
|
|
35230
|
-
if (
|
|
35231
|
-
results.push({ category: "builtin_write", operator: "dd of=", path:
|
|
35519
|
+
const path69 = word.slice(3);
|
|
35520
|
+
if (path69 && !isNullDevice(path69)) {
|
|
35521
|
+
results.push({ category: "builtin_write", operator: "dd of=", path: path69 });
|
|
35232
35522
|
}
|
|
35233
35523
|
}
|
|
35234
35524
|
}
|
|
@@ -35347,12 +35637,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35347
35637
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35348
35638
|
const word = suffixWords[i];
|
|
35349
35639
|
if (word === "-o" && i + 1 < suffixWords.length) {
|
|
35350
|
-
const
|
|
35351
|
-
if (!
|
|
35640
|
+
const path69 = suffixWords[i + 1];
|
|
35641
|
+
if (!path69.startsWith("-")) {
|
|
35352
35642
|
results.push({
|
|
35353
35643
|
category: "network_download",
|
|
35354
35644
|
operator: "curl -o",
|
|
35355
|
-
path:
|
|
35645
|
+
path: path69
|
|
35356
35646
|
});
|
|
35357
35647
|
}
|
|
35358
35648
|
} else if (word.startsWith("-o") && word.length > 2) {
|
|
@@ -35367,12 +35657,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35367
35657
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35368
35658
|
const word = suffixWords[i];
|
|
35369
35659
|
if (word === "-O" && i + 1 < suffixWords.length) {
|
|
35370
|
-
const
|
|
35371
|
-
if (!
|
|
35660
|
+
const path69 = suffixWords[i + 1];
|
|
35661
|
+
if (!path69.startsWith("-")) {
|
|
35372
35662
|
results.push({
|
|
35373
35663
|
category: "network_download",
|
|
35374
35664
|
operator: "wget -O",
|
|
35375
|
-
path:
|
|
35665
|
+
path: path69
|
|
35376
35666
|
});
|
|
35377
35667
|
}
|
|
35378
35668
|
} else if (word.startsWith("-O") && word.length > 2) {
|
|
@@ -35481,9 +35771,9 @@ function detectGitDestructive(cmd) {
|
|
|
35481
35771
|
if (first === "checkout") {
|
|
35482
35772
|
const dashDashIdx = suffixWords.indexOf("--");
|
|
35483
35773
|
if (dashDashIdx !== -1 && dashDashIdx + 1 < suffixWords.length) {
|
|
35484
|
-
const
|
|
35485
|
-
const op =
|
|
35486
|
-
results.push({ category: "git_destructive", operator: op, path:
|
|
35774
|
+
const path69 = suffixWords[dashDashIdx + 1];
|
|
35775
|
+
const op = path69 === "." ? "git checkout -- ." : "git checkout --";
|
|
35776
|
+
results.push({ category: "git_destructive", operator: op, path: path69 });
|
|
35487
35777
|
}
|
|
35488
35778
|
} else if (first === "restore") {
|
|
35489
35779
|
const hasHard = suffixWords.some((w) => w === "--hard" || w === "-H" || w.startsWith("-") && w.includes("H"));
|
|
@@ -35603,10 +35893,10 @@ function detectPowerShellWrites(command) {
|
|
|
35603
35893
|
if (redirectMatch) {
|
|
35604
35894
|
const beforeRedirect = redirectMatch[1];
|
|
35605
35895
|
const op = redirectMatch[2];
|
|
35606
|
-
const
|
|
35896
|
+
const path69 = redirectMatch[3];
|
|
35607
35897
|
const fdRedirectPattern = /\d>\s*$|\s\d>&$/;
|
|
35608
35898
|
if (!fdRedirectPattern.test(`${beforeRedirect} ${op}`)) {
|
|
35609
|
-
results.push({ category: "redirect", operator: op, path:
|
|
35899
|
+
results.push({ category: "redirect", operator: op, path: path69 });
|
|
35610
35900
|
}
|
|
35611
35901
|
}
|
|
35612
35902
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35619,12 +35909,12 @@ function detectPowerShellWrites(command) {
|
|
|
35619
35909
|
}
|
|
35620
35910
|
const iwrMatch = trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);
|
|
35621
35911
|
if (iwrMatch) {
|
|
35622
|
-
const
|
|
35623
|
-
if (
|
|
35912
|
+
const path69 = iwrMatch[1] || iwrMatch[2];
|
|
35913
|
+
if (path69) {
|
|
35624
35914
|
results.push({
|
|
35625
35915
|
category: "network_download",
|
|
35626
35916
|
operator: "Invoke-WebRequest -OutFile",
|
|
35627
|
-
path:
|
|
35917
|
+
path: path69
|
|
35628
35918
|
});
|
|
35629
35919
|
}
|
|
35630
35920
|
}
|
|
@@ -35636,15 +35926,15 @@ function detectPowerShellWrites(command) {
|
|
|
35636
35926
|
const rest = cmd.slice(cmdletMatch[0].length).trim();
|
|
35637
35927
|
const pathFlagMatch = rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+("([^"]+)"|'([^']+)'|(\S+))/i);
|
|
35638
35928
|
if (pathFlagMatch) {
|
|
35639
|
-
const
|
|
35640
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35929
|
+
const path69 = pathFlagMatch[2] ?? pathFlagMatch[3] ?? pathFlagMatch[4] ?? "";
|
|
35930
|
+
return { category: "redirect", operator: cmdletName, path: path69 };
|
|
35641
35931
|
}
|
|
35642
35932
|
const tokens = rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35643
35933
|
for (const token of tokens) {
|
|
35644
35934
|
if (token.startsWith("-"))
|
|
35645
35935
|
continue;
|
|
35646
|
-
const
|
|
35647
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35936
|
+
const path69 = token.replace(/^["']|["']$/g, "");
|
|
35937
|
+
return { category: "redirect", operator: cmdletName, path: path69 };
|
|
35648
35938
|
}
|
|
35649
35939
|
return null;
|
|
35650
35940
|
}
|
|
@@ -35660,9 +35950,9 @@ function detectPowerShellWrites(command) {
|
|
|
35660
35950
|
for (const token of tokens) {
|
|
35661
35951
|
if (token.startsWith("-"))
|
|
35662
35952
|
continue;
|
|
35663
|
-
const
|
|
35664
|
-
if (
|
|
35665
|
-
results.push({ category: "redirect", operator: cmdletName, path:
|
|
35953
|
+
const path69 = token.replace(/^["']|["']$/g, "");
|
|
35954
|
+
if (path69) {
|
|
35955
|
+
results.push({ category: "redirect", operator: cmdletName, path: path69 });
|
|
35666
35956
|
break;
|
|
35667
35957
|
}
|
|
35668
35958
|
}
|
|
@@ -35675,8 +35965,8 @@ function detectPowerShellWrites(command) {
|
|
|
35675
35965
|
const rest = cmd.slice(opMatch[0].length).trim();
|
|
35676
35966
|
const destFlagMatch = rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35677
35967
|
if (destFlagMatch) {
|
|
35678
|
-
const
|
|
35679
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35968
|
+
const path69 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
35969
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35680
35970
|
}
|
|
35681
35971
|
const tokens = [];
|
|
35682
35972
|
const flagTakingValue = new Set([
|
|
@@ -35715,11 +36005,11 @@ function detectPowerShellWrites(command) {
|
|
|
35715
36005
|
}
|
|
35716
36006
|
}
|
|
35717
36007
|
if (tokens.length >= 2) {
|
|
35718
|
-
const
|
|
35719
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
36008
|
+
const path69 = tokens[tokens.length - 1].replace(/^["']|["']$/g, "");
|
|
36009
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35720
36010
|
} else if (tokens.length === 1) {
|
|
35721
|
-
const
|
|
35722
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
36011
|
+
const path69 = tokens[0].replace(/^["']|["']$/g, "");
|
|
36012
|
+
return { category: "builtin_write", operator: cmdletName, path: path69 };
|
|
35723
36013
|
}
|
|
35724
36014
|
return null;
|
|
35725
36015
|
}
|
|
@@ -35733,14 +36023,14 @@ function detectPowerShellWrites(command) {
|
|
|
35733
36023
|
const afterCmdlet = pipeFileOpMatch[2].trim();
|
|
35734
36024
|
const destFlagMatch = afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35735
36025
|
if (destFlagMatch) {
|
|
35736
|
-
const
|
|
35737
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
36026
|
+
const path69 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
36027
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path69 });
|
|
35738
36028
|
} else {
|
|
35739
36029
|
const tokens = afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35740
36030
|
const nonFlagTokens = tokens.filter((t) => !t.startsWith("-") && t.length > 0);
|
|
35741
36031
|
if (nonFlagTokens.length > 0) {
|
|
35742
|
-
const
|
|
35743
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
36032
|
+
const path69 = nonFlagTokens[nonFlagTokens.length - 1].replace(/^["']|["']$/g, "");
|
|
36033
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path69 });
|
|
35744
36034
|
}
|
|
35745
36035
|
}
|
|
35746
36036
|
}
|
|
@@ -35793,10 +36083,10 @@ function detectCmdWrites(command) {
|
|
|
35793
36083
|
if (redirectMatch) {
|
|
35794
36084
|
const beforeRedirect = redirectMatch[1];
|
|
35795
36085
|
const op = redirectMatch[2];
|
|
35796
|
-
const
|
|
36086
|
+
const path69 = redirectMatch[3];
|
|
35797
36087
|
const fdRedirectPattern = /\d>&?$/;
|
|
35798
36088
|
if (!fdRedirectPattern.test(beforeRedirect)) {
|
|
35799
|
-
results.push({ category: "redirect", operator: op, path:
|
|
36089
|
+
results.push({ category: "redirect", operator: op, path: path69 });
|
|
35800
36090
|
}
|
|
35801
36091
|
}
|
|
35802
36092
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35854,8 +36144,8 @@ function detectCmdWrites(command) {
|
|
|
35854
36144
|
const rawTokens = rest.match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g) ?? [];
|
|
35855
36145
|
const tokens = rawTokens.filter((t) => !t.startsWith("/"));
|
|
35856
36146
|
if (tokens.length > 0) {
|
|
35857
|
-
const
|
|
35858
|
-
return { category: "builtin_write", operator: "del", path:
|
|
36147
|
+
const path69 = tokens[0].replace(/^["']|["']$/g, "");
|
|
36148
|
+
return { category: "builtin_write", operator: "del", path: path69 };
|
|
35859
36149
|
}
|
|
35860
36150
|
return null;
|
|
35861
36151
|
}
|
|
@@ -35865,16 +36155,16 @@ function detectCmdWrites(command) {
|
|
|
35865
36155
|
}
|
|
35866
36156
|
const rdMatch = innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);
|
|
35867
36157
|
if (rdMatch) {
|
|
35868
|
-
const
|
|
35869
|
-
if (!
|
|
35870
|
-
results.push({ category: "builtin_write", operator: "rd", path:
|
|
36158
|
+
const path69 = rdMatch[1].replace(/^["']|["']$/g, "");
|
|
36159
|
+
if (!path69.startsWith("/")) {
|
|
36160
|
+
results.push({ category: "builtin_write", operator: "rd", path: path69 });
|
|
35871
36161
|
}
|
|
35872
36162
|
}
|
|
35873
36163
|
const mdMatch = trimmed.match(/^md\s+(\S+)/i);
|
|
35874
36164
|
if (mdMatch) {
|
|
35875
|
-
const
|
|
35876
|
-
if (!
|
|
35877
|
-
results.push({ category: "builtin_write", operator: "md", path:
|
|
36165
|
+
const path69 = mdMatch[1].replace(/^["']|["']$/g, "");
|
|
36166
|
+
if (!path69.startsWith("/")) {
|
|
36167
|
+
results.push({ category: "builtin_write", operator: "md", path: path69 });
|
|
35878
36168
|
}
|
|
35879
36169
|
}
|
|
35880
36170
|
const echoMatch = trimmed.match(/^echo\s+(\S+.*?)\s+((?:>){1,2})\s*(\S+)$/i);
|
|
@@ -35990,9 +36280,10 @@ function resolvePath(pathText, cwd) {
|
|
|
35990
36280
|
return null;
|
|
35991
36281
|
const isWindowsPath = /^[a-zA-Z]:[\\\\/]/.test(cwd) || cwd.includes("\\");
|
|
35992
36282
|
if (isWindowsPath) {
|
|
35993
|
-
return
|
|
36283
|
+
return path68.win32.resolve(cwd, pathText);
|
|
35994
36284
|
}
|
|
35995
|
-
|
|
36285
|
+
const normalizedRelativeWindowsPath = !path68.posix.isAbsolute(pathText) && !/^[a-zA-Z]:[\\/]/.test(pathText) ? pathText.replace(/\\/g, "/") : pathText;
|
|
36286
|
+
return path68.posix.resolve(cwd, normalizedRelativeWindowsPath);
|
|
35996
36287
|
}
|
|
35997
36288
|
function getCdTarget(cmd) {
|
|
35998
36289
|
if (!cmd || typeof cmd !== "object")
|
|
@@ -36059,7 +36350,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
36059
36350
|
for (const cmd of node.commands) {
|
|
36060
36351
|
const cdTarget = getCdTarget(cmd);
|
|
36061
36352
|
if (cdTarget) {
|
|
36062
|
-
currentStack[0] =
|
|
36353
|
+
currentStack[0] = path68.posix.resolve(currentStack[0] ?? "/", cdTarget);
|
|
36063
36354
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
36064
36355
|
} else {
|
|
36065
36356
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
@@ -36105,7 +36396,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
36105
36396
|
const effectiveCwd = cwdStack[0] ?? "/";
|
|
36106
36397
|
const cdTarget = getCdTarget(node);
|
|
36107
36398
|
if (cdTarget) {
|
|
36108
|
-
cwdStack[0] =
|
|
36399
|
+
cwdStack[0] = path68.posix.resolve(cwdStack[0] ?? "/", cdTarget);
|
|
36109
36400
|
return;
|
|
36110
36401
|
}
|
|
36111
36402
|
const writesFromRedirs = getWritesFromCommandRedirs(node, effectiveCwd);
|
|
@@ -36151,12 +36442,12 @@ function getWritesFromRedirectNode(redirect, _context) {
|
|
|
36151
36442
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
36152
36443
|
return [];
|
|
36153
36444
|
const fileNode = r.file;
|
|
36154
|
-
const
|
|
36445
|
+
const path69 = extractRedirectPath(fileNode);
|
|
36155
36446
|
const opLabel = operatorLabel(opNode);
|
|
36156
36447
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
36157
|
-
return [{ category: "redirect", operator: opLabel, path:
|
|
36448
|
+
return [{ category: "redirect", operator: opLabel, path: path69 }];
|
|
36158
36449
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
36159
|
-
return [{ category: "here_doc", operator: opLabel, path:
|
|
36450
|
+
return [{ category: "here_doc", operator: opLabel, path: path69 }];
|
|
36160
36451
|
}
|
|
36161
36452
|
return [];
|
|
36162
36453
|
}
|
|
@@ -36277,6 +36568,15 @@ var ACTIVE_PARALLEL_TASK_STATES = new Set([
|
|
|
36277
36568
|
"tests_run"
|
|
36278
36569
|
]);
|
|
36279
36570
|
|
|
36571
|
+
// src/hooks/realtime-learning-nudge.ts
|
|
36572
|
+
var realtimeLearningNudgeBySession = new Map;
|
|
36573
|
+
function resetRealtimeLearningNudgeState() {
|
|
36574
|
+
realtimeLearningNudgeBySession.clear();
|
|
36575
|
+
}
|
|
36576
|
+
function clearRealtimeLearningNudgeSession(sessionID) {
|
|
36577
|
+
realtimeLearningNudgeBySession.delete(sessionID);
|
|
36578
|
+
}
|
|
36579
|
+
|
|
36280
36580
|
// src/session/worktree-link-suggestion.ts
|
|
36281
36581
|
import { execFile as execFile3 } from "child_process";
|
|
36282
36582
|
var GIT_TIMEOUT_MS2 = 1500;
|
|
@@ -36419,6 +36719,7 @@ function resetSwarmState() {
|
|
|
36419
36719
|
swarmState.environmentProfiles.clear();
|
|
36420
36720
|
clearPendingCoderScope();
|
|
36421
36721
|
resetStandardWorktreeIsolationState();
|
|
36722
|
+
resetRealtimeLearningNudgeState();
|
|
36422
36723
|
_councilDisagreementWarned.clear();
|
|
36423
36724
|
}
|
|
36424
36725
|
function resetSwarmStatePreservingSingletons() {
|
|
@@ -36557,6 +36858,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = STALE_SESSION
|
|
|
36557
36858
|
}
|
|
36558
36859
|
function endAgentSession(sessionId) {
|
|
36559
36860
|
swarmState.agentSessions.delete(sessionId);
|
|
36861
|
+
clearRealtimeLearningNudgeSession(sessionId);
|
|
36560
36862
|
}
|
|
36561
36863
|
function getAgentSession(sessionId) {
|
|
36562
36864
|
return swarmState.agentSessions.get(sessionId);
|
|
@@ -36899,7 +37201,7 @@ function evidenceToWorkflowState(evidence) {
|
|
|
36899
37201
|
}
|
|
36900
37202
|
async function readPlanFromDisk(directory) {
|
|
36901
37203
|
try {
|
|
36902
|
-
const planPath =
|
|
37204
|
+
const planPath = path69.join(directory, ".swarm", "plan.json");
|
|
36903
37205
|
const content = await fs32.readFile(planPath, "utf-8");
|
|
36904
37206
|
const parsed = JSON.parse(content);
|
|
36905
37207
|
return PlanSchema.parse(parsed);
|
|
@@ -36910,7 +37212,7 @@ async function readPlanFromDisk(directory) {
|
|
|
36910
37212
|
async function readGateEvidenceFromDisk(directory) {
|
|
36911
37213
|
const evidenceMap = new Map;
|
|
36912
37214
|
try {
|
|
36913
|
-
const evidenceDir =
|
|
37215
|
+
const evidenceDir = path69.join(directory, ".swarm", "evidence");
|
|
36914
37216
|
const entries = await fs32.readdir(evidenceDir, { withFileTypes: true });
|
|
36915
37217
|
for (const entry of entries) {
|
|
36916
37218
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
@@ -36921,7 +37223,7 @@ async function readGateEvidenceFromDisk(directory) {
|
|
|
36921
37223
|
continue;
|
|
36922
37224
|
}
|
|
36923
37225
|
try {
|
|
36924
|
-
const filePath =
|
|
37226
|
+
const filePath = path69.join(evidenceDir, entry.name);
|
|
36925
37227
|
const content = await fs32.readFile(filePath, "utf-8");
|
|
36926
37228
|
const parsed = JSON.parse(content);
|
|
36927
37229
|
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|
|
@@ -37063,7 +37365,7 @@ function hasActiveEpicMode(sessionID) {
|
|
|
37063
37365
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
37064
37366
|
const map = new Map;
|
|
37065
37367
|
try {
|
|
37066
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
37368
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-bpvazmsw.js");
|
|
37067
37369
|
const records = await listActive2(directory);
|
|
37068
37370
|
for (const record of records) {
|
|
37069
37371
|
if (record.sessionID !== sessionID)
|