opencode-swarm 7.139.2 → 7.139.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/skills/phase-wrap/SKILL.md +2 -2
- package/dist/background/stage-b-gates.d.ts +5 -1
- package/dist/background/task-envelope.d.ts +4 -4
- package/dist/cli/{config-doctor-hrb61yqe.js → config-doctor-75qky762.js} +3 -3
- package/dist/cli/{core-g2dfh9fq.js → core-nn8ffy5h.js} +3 -3
- package/dist/cli/{curation-policy-4tp0mbcb.js → curation-policy-f46tf3dw.js} +5 -5
- package/dist/cli/{curator-drift-vfh07mqy.js → curator-drift-r52hjskk.js} +2 -2
- package/dist/cli/{curator-llm-factory-hvw13hmr.js → curator-llm-factory-1r9vz0g2.js} +28 -28
- package/dist/cli/{curator-vpcs1p1v.js → curator-m6mk2v1n.js} +28 -28
- package/dist/cli/{dispatch-b1fge4xk.js → dispatch-nbv0hezh.js} +2 -2
- package/dist/cli/{evidence-summary-service-kzxr71yd.js → evidence-summary-service-sxcq5nrt.js} +6 -6
- package/dist/cli/{gate-evidence-z2b1ymnw.js → gate-evidence-1982qswy.js} +3 -3
- package/dist/cli/{guardrail-explain-k62h3c92.js → guardrail-explain-y2wg00dp.js} +29 -29
- package/dist/cli/{guardrail-log-2ftew0p3.js → guardrail-log-320grggj.js} +5 -5
- package/dist/cli/{hive-promoter-mpf0cfkk.js → hive-promoter-v4w7cjvk.js} +28 -28
- package/dist/cli/{index-3eddtgxt.js → index-05mms0va.js} +1 -1
- package/dist/cli/{index-y64jv2pe.js → index-0mzz46we.js} +2 -2
- package/dist/cli/{index-ffpmqx30.js → index-1jbj7vzv.js} +4 -4
- package/dist/cli/{index-y47dwge1.js → index-1yd38ajy.js} +2 -2
- package/dist/cli/{index-gvhvz176.js → index-2eet124q.js} +1 -1
- package/dist/cli/{index-0wp67gqj.js → index-4fr94329.js} +11 -6
- package/dist/cli/{index-y111zefa.js → index-4nt52yr9.js} +80 -31
- package/dist/cli/{index-3jcyn8g6.js → index-4wjk296r.js} +1 -1
- package/dist/cli/{index-se8xc78k.js → index-5hyq2mw6.js} +30 -30
- package/dist/cli/{index-5zyk8qgv.js → index-5syvwd8g.js} +1 -1
- package/dist/cli/{index-ktagrqxw.js → index-6axm8q3s.js} +3 -3
- package/dist/cli/{index-668dpw5e.js → index-6mvbjqbt.js} +1 -1
- package/dist/cli/{index-wsdnttf4.js → index-74hpm6sh.js} +1 -1
- package/dist/cli/{index-wrt6m5ze.js → index-ajwmn8gp.js} +289 -73
- package/dist/cli/{index-6w1re1qn.js → index-ba5e5e3n.js} +2 -2
- package/dist/cli/{index-8gftfvpp.js → index-bcwx1335.js} +1 -1
- package/dist/cli/{index-a12906mj.js → index-gen82t10.js} +3 -3
- package/dist/cli/{index-s608d3hw.js → index-hckq2r5m.js} +1 -1
- package/dist/cli/{index-e9tx99ds.js → index-hwnpd4tw.js} +3 -3
- package/dist/cli/{index-3radty3f.js → index-jqn332jx.js} +2 -2
- package/dist/cli/{index-x9q4bbhd.js → index-k87hs2ff.js} +1 -1
- package/dist/cli/{index-8p9pasnp.js → index-kyz7259r.js} +2 -2
- package/dist/cli/{index-prmb5qfp.js → index-mv0czd9c.js} +2 -2
- package/dist/cli/{index-6c5f309q.js → index-mzck763x.js} +2 -2
- package/dist/cli/{index-a7nh382r.js → index-tkg6rapy.js} +1344 -682
- package/dist/cli/{index-yr6x707c.js → index-v7g8dnyh.js} +3 -3
- package/dist/cli/{index-w71cq27a.js → index-xeyr62x0.js} +5 -5
- package/dist/cli/{index-vm4xw9z3.js → index-xsxrhakg.js} +1 -1
- package/dist/cli/{index-5w7ekpy3.js → index-xzzcfwwm.js} +1 -1
- package/dist/cli/{index-q11t5erh.js → index-yawwwhmc.js} +2 -2
- package/dist/cli/{index-q7ezzgwq.js → index-yh0q21nj.js} +1 -1
- package/dist/cli/{index-cyw81ngh.js → index-z6qe8wft.js} +6 -6
- package/dist/cli/index.js +28 -28
- package/dist/cli/{knowledge-escalator-n9pmx4qr.js → knowledge-escalator-kkjsjtza.js} +6 -6
- package/dist/cli/{knowledge-events-raevm18w.js → knowledge-events-jbw9j94n.js} +4 -4
- package/dist/cli/{knowledge-link-3tq8w6gs.js → knowledge-link-f6akgbdn.js} +3 -3
- package/dist/cli/{knowledge-store-bcfqz8fr.js → knowledge-store-m7vnz62z.js} +4 -4
- package/dist/cli/{knowledge-validator-jxqj96cx.js → knowledge-validator-rqj7kech.js} +7 -7
- package/dist/cli/{pending-delegations-tmyf18p4.js → pending-delegations-14544jpr.js} +3 -3
- package/dist/cli/{pr-subscriptions-hhx6yk24.js → pr-subscriptions-qdwfm1a8.js} +3 -3
- package/dist/cli/{runner-w30gazew.js → runner-mzb3e2s6.js} +4 -4
- package/dist/cli/{scan-cursor-ah5swtyh.js → scan-cursor-8e6ryhjq.js} +5 -5
- package/dist/cli/{schema-f7jgrtxj.js → schema-g7rs20c6.js} +2 -2
- package/dist/cli/{scope-persistence-3f0d4fwv.js → scope-persistence-wy65zyha.js} +2 -2
- package/dist/cli/{skill-generator-hp7as46c.js → skill-generator-2rv6ftre.js} +8 -8
- package/dist/cli/{task-envelope-qn0qtnh0.js → task-envelope-jp2fdsvn.js} +11 -8
- package/dist/cli/{workspace-snapshot-h5rzw37b.js → workspace-snapshot-w3tg4ne5.js} +2 -2
- package/dist/cli/{worktree-collision-ownership-vexb0b6r.js → worktree-collision-ownership-24s0t62z.js} +4 -4
- package/dist/commands/approve-plan-critic.d.ts +2 -2
- package/dist/commands/registry.d.ts +1 -1
- package/dist/config/agent-model.d.ts +35 -0
- package/dist/db/qa-gate-profile.d.ts +11 -3
- package/dist/evidence/manager.d.ts +1 -1
- package/dist/evidence/phase-participation.d.ts +44 -0
- package/dist/hooks/compaction-customizer.d.ts +30 -2
- package/dist/hooks/context-budget.d.ts +1 -1
- package/dist/hooks/delegation-gate.d.ts +3 -3
- package/dist/hooks/guardrails/index.d.ts +5 -1
- package/dist/hooks/guardrails/messages-transform.d.ts +2 -0
- package/dist/hooks/guardrails/pre-check-result.d.ts +20 -0
- package/dist/index.js +420 -415
- package/dist/sast/semgrep.d.ts +15 -32
- package/dist/services/compaction-service.d.ts +3 -1
- package/dist/session/snapshot-writer.d.ts +1 -0
- package/dist/state.d.ts +70 -19
- package/dist/tools/context-status.d.ts +4 -1
- package/dist/tools/lint.d.ts +48 -22
- package/dist/tools/pre-check-batch.d.ts +37 -13
- package/dist/tools/quality-budget.d.ts +3 -2
- package/dist/tools/sast-baseline.d.ts +1 -0
- package/dist/tools/sast-scan.d.ts +4 -1
- package/dist/tools/secretscan.d.ts +2 -2
- package/dist/tools/set-qa-gates.d.ts +5 -4
- package/dist/utils/bun-compat.d.ts +20 -0
- package/dist/utils/external-tool-runner.d.ts +10 -0
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getProfileForFile,
|
|
6
6
|
isCommandAvailable,
|
|
7
7
|
tool
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-xsxrhakg.js";
|
|
9
9
|
import {
|
|
10
10
|
captureWorkingTreeFingerprint,
|
|
11
11
|
createModelEvaluationExecutor,
|
|
@@ -13,16 +13,16 @@ import {
|
|
|
13
13
|
resolveExecutableFromPath,
|
|
14
14
|
runEvaluation,
|
|
15
15
|
runExternalTool
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-ajwmn8gp.js";
|
|
17
17
|
import {
|
|
18
18
|
stableCanonicalStringify
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-0mzz46we.js";
|
|
20
20
|
import {
|
|
21
21
|
detectStraySwarmDirs,
|
|
22
22
|
readDoctorArtifact,
|
|
23
23
|
removeStraySwarmDir,
|
|
24
24
|
runConfigDoctor
|
|
25
|
-
} from "./index-
|
|
25
|
+
} from "./index-1yd38ajy.js";
|
|
26
26
|
import {
|
|
27
27
|
MAX_TRANSIENT_RETRIES,
|
|
28
28
|
archiveEvidence,
|
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
savePlan,
|
|
62
62
|
transientBackoff,
|
|
63
63
|
validateProjectRoot
|
|
64
|
-
} from "./index-
|
|
64
|
+
} from "./index-4fr94329.js";
|
|
65
65
|
import {
|
|
66
66
|
EvaluationTaskV1Schema,
|
|
67
67
|
GateAuditManifestV1Schema,
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
saveGateAuditResult,
|
|
79
79
|
savePromotionDecision,
|
|
80
80
|
saveTaskSetSnapshot
|
|
81
|
-
} from "./index-
|
|
81
|
+
} from "./index-hckq2r5m.js";
|
|
82
82
|
import {
|
|
83
83
|
canonicalHash,
|
|
84
84
|
canonicalJson,
|
|
@@ -116,15 +116,15 @@ import {
|
|
|
116
116
|
retireSkill,
|
|
117
117
|
selectCandidateEntries,
|
|
118
118
|
syncBundledProjectSkillsIfMissingAsync
|
|
119
|
-
} from "./index-
|
|
119
|
+
} from "./index-6axm8q3s.js";
|
|
120
120
|
import {
|
|
121
121
|
readRecentEscalations
|
|
122
|
-
} from "./index-
|
|
122
|
+
} from "./index-xeyr62x0.js";
|
|
123
123
|
import {
|
|
124
124
|
alreadyCuratedThisGeneration,
|
|
125
125
|
claimNextScanBatch,
|
|
126
126
|
resolveCohortId
|
|
127
|
-
} from "./index-
|
|
127
|
+
} from "./index-ba5e5e3n.js";
|
|
128
128
|
import {
|
|
129
129
|
CURATOR_INIT_PROMPT,
|
|
130
130
|
CURATOR_PHASE_PROMPT,
|
|
@@ -166,7 +166,7 @@ import {
|
|
|
166
166
|
resolveRemoteRefsContainingHead,
|
|
167
167
|
resolveRemoteRefsContainingHeadAsync,
|
|
168
168
|
switchPrFeedbackTrackingCandidateAsync
|
|
169
|
-
} from "./index-
|
|
169
|
+
} from "./index-74hpm6sh.js";
|
|
170
170
|
import {
|
|
171
171
|
appendUnactionable,
|
|
172
172
|
quarantineEntry,
|
|
@@ -177,11 +177,11 @@ import {
|
|
|
177
177
|
validateActionableFields,
|
|
178
178
|
validateLesson,
|
|
179
179
|
validateSkillPath
|
|
180
|
-
} from "./index-
|
|
180
|
+
} from "./index-1jbj7vzv.js";
|
|
181
181
|
import {
|
|
182
182
|
authorizeCuration,
|
|
183
183
|
buildConfigFingerprintInput
|
|
184
|
-
} from "./index-
|
|
184
|
+
} from "./index-jqn332jx.js";
|
|
185
185
|
import {
|
|
186
186
|
cohortConfigFingerprint
|
|
187
187
|
} from "./index-rtry5xyf.js";
|
|
@@ -214,7 +214,7 @@ import {
|
|
|
214
214
|
transactFile,
|
|
215
215
|
transactKnowledge,
|
|
216
216
|
wordBigrams
|
|
217
|
-
} from "./index-
|
|
217
|
+
} from "./index-z6qe8wft.js";
|
|
218
218
|
import {
|
|
219
219
|
MAX_EVENT_LOG_ENTRIES,
|
|
220
220
|
_internals,
|
|
@@ -224,7 +224,7 @@ import {
|
|
|
224
224
|
recordHiveKnowledgeEvent,
|
|
225
225
|
recordKnowledgeEvent,
|
|
226
226
|
resolveKnowledgeEventsPath
|
|
227
|
-
} from "./index-
|
|
227
|
+
} from "./index-hwnpd4tw.js";
|
|
228
228
|
import {
|
|
229
229
|
resolveHiveDataDir,
|
|
230
230
|
resolveHiveEventsPath,
|
|
@@ -240,16 +240,16 @@ import {
|
|
|
240
240
|
resolveLinkDir,
|
|
241
241
|
sanitizeLinkId,
|
|
242
242
|
writeLinkPointer
|
|
243
|
-
} from "./index-
|
|
243
|
+
} from "./index-6mvbjqbt.js";
|
|
244
244
|
import {
|
|
245
245
|
atomicWriteFile
|
|
246
|
-
} from "./index-
|
|
246
|
+
} from "./index-2eet124q.js";
|
|
247
247
|
import {
|
|
248
248
|
exports_loader,
|
|
249
249
|
init_loader,
|
|
250
250
|
loadPluginConfig,
|
|
251
251
|
loadPluginConfigWithMeta
|
|
252
|
-
} from "./index-
|
|
252
|
+
} from "./index-yawwwhmc.js";
|
|
253
253
|
import {
|
|
254
254
|
RetrospectiveEvidenceSchema
|
|
255
255
|
} from "./index-gprxjmm7.js";
|
|
@@ -266,7 +266,7 @@ import {
|
|
|
266
266
|
package_default,
|
|
267
267
|
resolveAutoReviewConfig,
|
|
268
268
|
stripKnownSwarmPrefix
|
|
269
|
-
} from "./index-
|
|
269
|
+
} from "./index-kyz7259r.js";
|
|
270
270
|
import {
|
|
271
271
|
KNOWLEDGE_SCHEMA_VERSION,
|
|
272
272
|
OUTCOME_BLOCK_THRESHOLD,
|
|
@@ -282,13 +282,13 @@ import {
|
|
|
282
282
|
listActive,
|
|
283
283
|
subscribe,
|
|
284
284
|
unsubscribe
|
|
285
|
-
} from "./index-
|
|
285
|
+
} from "./index-5syvwd8g.js";
|
|
286
286
|
import {
|
|
287
287
|
MAX_PENDING_SCOPE_BINDINGS,
|
|
288
288
|
clearAllScopes,
|
|
289
289
|
clearScopeBindingFromDisk,
|
|
290
290
|
clearScopeBindings
|
|
291
|
-
} from "./index-
|
|
291
|
+
} from "./index-05mms0va.js";
|
|
292
292
|
import {
|
|
293
293
|
appendLedgerEvent,
|
|
294
294
|
computePlanHash,
|
|
@@ -311,6 +311,7 @@ import {
|
|
|
311
311
|
} from "./index-4rhhvd1a.js";
|
|
312
312
|
import {
|
|
313
313
|
AGENT_TOOL_MAP,
|
|
314
|
+
ALL_AGENT_NAMES,
|
|
314
315
|
ALL_SUBAGENT_NAMES,
|
|
315
316
|
ORCHESTRATOR_NAME,
|
|
316
317
|
SWARM_WORKTREE_DIR_NAME,
|
|
@@ -319,16 +320,16 @@ import {
|
|
|
319
320
|
init_agent_names,
|
|
320
321
|
init_constants,
|
|
321
322
|
init_tool_metadata
|
|
322
|
-
} from "./index-
|
|
323
|
+
} from "./index-4wjk296r.js";
|
|
323
324
|
import {
|
|
324
325
|
findByBatchId,
|
|
325
326
|
readDelegations
|
|
326
|
-
} from "./index-
|
|
327
|
+
} from "./index-mv0czd9c.js";
|
|
327
328
|
import {
|
|
328
329
|
readSwarmFileAsync,
|
|
329
330
|
safeHook,
|
|
330
331
|
validateSwarmPath
|
|
331
|
-
} from "./index-
|
|
332
|
+
} from "./index-k87hs2ff.js";
|
|
332
333
|
import {
|
|
333
334
|
invalidateCachedArtifact,
|
|
334
335
|
resetSwarmArtifactCache
|
|
@@ -353,7 +354,7 @@ import {
|
|
|
353
354
|
bunSpawn,
|
|
354
355
|
bunWrite,
|
|
355
356
|
mergeEnvForChild
|
|
356
|
-
} from "./index-
|
|
357
|
+
} from "./index-4nt52yr9.js";
|
|
357
358
|
import {
|
|
358
359
|
criticalWarn,
|
|
359
360
|
error,
|
|
@@ -367,6 +368,19 @@ import {
|
|
|
367
368
|
__toESM
|
|
368
369
|
} from "./index-a76rekgs.js";
|
|
369
370
|
|
|
371
|
+
// src/config/agent-model.ts
|
|
372
|
+
init_agent_names();
|
|
373
|
+
init_constants();
|
|
374
|
+
var CANONICAL_AGENT_NAMES = new Set(ALL_AGENT_NAMES);
|
|
375
|
+
var KNOWN_EMBEDDED_VARIANTS = new Set([
|
|
376
|
+
"low",
|
|
377
|
+
"medium",
|
|
378
|
+
"high",
|
|
379
|
+
"max",
|
|
380
|
+
"xhigh",
|
|
381
|
+
"thinking"
|
|
382
|
+
]);
|
|
383
|
+
|
|
370
384
|
// src/agents/index.ts
|
|
371
385
|
init_constants();
|
|
372
386
|
init_schema();
|
|
@@ -4900,71 +4914,6 @@ import * as path20 from "path";
|
|
|
4900
4914
|
init_agent_names();
|
|
4901
4915
|
init_schema();
|
|
4902
4916
|
|
|
4903
|
-
// src/turbo/epic/cochange-conflict.ts
|
|
4904
|
-
function pathMatches(scopePath, cochangePath) {
|
|
4905
|
-
if (scopePath === cochangePath)
|
|
4906
|
-
return true;
|
|
4907
|
-
return scopePath.endsWith(`/${cochangePath}`);
|
|
4908
|
-
}
|
|
4909
|
-
function epicPairConflict(scopeA, scopeB, cochangePairs, threshold) {
|
|
4910
|
-
const normA = scopeA.map(normalizePath);
|
|
4911
|
-
const normB = scopeB.map(normalizePath);
|
|
4912
|
-
const pathPairs = [];
|
|
4913
|
-
for (const a of normA) {
|
|
4914
|
-
for (const b of normB) {
|
|
4915
|
-
if (pathsConflict(a, b)) {
|
|
4916
|
-
pathPairs.push([a, b]);
|
|
4917
|
-
}
|
|
4918
|
-
}
|
|
4919
|
-
}
|
|
4920
|
-
const pathConflict = pathPairs.length > 0;
|
|
4921
|
-
const activePairs = cochangePairs.filter((e) => e.coChangeCount >= threshold.minCoChanges && e.npmi >= threshold.npmi);
|
|
4922
|
-
const cochangeMatches = [];
|
|
4923
|
-
for (const entry of activePairs) {
|
|
4924
|
-
const fa = entry.fileA;
|
|
4925
|
-
const fb = entry.fileB;
|
|
4926
|
-
const aTouchesFa = normA.some((p) => pathMatches(p, fa));
|
|
4927
|
-
const aTouchesFb = normA.some((p) => pathMatches(p, fb));
|
|
4928
|
-
const bTouchesFa = normB.some((p) => pathMatches(p, fa));
|
|
4929
|
-
const bTouchesFb = normB.some((p) => pathMatches(p, fb));
|
|
4930
|
-
const aExclusivelyFa = aTouchesFa && !aTouchesFb;
|
|
4931
|
-
const aExclusivelyFb = aTouchesFb && !aTouchesFa;
|
|
4932
|
-
const bExclusivelyFa = bTouchesFa && !bTouchesFb;
|
|
4933
|
-
const bExclusivelyFb = bTouchesFb && !bTouchesFa;
|
|
4934
|
-
const crossCouple = aExclusivelyFa && bExclusivelyFb || aExclusivelyFb && bExclusivelyFa;
|
|
4935
|
-
if (crossCouple) {
|
|
4936
|
-
cochangeMatches.push({
|
|
4937
|
-
a: fa,
|
|
4938
|
-
b: fb,
|
|
4939
|
-
npmi: entry.npmi,
|
|
4940
|
-
coChangeCount: entry.coChangeCount
|
|
4941
|
-
});
|
|
4942
|
-
}
|
|
4943
|
-
}
|
|
4944
|
-
const cochangeConflict = cochangeMatches.length > 0;
|
|
4945
|
-
let reason;
|
|
4946
|
-
if (pathConflict && cochangeConflict)
|
|
4947
|
-
reason = "both";
|
|
4948
|
-
else if (pathConflict)
|
|
4949
|
-
reason = "path";
|
|
4950
|
-
else if (cochangeConflict)
|
|
4951
|
-
reason = "cochange";
|
|
4952
|
-
else
|
|
4953
|
-
reason = "none";
|
|
4954
|
-
return {
|
|
4955
|
-
conflict: pathConflict || cochangeConflict,
|
|
4956
|
-
reason,
|
|
4957
|
-
evidence: { pathPairs, cochangePairs: cochangeMatches }
|
|
4958
|
-
};
|
|
4959
|
-
}
|
|
4960
|
-
|
|
4961
|
-
// src/state.ts
|
|
4962
|
-
init_constants();
|
|
4963
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
4964
|
-
import * as fs2 from "fs/promises";
|
|
4965
|
-
import * as path7 from "path";
|
|
4966
|
-
init_schema();
|
|
4967
|
-
|
|
4968
4917
|
// src/db/qa-gate-profile.ts
|
|
4969
4918
|
import { createHash as createHash3 } from "crypto";
|
|
4970
4919
|
|
|
@@ -5067,7 +5016,8 @@ var _internals5 = {
|
|
|
5067
5016
|
setGates,
|
|
5068
5017
|
getEffectiveGates,
|
|
5069
5018
|
computeProfileHash,
|
|
5070
|
-
hasAnyProfileWithEnabledGate
|
|
5019
|
+
hasAnyProfileWithEnabledGate,
|
|
5020
|
+
afterSetGatesRead: () => {}
|
|
5071
5021
|
};
|
|
5072
5022
|
var DEFAULT_QA_GATES = {
|
|
5073
5023
|
reviewer: true,
|
|
@@ -5082,6 +5032,7 @@ var DEFAULT_QA_GATES = {
|
|
|
5082
5032
|
drift_check: true,
|
|
5083
5033
|
final_council: false
|
|
5084
5034
|
};
|
|
5035
|
+
var qaGateProfileSavepointCounter = 0;
|
|
5085
5036
|
function rowToProfile(row) {
|
|
5086
5037
|
let parsed = {};
|
|
5087
5038
|
try {
|
|
@@ -5100,7 +5051,7 @@ function rowToProfile(row) {
|
|
|
5100
5051
|
const knownKeys = new Set(Object.keys(DEFAULT_QA_GATES));
|
|
5101
5052
|
const filteredParsed = {};
|
|
5102
5053
|
for (const key of Object.keys(parsed)) {
|
|
5103
|
-
if (knownKeys.has(key)) {
|
|
5054
|
+
if (knownKeys.has(key) && typeof parsed[key] === "boolean") {
|
|
5104
5055
|
filteredParsed[key] = parsed[key];
|
|
5105
5056
|
}
|
|
5106
5057
|
}
|
|
@@ -5136,12 +5087,18 @@ function hasAnyProfileWithEnabledGate(directory, gate) {
|
|
|
5136
5087
|
}
|
|
5137
5088
|
return false;
|
|
5138
5089
|
}
|
|
5139
|
-
function getOrCreateProfile(directory, planId, projectType) {
|
|
5090
|
+
function getOrCreateProfile(directory, planId, projectType, initialGates = {}) {
|
|
5140
5091
|
const existing = _internals5.getProfile(directory, planId);
|
|
5141
5092
|
if (existing)
|
|
5142
5093
|
return existing;
|
|
5143
5094
|
const db = getProjectDb(directory);
|
|
5144
|
-
const
|
|
5095
|
+
const seededGates = { ...DEFAULT_QA_GATES };
|
|
5096
|
+
for (const key of Object.keys(DEFAULT_QA_GATES)) {
|
|
5097
|
+
if (typeof initialGates[key] === "boolean") {
|
|
5098
|
+
seededGates[key] = initialGates[key];
|
|
5099
|
+
}
|
|
5100
|
+
}
|
|
5101
|
+
const gatesJson = JSON.stringify(seededGates);
|
|
5145
5102
|
const insert = db.transaction(() => {
|
|
5146
5103
|
db.run("INSERT INTO qa_gate_profile (plan_id, project_type, gates) VALUES (?, ?, ?)", [planId, projectType ?? null, gatesJson]);
|
|
5147
5104
|
});
|
|
@@ -5160,35 +5117,51 @@ function getOrCreateProfile(directory, planId, projectType) {
|
|
|
5160
5117
|
return after;
|
|
5161
5118
|
}
|
|
5162
5119
|
function setGates(directory, planId, gates) {
|
|
5163
|
-
const
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
}
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
const
|
|
5173
|
-
if (
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5120
|
+
const db = getProjectDb(directory);
|
|
5121
|
+
const savepointName = `qa_gate_profile_set_${qaGateProfileSavepointCounter++}`;
|
|
5122
|
+
const startedTransaction = !db.inTransaction;
|
|
5123
|
+
db.run(startedTransaction ? "BEGIN IMMEDIATE" : `SAVEPOINT ${savepointName}`);
|
|
5124
|
+
try {
|
|
5125
|
+
const currentRow = db.query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId);
|
|
5126
|
+
if (!currentRow) {
|
|
5127
|
+
throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
|
|
5128
|
+
}
|
|
5129
|
+
const current = rowToProfile(currentRow);
|
|
5130
|
+
if (current.locked_at !== null) {
|
|
5131
|
+
throw new Error("Cannot modify gates: QA gate profile is locked after critic approval");
|
|
5132
|
+
}
|
|
5133
|
+
_internals5.afterSetGatesRead(current);
|
|
5134
|
+
const merged = { ...current.gates };
|
|
5135
|
+
for (const key of Object.keys(gates)) {
|
|
5136
|
+
const incoming = gates[key];
|
|
5137
|
+
if (incoming === undefined)
|
|
5138
|
+
continue;
|
|
5139
|
+
if (incoming === false && current.gates[key] === true) {
|
|
5140
|
+
throw new Error(`Cannot disable gate '${key}': sessions can only ratchet tighter`);
|
|
5141
|
+
}
|
|
5142
|
+
if (incoming === true) {
|
|
5143
|
+
merged[key] = true;
|
|
5144
|
+
}
|
|
5177
5145
|
}
|
|
5178
|
-
|
|
5179
|
-
merged
|
|
5146
|
+
db.run("UPDATE qa_gate_profile SET gates = ? WHERE plan_id = ?", [
|
|
5147
|
+
JSON.stringify(merged),
|
|
5148
|
+
planId
|
|
5149
|
+
]);
|
|
5150
|
+
const updatedRow = db.query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId);
|
|
5151
|
+
if (!updatedRow) {
|
|
5152
|
+
throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
|
|
5180
5153
|
}
|
|
5154
|
+
db.run(startedTransaction ? "COMMIT" : `RELEASE ${savepointName}`);
|
|
5155
|
+
return rowToProfile(updatedRow);
|
|
5156
|
+
} catch (err) {
|
|
5157
|
+
try {
|
|
5158
|
+
db.run(startedTransaction ? "ROLLBACK" : `ROLLBACK TO ${savepointName}`);
|
|
5159
|
+
if (!startedTransaction) {
|
|
5160
|
+
db.run(`RELEASE ${savepointName}`);
|
|
5161
|
+
}
|
|
5162
|
+
} catch {}
|
|
5163
|
+
throw err;
|
|
5181
5164
|
}
|
|
5182
|
-
const db = getProjectDb(directory);
|
|
5183
|
-
db.run("UPDATE qa_gate_profile SET gates = ? WHERE plan_id = ?", [
|
|
5184
|
-
JSON.stringify(merged),
|
|
5185
|
-
planId
|
|
5186
|
-
]);
|
|
5187
|
-
const updated = _internals5.getProfile(directory, planId);
|
|
5188
|
-
if (!updated) {
|
|
5189
|
-
throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
|
|
5190
|
-
}
|
|
5191
|
-
return updated;
|
|
5192
5165
|
}
|
|
5193
5166
|
function computeProfileHash(profile) {
|
|
5194
5167
|
const payload = JSON.stringify({
|
|
@@ -5207,6 +5180,71 @@ function getEffectiveGates(profile, sessionOverrides) {
|
|
|
5207
5180
|
return merged;
|
|
5208
5181
|
}
|
|
5209
5182
|
|
|
5183
|
+
// src/turbo/epic/cochange-conflict.ts
|
|
5184
|
+
function pathMatches(scopePath, cochangePath) {
|
|
5185
|
+
if (scopePath === cochangePath)
|
|
5186
|
+
return true;
|
|
5187
|
+
return scopePath.endsWith(`/${cochangePath}`);
|
|
5188
|
+
}
|
|
5189
|
+
function epicPairConflict(scopeA, scopeB, cochangePairs, threshold) {
|
|
5190
|
+
const normA = scopeA.map(normalizePath);
|
|
5191
|
+
const normB = scopeB.map(normalizePath);
|
|
5192
|
+
const pathPairs = [];
|
|
5193
|
+
for (const a of normA) {
|
|
5194
|
+
for (const b of normB) {
|
|
5195
|
+
if (pathsConflict(a, b)) {
|
|
5196
|
+
pathPairs.push([a, b]);
|
|
5197
|
+
}
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
const pathConflict = pathPairs.length > 0;
|
|
5201
|
+
const activePairs = cochangePairs.filter((e) => e.coChangeCount >= threshold.minCoChanges && e.npmi >= threshold.npmi);
|
|
5202
|
+
const cochangeMatches = [];
|
|
5203
|
+
for (const entry of activePairs) {
|
|
5204
|
+
const fa = entry.fileA;
|
|
5205
|
+
const fb = entry.fileB;
|
|
5206
|
+
const aTouchesFa = normA.some((p) => pathMatches(p, fa));
|
|
5207
|
+
const aTouchesFb = normA.some((p) => pathMatches(p, fb));
|
|
5208
|
+
const bTouchesFa = normB.some((p) => pathMatches(p, fa));
|
|
5209
|
+
const bTouchesFb = normB.some((p) => pathMatches(p, fb));
|
|
5210
|
+
const aExclusivelyFa = aTouchesFa && !aTouchesFb;
|
|
5211
|
+
const aExclusivelyFb = aTouchesFb && !aTouchesFa;
|
|
5212
|
+
const bExclusivelyFa = bTouchesFa && !bTouchesFb;
|
|
5213
|
+
const bExclusivelyFb = bTouchesFb && !bTouchesFa;
|
|
5214
|
+
const crossCouple = aExclusivelyFa && bExclusivelyFb || aExclusivelyFb && bExclusivelyFa;
|
|
5215
|
+
if (crossCouple) {
|
|
5216
|
+
cochangeMatches.push({
|
|
5217
|
+
a: fa,
|
|
5218
|
+
b: fb,
|
|
5219
|
+
npmi: entry.npmi,
|
|
5220
|
+
coChangeCount: entry.coChangeCount
|
|
5221
|
+
});
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
5224
|
+
const cochangeConflict = cochangeMatches.length > 0;
|
|
5225
|
+
let reason;
|
|
5226
|
+
if (pathConflict && cochangeConflict)
|
|
5227
|
+
reason = "both";
|
|
5228
|
+
else if (pathConflict)
|
|
5229
|
+
reason = "path";
|
|
5230
|
+
else if (cochangeConflict)
|
|
5231
|
+
reason = "cochange";
|
|
5232
|
+
else
|
|
5233
|
+
reason = "none";
|
|
5234
|
+
return {
|
|
5235
|
+
conflict: pathConflict || cochangeConflict,
|
|
5236
|
+
reason,
|
|
5237
|
+
evidence: { pathPairs, cochangePairs: cochangeMatches }
|
|
5238
|
+
};
|
|
5239
|
+
}
|
|
5240
|
+
|
|
5241
|
+
// src/state.ts
|
|
5242
|
+
init_constants();
|
|
5243
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
5244
|
+
import * as fs2 from "fs/promises";
|
|
5245
|
+
import * as path7 from "path";
|
|
5246
|
+
init_schema();
|
|
5247
|
+
|
|
5210
5248
|
// src/hooks/realtime-learning-nudge.ts
|
|
5211
5249
|
var realtimeLearningNudgeBySession = new Map;
|
|
5212
5250
|
function resetRealtimeLearningNudgeState() {
|
|
@@ -5686,8 +5724,7 @@ var swarmState = {
|
|
|
5686
5724
|
knowledgeAckDedup: new Set,
|
|
5687
5725
|
gateDenialCounts: new Map,
|
|
5688
5726
|
generatedAgentNames: [],
|
|
5689
|
-
|
|
5690
|
-
lastBudgetTokens: 0,
|
|
5727
|
+
lastBudgetBySession: new Map,
|
|
5691
5728
|
liveContextWindows: new Map,
|
|
5692
5729
|
agentSessions: defaultRunContext.agentSessions,
|
|
5693
5730
|
pendingRehydrations: new Set,
|
|
@@ -5700,8 +5737,7 @@ function resetSwarmState() {
|
|
|
5700
5737
|
swarmState.activeAgent.clear();
|
|
5701
5738
|
swarmState.delegationChains.clear();
|
|
5702
5739
|
swarmState.pendingEvents = 0;
|
|
5703
|
-
swarmState.
|
|
5704
|
-
swarmState.lastBudgetTokens = 0;
|
|
5740
|
+
swarmState.lastBudgetBySession.clear();
|
|
5705
5741
|
swarmState.liveContextWindows.clear();
|
|
5706
5742
|
swarmState.agentSessions.clear();
|
|
5707
5743
|
_lastIdleSweepAtMs = 0;
|
|
@@ -6530,10 +6566,19 @@ function hasActiveEpicMode(sessionID) {
|
|
|
6530
6566
|
}
|
|
6531
6567
|
return false;
|
|
6532
6568
|
}
|
|
6569
|
+
function getDisplayBudget() {
|
|
6570
|
+
let best = null;
|
|
6571
|
+
for (const entry of swarmState.lastBudgetBySession.values()) {
|
|
6572
|
+
if (entry.pct > 0 && (best === null || entry.pct > best.pct)) {
|
|
6573
|
+
best = entry;
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
return best;
|
|
6577
|
+
}
|
|
6533
6578
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
6534
6579
|
const map = new Map;
|
|
6535
6580
|
try {
|
|
6536
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
6581
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-qdwfm1a8.js");
|
|
6537
6582
|
const records = await listActive2(directory);
|
|
6538
6583
|
for (const record of records) {
|
|
6539
6584
|
if (record.sessionID !== sessionID)
|
|
@@ -18989,7 +19034,7 @@ function planMerges(active, threshold, maxComparisons, maxMerges) {
|
|
|
18989
19034
|
};
|
|
18990
19035
|
}
|
|
18991
19036
|
async function sweepActiveNearDuplicates(directory, options = {}) {
|
|
18992
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
19037
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
18993
19038
|
const { config } = loadPluginConfigWithMeta2(directory);
|
|
18994
19039
|
const sweepConfig = config.learning?.dedup_sweep;
|
|
18995
19040
|
if (sweepConfig?.enabled === false)
|
|
@@ -20584,7 +20629,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20584
20629
|
}
|
|
20585
20630
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
20586
20631
|
try {
|
|
20587
|
-
const skillModule = await import("./skill-generator-
|
|
20632
|
+
const skillModule = await import("./skill-generator-2rv6ftre.js");
|
|
20588
20633
|
for (const cand of skillCandidates) {
|
|
20589
20634
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
20590
20635
|
continue;
|
|
@@ -21044,7 +21089,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
21044
21089
|
} catch {}
|
|
21045
21090
|
}
|
|
21046
21091
|
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
21047
|
-
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-
|
|
21092
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-kkjsjtza.js");
|
|
21048
21093
|
for (const { id } of contradictedEntries) {
|
|
21049
21094
|
try {
|
|
21050
21095
|
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
@@ -21863,7 +21908,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
21863
21908
|
warnings.push("Failed to collect knowledge summary.");
|
|
21864
21909
|
}
|
|
21865
21910
|
try {
|
|
21866
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
21911
|
+
const { getScanStatus } = await import("./scan-cursor-8e6ryhjq.js");
|
|
21867
21912
|
const scanStatus = await getScanStatus(directory);
|
|
21868
21913
|
if (scanStatus.remaining_estimate > 0) {
|
|
21869
21914
|
warnings.push(`Fair scan: reviewed ${knowledgeSummary.length} entries this sweep (generation ${scanStatus.generation}); ${scanStatus.remaining_estimate} more eligible entries will be visited in future curation sweeps.`);
|
|
@@ -22035,9 +22080,9 @@ var _internals24 = {
|
|
|
22035
22080
|
verifyPostMortemKnowledgeActions,
|
|
22036
22081
|
repairPostMortemActions,
|
|
22037
22082
|
loadDefaultKnowledgeConfig: async (directory) => {
|
|
22038
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
22083
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
22039
22084
|
try {
|
|
22040
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
22085
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
22041
22086
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
22042
22087
|
return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
22043
22088
|
} catch {
|
|
@@ -22045,11 +22090,11 @@ var _internals24 = {
|
|
|
22045
22090
|
}
|
|
22046
22091
|
},
|
|
22047
22092
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
|
|
22048
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
22093
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-m6mk2v1n.js");
|
|
22049
22094
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
|
|
22050
22095
|
},
|
|
22051
22096
|
checkHivePromotions: async (entries, knowledgeConfig, directory) => {
|
|
22052
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
22097
|
+
const { checkHivePromotions } = await import("./hive-promoter-v4w7cjvk.js");
|
|
22053
22098
|
return checkHivePromotions(entries, knowledgeConfig, directory);
|
|
22054
22099
|
},
|
|
22055
22100
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -22058,7 +22103,7 @@ var _internals24 = {
|
|
|
22058
22103
|
activateProposal,
|
|
22059
22104
|
listSkills: listSkills2,
|
|
22060
22105
|
sanitizeSlug
|
|
22061
|
-
} = await import("./skill-generator-
|
|
22106
|
+
} = await import("./skill-generator-2rv6ftre.js");
|
|
22062
22107
|
const result = {
|
|
22063
22108
|
approved: [],
|
|
22064
22109
|
rejected: [],
|
|
@@ -22100,7 +22145,7 @@ var _internals24 = {
|
|
|
22100
22145
|
return result;
|
|
22101
22146
|
},
|
|
22102
22147
|
readPriorDriftReports: async (directory) => {
|
|
22103
|
-
const { readPriorDriftReports } = await import("./curator-drift-
|
|
22148
|
+
const { readPriorDriftReports } = await import("./curator-drift-r52hjskk.js");
|
|
22104
22149
|
return readPriorDriftReports(directory);
|
|
22105
22150
|
},
|
|
22106
22151
|
readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
|
|
@@ -24686,9 +24731,9 @@ function hashContent(content) {
|
|
|
24686
24731
|
return createHash9("sha1").update(content).digest("hex");
|
|
24687
24732
|
}
|
|
24688
24733
|
async function loadConfigForPolicyCurator(directory) {
|
|
24689
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
24734
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
24690
24735
|
try {
|
|
24691
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
24736
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
24692
24737
|
const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
|
|
24693
24738
|
return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
|
|
24694
24739
|
} catch {
|
|
@@ -28697,7 +28742,7 @@ async function runFinalizeStage(ctx) {
|
|
|
28697
28742
|
}
|
|
28698
28743
|
}
|
|
28699
28744
|
try {
|
|
28700
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
28745
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-g7rs20c6.js");
|
|
28701
28746
|
const { config: pmLoadedConfig } = _internals37.loadPluginConfigWithMeta(ctx.directory);
|
|
28702
28747
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
28703
28748
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -30970,9 +31015,9 @@ var _internals42 = {
|
|
|
30970
31015
|
loadPluginConfigWithMeta,
|
|
30971
31016
|
loadCuratorDeps: async () => {
|
|
30972
31017
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
30973
|
-
import("./schema-
|
|
30974
|
-
import("./curator-
|
|
30975
|
-
import("./curator-llm-factory-
|
|
31018
|
+
import("./schema-g7rs20c6.js"),
|
|
31019
|
+
import("./curator-m6mk2v1n.js"),
|
|
31020
|
+
import("./curator-llm-factory-1r9vz0g2.js")
|
|
30976
31021
|
]);
|
|
30977
31022
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
30978
31023
|
}
|
|
@@ -31877,7 +31922,7 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
31877
31922
|
let scanCompleted = false;
|
|
31878
31923
|
let scanRemaining = 0;
|
|
31879
31924
|
try {
|
|
31880
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
31925
|
+
const { getScanStatus } = await import("./scan-cursor-8e6ryhjq.js");
|
|
31881
31926
|
const status = await getScanStatus(directory);
|
|
31882
31927
|
scanGeneration = status.generation;
|
|
31883
31928
|
scanCompleted = status.completed;
|
|
@@ -31885,19 +31930,19 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
31885
31930
|
} catch {}
|
|
31886
31931
|
let configMatch = null;
|
|
31887
31932
|
try {
|
|
31888
|
-
const { isLinked: isLinked2 } = await import("./knowledge-link-
|
|
31933
|
+
const { isLinked: isLinked2 } = await import("./knowledge-link-f6akgbdn.js");
|
|
31889
31934
|
if (isLinked2(directory)) {
|
|
31890
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
31935
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
31891
31936
|
let config;
|
|
31892
31937
|
try {
|
|
31893
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
31938
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
31894
31939
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
31895
31940
|
config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
31896
31941
|
} catch {
|
|
31897
31942
|
config = KnowledgeConfigSchema2.parse({});
|
|
31898
31943
|
}
|
|
31899
31944
|
const { cohortConfigFingerprint: cohortConfigFingerprint2 } = await import("./config-fingerprint-v22xh5a2.js");
|
|
31900
|
-
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-
|
|
31945
|
+
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-f46tf3dw.js");
|
|
31901
31946
|
const currentFp = cohortConfigFingerprint2(buildConfigFingerprintInput2(config));
|
|
31902
31947
|
const cohortFp = await readCohortConfigFingerprint(directory);
|
|
31903
31948
|
configMatch = cohortFp === null ? null : currentFp === cohortFp;
|
|
@@ -33108,7 +33153,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
33108
33153
|
const result = runConfigDoctor(config, directory);
|
|
33109
33154
|
let output;
|
|
33110
33155
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
33111
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
33156
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-75qky762.js");
|
|
33112
33157
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true, {
|
|
33113
33158
|
applyLossy: true
|
|
33114
33159
|
});
|
|
@@ -33945,7 +33990,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
33945
33990
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
33946
33991
|
}
|
|
33947
33992
|
async function handleEvidenceSummaryCommand(directory) {
|
|
33948
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
33993
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-sxcq5nrt.js");
|
|
33949
33994
|
const artifact = await buildEvidenceSummary(directory);
|
|
33950
33995
|
if (!artifact) {
|
|
33951
33996
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -35621,7 +35666,8 @@ function validateInput(input) {
|
|
|
35621
35666
|
}
|
|
35622
35667
|
return { valid: true };
|
|
35623
35668
|
}
|
|
35624
|
-
async function qualityBudget(input, directory) {
|
|
35669
|
+
async function qualityBudget(input, directory, abortSignal) {
|
|
35670
|
+
abortSignal?.throwIfAborted();
|
|
35625
35671
|
const validation = validateInput(input);
|
|
35626
35672
|
if (!validation.valid) {
|
|
35627
35673
|
throw new Error(`Invalid input: ${validation.error}`);
|
|
@@ -35661,10 +35707,12 @@ async function qualityBudget(input, directory) {
|
|
|
35661
35707
|
}
|
|
35662
35708
|
};
|
|
35663
35709
|
}
|
|
35664
|
-
const metrics = await computeQualityMetrics(changedFiles, thresholds, directory);
|
|
35710
|
+
const metrics = await _internals49.computeQualityMetrics(changedFiles, thresholds, directory);
|
|
35711
|
+
abortSignal?.throwIfAborted();
|
|
35665
35712
|
const errorsCount = metrics.violations.filter((v) => v.severity === "error").length;
|
|
35666
35713
|
const warningsCount = metrics.violations.filter((v) => v.severity === "warning").length;
|
|
35667
35714
|
const verdict = errorsCount > 0 ? "fail" : "pass";
|
|
35715
|
+
abortSignal?.throwIfAborted();
|
|
35668
35716
|
await saveEvidence(directory, "quality_budget", {
|
|
35669
35717
|
task_id: "quality_budget",
|
|
35670
35718
|
type: "quality_budget",
|
|
@@ -35691,7 +35739,8 @@ async function qualityBudget(input, directory) {
|
|
|
35691
35739
|
files: v.files
|
|
35692
35740
|
})),
|
|
35693
35741
|
files_analyzed: metrics.files_analyzed
|
|
35694
|
-
});
|
|
35742
|
+
}, abortSignal);
|
|
35743
|
+
abortSignal?.throwIfAborted();
|
|
35695
35744
|
return {
|
|
35696
35745
|
verdict,
|
|
35697
35746
|
metrics,
|
|
@@ -35718,13 +35767,14 @@ var quality_budget = createSwarmTool({
|
|
|
35718
35767
|
exclude_globs: exports_external.array(exports_external.string()).optional()
|
|
35719
35768
|
}).optional().describe("Quality budget thresholds")
|
|
35720
35769
|
},
|
|
35721
|
-
async execute(args, directory) {
|
|
35722
|
-
const result = await _internals49.qualityBudget(args, directory);
|
|
35770
|
+
async execute(args, directory, ctx) {
|
|
35771
|
+
const result = await _internals49.qualityBudget(args, directory, ctx?.abort);
|
|
35723
35772
|
return JSON.stringify(result);
|
|
35724
35773
|
}
|
|
35725
35774
|
});
|
|
35726
35775
|
var _internals49 = {
|
|
35727
|
-
qualityBudget
|
|
35776
|
+
qualityBudget,
|
|
35777
|
+
computeQualityMetrics
|
|
35728
35778
|
};
|
|
35729
35779
|
|
|
35730
35780
|
// src/tools/sast-scan.ts
|
|
@@ -36583,15 +36633,75 @@ function executeRulesSync(filePath, content, language) {
|
|
|
36583
36633
|
}
|
|
36584
36634
|
|
|
36585
36635
|
// src/sast/semgrep.ts
|
|
36586
|
-
init_logger();
|
|
36587
|
-
import * as child_process6 from "child_process";
|
|
36588
36636
|
import * as fs24 from "fs";
|
|
36589
36637
|
import * as path61 from "path";
|
|
36590
36638
|
var semgrepAvailableCache = null;
|
|
36639
|
+
var semgrepAvailabilityProbe = null;
|
|
36640
|
+
var semgrepAvailabilityGeneration = 0;
|
|
36591
36641
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
36592
36642
|
var DEFAULT_TIMEOUT_MS2 = 30000;
|
|
36643
|
+
var SEMGREP_AVAILABILITY_TIMEOUT_MS = 5000;
|
|
36644
|
+
var SEMGREP_AVAILABILITY_MAX_STDOUT_BYTES = 16 * 1024;
|
|
36645
|
+
var SEMGREP_AVAILABILITY_MAX_STDERR_BYTES = 16 * 1024;
|
|
36593
36646
|
var MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
|
|
36594
|
-
|
|
36647
|
+
function resolveSemgrepBinary() {
|
|
36648
|
+
return _internals50.resolveExecutableFromPath(process.platform === "win32" ? ["semgrep.exe"] : ["semgrep"]);
|
|
36649
|
+
}
|
|
36650
|
+
function getAvailabilityProbeCwd() {
|
|
36651
|
+
try {
|
|
36652
|
+
return fs24.realpathSync(process.cwd());
|
|
36653
|
+
} catch {
|
|
36654
|
+
return path61.resolve(process.cwd());
|
|
36655
|
+
}
|
|
36656
|
+
}
|
|
36657
|
+
async function runSemgrepAvailabilityProbe(executable, cwd, generation) {
|
|
36658
|
+
try {
|
|
36659
|
+
const run = await _internals50.runExternalTool({
|
|
36660
|
+
executable,
|
|
36661
|
+
args: ["--version"],
|
|
36662
|
+
cwd,
|
|
36663
|
+
timeoutMs: SEMGREP_AVAILABILITY_TIMEOUT_MS,
|
|
36664
|
+
maxStdoutBytes: SEMGREP_AVAILABILITY_MAX_STDOUT_BYTES,
|
|
36665
|
+
maxStderrBytes: SEMGREP_AVAILABILITY_MAX_STDERR_BYTES
|
|
36666
|
+
});
|
|
36667
|
+
const available = run.status === "completed" && run.exitCode === 0 && !run.stdoutTruncated && !run.stderrTruncated;
|
|
36668
|
+
if (available && generation === semgrepAvailabilityGeneration) {
|
|
36669
|
+
semgrepAvailableCache = true;
|
|
36670
|
+
}
|
|
36671
|
+
return available;
|
|
36672
|
+
} catch {
|
|
36673
|
+
return false;
|
|
36674
|
+
}
|
|
36675
|
+
}
|
|
36676
|
+
async function waitForAvailabilityProbe(probe, abortSignal) {
|
|
36677
|
+
if (!abortSignal)
|
|
36678
|
+
return probe;
|
|
36679
|
+
if (abortSignal.aborted)
|
|
36680
|
+
return false;
|
|
36681
|
+
return new Promise((resolve18) => {
|
|
36682
|
+
let settled = false;
|
|
36683
|
+
const finish = (available) => {
|
|
36684
|
+
if (settled)
|
|
36685
|
+
return;
|
|
36686
|
+
settled = true;
|
|
36687
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
36688
|
+
resolve18(available);
|
|
36689
|
+
};
|
|
36690
|
+
const onAbort = () => finish(false);
|
|
36691
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
36692
|
+
probe.then(finish, () => finish(false));
|
|
36693
|
+
});
|
|
36694
|
+
}
|
|
36695
|
+
function describeExternalToolFailure(status) {
|
|
36696
|
+
switch (status) {
|
|
36697
|
+
case "timeout":
|
|
36698
|
+
return "Semgrep process timed out";
|
|
36699
|
+
case "cancelled":
|
|
36700
|
+
return "Semgrep execution cancelled";
|
|
36701
|
+
case "spawn-error":
|
|
36702
|
+
return "Semgrep process failed to start or terminate safely";
|
|
36703
|
+
}
|
|
36704
|
+
}
|
|
36595
36705
|
var _internals50 = {
|
|
36596
36706
|
isSemgrepAvailable,
|
|
36597
36707
|
checkSemgrepAvailable,
|
|
@@ -36599,60 +36709,117 @@ var _internals50 = {
|
|
|
36599
36709
|
runSemgrep,
|
|
36600
36710
|
getRulesDirectory,
|
|
36601
36711
|
hasBundledRules,
|
|
36602
|
-
|
|
36712
|
+
resolveExecutableFromPath,
|
|
36713
|
+
resolveSemgrepBinary,
|
|
36714
|
+
runExternalTool,
|
|
36715
|
+
getAvailabilityProbeCwd
|
|
36603
36716
|
};
|
|
36604
36717
|
function isSemgrepAvailable() {
|
|
36605
36718
|
if (semgrepAvailableCache !== null) {
|
|
36606
36719
|
return semgrepAvailableCache;
|
|
36607
36720
|
}
|
|
36608
|
-
|
|
36609
|
-
|
|
36610
|
-
|
|
36611
|
-
|
|
36612
|
-
|
|
36613
|
-
|
|
36614
|
-
return
|
|
36615
|
-
}
|
|
36721
|
+
return _internals50.resolveSemgrepBinary() !== null;
|
|
36722
|
+
}
|
|
36723
|
+
async function checkSemgrepAvailable(cwd, abortSignal) {
|
|
36724
|
+
if (abortSignal?.aborted)
|
|
36725
|
+
return false;
|
|
36726
|
+
if (semgrepAvailableCache !== null) {
|
|
36727
|
+
return semgrepAvailableCache;
|
|
36728
|
+
}
|
|
36729
|
+
const executable = _internals50.resolveSemgrepBinary();
|
|
36730
|
+
if (!executable) {
|
|
36616
36731
|
semgrepAvailableCache = false;
|
|
36617
36732
|
return false;
|
|
36618
36733
|
}
|
|
36619
|
-
|
|
36620
|
-
|
|
36621
|
-
|
|
36734
|
+
if (!semgrepAvailabilityProbe) {
|
|
36735
|
+
const generation = semgrepAvailabilityGeneration;
|
|
36736
|
+
const probe = runSemgrepAvailabilityProbe(executable, cwd ?? _internals50.getAvailabilityProbeCwd(), generation);
|
|
36737
|
+
semgrepAvailabilityProbe = probe;
|
|
36738
|
+
probe.then(() => {
|
|
36739
|
+
if (semgrepAvailabilityProbe === probe) {
|
|
36740
|
+
semgrepAvailabilityProbe = null;
|
|
36741
|
+
}
|
|
36742
|
+
}, () => {
|
|
36743
|
+
if (semgrepAvailabilityProbe === probe) {
|
|
36744
|
+
semgrepAvailabilityProbe = null;
|
|
36745
|
+
}
|
|
36746
|
+
});
|
|
36747
|
+
}
|
|
36748
|
+
return waitForAvailabilityProbe(semgrepAvailabilityProbe, abortSignal);
|
|
36622
36749
|
}
|
|
36623
36750
|
function resetSemgrepCache() {
|
|
36751
|
+
semgrepAvailabilityGeneration++;
|
|
36624
36752
|
semgrepAvailableCache = null;
|
|
36753
|
+
semgrepAvailabilityProbe = null;
|
|
36625
36754
|
}
|
|
36626
36755
|
function parseSemgrepResults(semgrepOutput) {
|
|
36627
36756
|
const findings = [];
|
|
36628
36757
|
try {
|
|
36629
36758
|
const parsed = JSON.parse(semgrepOutput);
|
|
36630
|
-
|
|
36631
|
-
if (
|
|
36632
|
-
|
|
36759
|
+
let results;
|
|
36760
|
+
if (Array.isArray(parsed)) {
|
|
36761
|
+
results = parsed;
|
|
36762
|
+
} else if (parsed && typeof parsed === "object") {
|
|
36763
|
+
const output = parsed;
|
|
36764
|
+
if (output.errors !== undefined && !Array.isArray(output.errors)) {
|
|
36765
|
+
throw new Error("invalid Semgrep errors shape");
|
|
36766
|
+
}
|
|
36767
|
+
if (Array.isArray(output.errors) && output.errors.length > 0) {
|
|
36768
|
+
throw new SemgrepScanError(`Semgrep reported ${output.errors.length} scan error${output.errors.length === 1 ? "" : "s"}`);
|
|
36769
|
+
}
|
|
36770
|
+
results = output.results;
|
|
36633
36771
|
}
|
|
36772
|
+
if (!Array.isArray(results))
|
|
36773
|
+
throw new Error("invalid Semgrep result shape");
|
|
36634
36774
|
for (const result of results) {
|
|
36635
|
-
if (!result || typeof result !== "object")
|
|
36636
|
-
|
|
36637
|
-
|
|
36775
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) {
|
|
36776
|
+
throw new Error("invalid Semgrep result entry");
|
|
36777
|
+
}
|
|
36778
|
+
const entry = result;
|
|
36779
|
+
const extra = entry.extra && typeof entry.extra === "object" && !Array.isArray(entry.extra) ? entry.extra : null;
|
|
36780
|
+
const start = entry.start && typeof entry.start === "object" && !Array.isArray(entry.start) ? entry.start : null;
|
|
36781
|
+
const ruleId = entry.check_id ?? entry.rule_id;
|
|
36782
|
+
const file = entry.path ?? start?.filename ?? entry.file;
|
|
36783
|
+
const line = start?.line ?? entry.line;
|
|
36784
|
+
const column = start?.col ?? entry.column;
|
|
36785
|
+
const severityValue = extra?.severity ?? entry.severity;
|
|
36786
|
+
const message = extra?.message ?? entry.message;
|
|
36787
|
+
const knownSeverities = new Set([
|
|
36788
|
+
"error",
|
|
36789
|
+
"critical",
|
|
36790
|
+
"warning",
|
|
36791
|
+
"high",
|
|
36792
|
+
"medium",
|
|
36793
|
+
"info",
|
|
36794
|
+
"low"
|
|
36795
|
+
]);
|
|
36796
|
+
if (typeof ruleId !== "string" || ruleId.length === 0 || typeof file !== "string" || file.length === 0 || file.includes("\x00") || typeof line !== "number" || !Number.isInteger(line) || line < 1 || column !== undefined && (typeof column !== "number" || !Number.isInteger(column) || column < 1) || typeof severityValue !== "string" || !knownSeverities.has(severityValue.toLowerCase()) || message !== undefined && typeof message !== "string" || extra?.fix !== undefined && typeof extra.fix !== "string" || extra?.lines !== undefined && typeof extra.lines !== "string" || entry.lines !== undefined && typeof entry.lines !== "string") {
|
|
36797
|
+
throw new Error("invalid Semgrep result entry");
|
|
36798
|
+
}
|
|
36799
|
+
const severity = mapSemgrepSeverity(severityValue);
|
|
36638
36800
|
findings.push({
|
|
36639
|
-
rule_id:
|
|
36801
|
+
rule_id: ruleId,
|
|
36640
36802
|
severity,
|
|
36641
|
-
message:
|
|
36803
|
+
message: message ?? "Security issue detected",
|
|
36642
36804
|
location: {
|
|
36643
|
-
file
|
|
36644
|
-
line
|
|
36645
|
-
column
|
|
36805
|
+
file,
|
|
36806
|
+
line,
|
|
36807
|
+
column
|
|
36646
36808
|
},
|
|
36647
|
-
remediation:
|
|
36648
|
-
excerpt:
|
|
36809
|
+
remediation: extra?.fix,
|
|
36810
|
+
excerpt: extra?.lines ?? entry.lines ?? ""
|
|
36649
36811
|
});
|
|
36650
36812
|
}
|
|
36651
|
-
} catch {
|
|
36652
|
-
|
|
36813
|
+
} catch (error2) {
|
|
36814
|
+
if (error2 instanceof SemgrepScanError)
|
|
36815
|
+
throw error2;
|
|
36816
|
+
throw new Error("Semgrep returned invalid JSON output", { cause: error2 });
|
|
36653
36817
|
}
|
|
36654
36818
|
return findings;
|
|
36655
36819
|
}
|
|
36820
|
+
|
|
36821
|
+
class SemgrepScanError extends Error {
|
|
36822
|
+
}
|
|
36656
36823
|
function mapSemgrepSeverity(severity) {
|
|
36657
36824
|
const severityLower = (severity || "").toLowerCase();
|
|
36658
36825
|
switch (severityLower) {
|
|
@@ -36669,136 +36836,6 @@ function mapSemgrepSeverity(severity) {
|
|
|
36669
36836
|
return "medium";
|
|
36670
36837
|
}
|
|
36671
36838
|
}
|
|
36672
|
-
async function executeWithTimeout(command, args, options) {
|
|
36673
|
-
const maxOutputBytes = options.maxOutputBytes ?? MAX_OUTPUT_BYTES;
|
|
36674
|
-
return new Promise((resolve18) => {
|
|
36675
|
-
const child = child_process6.spawn(command, args, {
|
|
36676
|
-
shell: false,
|
|
36677
|
-
cwd: options.cwd,
|
|
36678
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
36679
|
-
});
|
|
36680
|
-
options.onSpawn?.(child.pid);
|
|
36681
|
-
let stdout = "";
|
|
36682
|
-
let stderr = "";
|
|
36683
|
-
let stdoutBytes = 0;
|
|
36684
|
-
let stderrBytes = 0;
|
|
36685
|
-
let stdoutTruncated = false;
|
|
36686
|
-
let stderrTruncated = false;
|
|
36687
|
-
let settled = false;
|
|
36688
|
-
let timeout;
|
|
36689
|
-
let escalation;
|
|
36690
|
-
const settle = (result) => {
|
|
36691
|
-
if (settled)
|
|
36692
|
-
return;
|
|
36693
|
-
settled = true;
|
|
36694
|
-
if (timeout)
|
|
36695
|
-
clearTimeout(timeout);
|
|
36696
|
-
if (escalation)
|
|
36697
|
-
clearTimeout(escalation);
|
|
36698
|
-
const truncated = stdoutTruncated || stderrTruncated;
|
|
36699
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
36700
|
-
try {
|
|
36701
|
-
child.kill("SIGTERM");
|
|
36702
|
-
} catch (e) {
|
|
36703
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36704
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36705
|
-
}
|
|
36706
|
-
}
|
|
36707
|
-
escalation = setTimeout(() => {
|
|
36708
|
-
try {
|
|
36709
|
-
child.kill("SIGKILL");
|
|
36710
|
-
} catch (e) {
|
|
36711
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36712
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36713
|
-
}
|
|
36714
|
-
}
|
|
36715
|
-
}, KILL_GRACE_MS);
|
|
36716
|
-
if (typeof escalation.unref === "function") {
|
|
36717
|
-
escalation.unref();
|
|
36718
|
-
}
|
|
36719
|
-
}
|
|
36720
|
-
resolve18({ ...result, truncated });
|
|
36721
|
-
};
|
|
36722
|
-
timeout = setTimeout(() => {
|
|
36723
|
-
settle({
|
|
36724
|
-
stdout,
|
|
36725
|
-
stderr: "Process timed out",
|
|
36726
|
-
exitCode: 124
|
|
36727
|
-
});
|
|
36728
|
-
}, options.timeoutMs);
|
|
36729
|
-
if (typeof timeout.unref === "function") {
|
|
36730
|
-
timeout.unref();
|
|
36731
|
-
}
|
|
36732
|
-
child.stdout?.on("data", (data) => {
|
|
36733
|
-
if (stdoutTruncated)
|
|
36734
|
-
return;
|
|
36735
|
-
const chunk = data.toString();
|
|
36736
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
36737
|
-
if (stdoutBytes + chunkBytes > maxOutputBytes) {
|
|
36738
|
-
const remaining = Math.max(0, maxOutputBytes - stdoutBytes);
|
|
36739
|
-
stdout += Buffer.from(chunk, "utf8").subarray(0, remaining).toString("utf8");
|
|
36740
|
-
stdoutBytes = maxOutputBytes;
|
|
36741
|
-
stdoutTruncated = true;
|
|
36742
|
-
settle({
|
|
36743
|
-
stdout,
|
|
36744
|
-
stderr,
|
|
36745
|
-
exitCode: -1
|
|
36746
|
-
});
|
|
36747
|
-
try {
|
|
36748
|
-
child.kill("SIGTERM");
|
|
36749
|
-
} catch (e) {
|
|
36750
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36751
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36752
|
-
}
|
|
36753
|
-
}
|
|
36754
|
-
} else {
|
|
36755
|
-
stdout += chunk;
|
|
36756
|
-
stdoutBytes += chunkBytes;
|
|
36757
|
-
}
|
|
36758
|
-
});
|
|
36759
|
-
child.stderr?.on("data", (data) => {
|
|
36760
|
-
if (stderrTruncated)
|
|
36761
|
-
return;
|
|
36762
|
-
const chunk = data.toString();
|
|
36763
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
36764
|
-
if (stderrBytes + chunkBytes > maxOutputBytes) {
|
|
36765
|
-
const remaining = Math.max(0, maxOutputBytes - stderrBytes);
|
|
36766
|
-
stderr += Buffer.from(chunk, "utf8").subarray(0, remaining).toString("utf8");
|
|
36767
|
-
stderrBytes = maxOutputBytes;
|
|
36768
|
-
stderrTruncated = true;
|
|
36769
|
-
settle({
|
|
36770
|
-
stdout,
|
|
36771
|
-
stderr,
|
|
36772
|
-
exitCode: -1
|
|
36773
|
-
});
|
|
36774
|
-
try {
|
|
36775
|
-
child.kill("SIGTERM");
|
|
36776
|
-
} catch (e) {
|
|
36777
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36778
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36779
|
-
}
|
|
36780
|
-
}
|
|
36781
|
-
} else {
|
|
36782
|
-
stderr += chunk;
|
|
36783
|
-
stderrBytes += chunkBytes;
|
|
36784
|
-
}
|
|
36785
|
-
});
|
|
36786
|
-
child.on("close", (code) => {
|
|
36787
|
-
settle({
|
|
36788
|
-
stdout,
|
|
36789
|
-
stderr,
|
|
36790
|
-
exitCode: code ?? 0
|
|
36791
|
-
});
|
|
36792
|
-
});
|
|
36793
|
-
child.on("error", (err) => {
|
|
36794
|
-
settle({
|
|
36795
|
-
stdout,
|
|
36796
|
-
stderr: err.message,
|
|
36797
|
-
exitCode: 1
|
|
36798
|
-
});
|
|
36799
|
-
});
|
|
36800
|
-
});
|
|
36801
|
-
}
|
|
36802
36839
|
async function runSemgrep(options) {
|
|
36803
36840
|
const files = options.files || [];
|
|
36804
36841
|
const rulesDir = options.rulesDir || DEFAULT_RULES_DIR;
|
|
@@ -36810,7 +36847,24 @@ async function runSemgrep(options) {
|
|
|
36810
36847
|
engine: "tier_a"
|
|
36811
36848
|
};
|
|
36812
36849
|
}
|
|
36813
|
-
if (!_internals50.
|
|
36850
|
+
if (!await _internals50.checkSemgrepAvailable(options.cwd, options.abortSignal)) {
|
|
36851
|
+
if (options.abortSignal?.aborted) {
|
|
36852
|
+
return {
|
|
36853
|
+
available: true,
|
|
36854
|
+
findings: [],
|
|
36855
|
+
error: "Semgrep execution cancelled",
|
|
36856
|
+
engine: "tier_a"
|
|
36857
|
+
};
|
|
36858
|
+
}
|
|
36859
|
+
return {
|
|
36860
|
+
available: false,
|
|
36861
|
+
findings: [],
|
|
36862
|
+
error: "Semgrep is not installed or not available on PATH",
|
|
36863
|
+
engine: "tier_a"
|
|
36864
|
+
};
|
|
36865
|
+
}
|
|
36866
|
+
const executable = _internals50.resolveSemgrepBinary();
|
|
36867
|
+
if (!executable) {
|
|
36814
36868
|
return {
|
|
36815
36869
|
available: false,
|
|
36816
36870
|
findings: [],
|
|
@@ -36828,11 +36882,16 @@ async function runSemgrep(options) {
|
|
|
36828
36882
|
}
|
|
36829
36883
|
args.push(...files);
|
|
36830
36884
|
try {
|
|
36831
|
-
const result = await
|
|
36885
|
+
const result = await _internals50.runExternalTool({
|
|
36886
|
+
executable,
|
|
36887
|
+
args,
|
|
36888
|
+
cwd: options.cwd ?? _internals50.getAvailabilityProbeCwd(),
|
|
36832
36889
|
timeoutMs,
|
|
36833
|
-
|
|
36890
|
+
maxStdoutBytes: MAX_OUTPUT_BYTES,
|
|
36891
|
+
maxStderrBytes: MAX_OUTPUT_BYTES,
|
|
36892
|
+
abortSignal: options.abortSignal
|
|
36834
36893
|
});
|
|
36835
|
-
if (result.
|
|
36894
|
+
if (result.stdoutTruncated || result.stderrTruncated) {
|
|
36836
36895
|
return {
|
|
36837
36896
|
available: true,
|
|
36838
36897
|
findings: [],
|
|
@@ -36840,6 +36899,14 @@ async function runSemgrep(options) {
|
|
|
36840
36899
|
engine: "tier_a"
|
|
36841
36900
|
};
|
|
36842
36901
|
}
|
|
36902
|
+
if (result.status !== "completed") {
|
|
36903
|
+
return {
|
|
36904
|
+
available: true,
|
|
36905
|
+
findings: [],
|
|
36906
|
+
error: describeExternalToolFailure(result.status),
|
|
36907
|
+
engine: "tier_a"
|
|
36908
|
+
};
|
|
36909
|
+
}
|
|
36843
36910
|
if (result.exitCode !== 0) {
|
|
36844
36911
|
if (result.exitCode === 1 && result.stdout) {
|
|
36845
36912
|
const findings2 = parseSemgrepResults(result.stdout);
|
|
@@ -36852,7 +36919,7 @@ async function runSemgrep(options) {
|
|
|
36852
36919
|
return {
|
|
36853
36920
|
available: true,
|
|
36854
36921
|
findings: [],
|
|
36855
|
-
error:
|
|
36922
|
+
error: `Semgrep exited with code ${result.exitCode}`,
|
|
36856
36923
|
engine: "tier_a"
|
|
36857
36924
|
};
|
|
36858
36925
|
}
|
|
@@ -36863,11 +36930,11 @@ async function runSemgrep(options) {
|
|
|
36863
36930
|
engine: "tier_a+tier_b"
|
|
36864
36931
|
};
|
|
36865
36932
|
} catch (error2) {
|
|
36866
|
-
const
|
|
36933
|
+
const safeError = error2 instanceof SemgrepScanError || error2 instanceof Error && error2.message === "Semgrep returned invalid JSON output" ? error2.message : "Semgrep execution failed unexpectedly";
|
|
36867
36934
|
return {
|
|
36868
36935
|
available: true,
|
|
36869
36936
|
findings: [],
|
|
36870
|
-
error:
|
|
36937
|
+
error: safeError,
|
|
36871
36938
|
engine: "tier_a"
|
|
36872
36939
|
};
|
|
36873
36940
|
}
|
|
@@ -36981,8 +37048,30 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
36981
37048
|
};
|
|
36982
37049
|
});
|
|
36983
37050
|
}
|
|
36984
|
-
async function
|
|
37051
|
+
async function waitForLockRetry(delayMs, abortSignal) {
|
|
37052
|
+
if (abortSignal?.aborted)
|
|
37053
|
+
return false;
|
|
37054
|
+
return await new Promise((resolve19) => {
|
|
37055
|
+
let settled = false;
|
|
37056
|
+
const finish = (value) => {
|
|
37057
|
+
if (settled)
|
|
37058
|
+
return;
|
|
37059
|
+
settled = true;
|
|
37060
|
+
clearTimeout(timeout);
|
|
37061
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
37062
|
+
resolve19(value);
|
|
37063
|
+
};
|
|
37064
|
+
const onAbort = () => finish(false);
|
|
37065
|
+
const timeout = setTimeout(() => finish(true), delayMs);
|
|
37066
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
37067
|
+
if (abortSignal?.aborted)
|
|
37068
|
+
onAbort();
|
|
37069
|
+
});
|
|
37070
|
+
}
|
|
37071
|
+
async function acquireLock2(lockPath, abortSignal) {
|
|
36985
37072
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
37073
|
+
if (abortSignal?.aborted)
|
|
37074
|
+
return null;
|
|
36986
37075
|
try {
|
|
36987
37076
|
const fd = fs25.openSync(lockPath, "wx");
|
|
36988
37077
|
fs25.closeSync(fd);
|
|
@@ -36994,7 +37083,9 @@ async function acquireLock2(lockPath) {
|
|
|
36994
37083
|
};
|
|
36995
37084
|
} catch {
|
|
36996
37085
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
36997
|
-
|
|
37086
|
+
if (!await waitForLockRetry(LOCK_RETRY_DELAYS_MS[attempt], abortSignal)) {
|
|
37087
|
+
return null;
|
|
37088
|
+
}
|
|
36998
37089
|
}
|
|
36999
37090
|
}
|
|
37000
37091
|
}
|
|
@@ -37029,9 +37120,19 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37029
37120
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
37030
37121
|
};
|
|
37031
37122
|
}
|
|
37123
|
+
if (opts?.abortSignal?.aborted) {
|
|
37124
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37125
|
+
}
|
|
37032
37126
|
fs25.mkdirSync(path62.dirname(baselinePath), { recursive: true });
|
|
37033
37127
|
fs25.mkdirSync(path62.dirname(tempPath), { recursive: true });
|
|
37034
|
-
const releaseLock = await acquireLock2(lockPath);
|
|
37128
|
+
const releaseLock = await acquireLock2(lockPath, opts?.abortSignal);
|
|
37129
|
+
if (!releaseLock) {
|
|
37130
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37131
|
+
}
|
|
37132
|
+
if (opts?.abortSignal?.aborted) {
|
|
37133
|
+
releaseLock();
|
|
37134
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37135
|
+
}
|
|
37035
37136
|
try {
|
|
37036
37137
|
let existing = null;
|
|
37037
37138
|
try {
|
|
@@ -37095,7 +37196,14 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37095
37196
|
message: `Baseline would exceed size cap (${json2.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
37096
37197
|
};
|
|
37097
37198
|
}
|
|
37199
|
+
if (opts?.abortSignal?.aborted) {
|
|
37200
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37201
|
+
}
|
|
37098
37202
|
fs25.writeFileSync(tempPath, json2, "utf-8");
|
|
37203
|
+
if (opts?.abortSignal?.aborted) {
|
|
37204
|
+
fs25.rmSync(tempPath, { force: true });
|
|
37205
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37206
|
+
}
|
|
37099
37207
|
fs25.renameSync(tempPath, baselinePath);
|
|
37100
37208
|
invalidateCachedArtifact(baselinePath);
|
|
37101
37209
|
return {
|
|
@@ -37128,7 +37236,14 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37128
37236
|
message: `Baseline would exceed size cap (${json.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
37129
37237
|
};
|
|
37130
37238
|
}
|
|
37239
|
+
if (opts?.abortSignal?.aborted) {
|
|
37240
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37241
|
+
}
|
|
37131
37242
|
fs25.writeFileSync(tempPath, json, "utf-8");
|
|
37243
|
+
if (opts?.abortSignal?.aborted) {
|
|
37244
|
+
fs25.rmSync(tempPath, { force: true });
|
|
37245
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37246
|
+
}
|
|
37132
37247
|
fs25.renameSync(tempPath, baselinePath);
|
|
37133
37248
|
invalidateCachedArtifact(baselinePath);
|
|
37134
37249
|
return {
|
|
@@ -37250,6 +37365,36 @@ function countBySeverity(findings) {
|
|
|
37250
37365
|
}
|
|
37251
37366
|
return counts;
|
|
37252
37367
|
}
|
|
37368
|
+
function safeSemgrepDiagnostic(message) {
|
|
37369
|
+
const diagnostic = message.trim();
|
|
37370
|
+
if (diagnostic === "Semgrep process timed out" || diagnostic === "Semgrep execution cancelled" || diagnostic === "Semgrep is not installed or not available on PATH" || diagnostic === "Semgrep returned invalid JSON output" || diagnostic === "Semgrep process failed to start or terminate safely" || diagnostic === "Semgrep execution failed unexpectedly") {
|
|
37371
|
+
return diagnostic;
|
|
37372
|
+
}
|
|
37373
|
+
if (/^Semgrep exited with code -?\d+$/.test(diagnostic)) {
|
|
37374
|
+
return diagnostic;
|
|
37375
|
+
}
|
|
37376
|
+
if (/^Semgrep reported \d+ scan errors?$/.test(diagnostic)) {
|
|
37377
|
+
return diagnostic;
|
|
37378
|
+
}
|
|
37379
|
+
if (diagnostic.startsWith("Semgrep output exceeded")) {
|
|
37380
|
+
return "Semgrep output exceeded its bounded limit; results incomplete";
|
|
37381
|
+
}
|
|
37382
|
+
return "Semgrep execution failed";
|
|
37383
|
+
}
|
|
37384
|
+
function cancelledScanResult(findings, filesScanned) {
|
|
37385
|
+
const finalFindings = findings.slice(0, MAX_FINDINGS);
|
|
37386
|
+
return {
|
|
37387
|
+
verdict: "fail",
|
|
37388
|
+
error: "SAST scan cancelled",
|
|
37389
|
+
findings: finalFindings,
|
|
37390
|
+
summary: {
|
|
37391
|
+
engine: "tier_a",
|
|
37392
|
+
files_scanned: filesScanned,
|
|
37393
|
+
findings_count: finalFindings.length,
|
|
37394
|
+
findings_by_severity: countBySeverity(finalFindings)
|
|
37395
|
+
}
|
|
37396
|
+
};
|
|
37397
|
+
}
|
|
37253
37398
|
function scanFileWithTierA(filePath, language) {
|
|
37254
37399
|
try {
|
|
37255
37400
|
const content = fs26.readFileSync(filePath, "utf-8");
|
|
@@ -37275,7 +37420,8 @@ async function sastScan(input, directory, config) {
|
|
|
37275
37420
|
severity_threshold = "medium",
|
|
37276
37421
|
capture_baseline = false,
|
|
37277
37422
|
phase,
|
|
37278
|
-
offline_only = false
|
|
37423
|
+
offline_only = false,
|
|
37424
|
+
abort_signal
|
|
37279
37425
|
} = input;
|
|
37280
37426
|
if (config?.gates?.sast_scan?.enabled === false) {
|
|
37281
37427
|
return {
|
|
@@ -37298,10 +37444,17 @@ async function sastScan(input, directory, config) {
|
|
|
37298
37444
|
let filesScanned = 0;
|
|
37299
37445
|
let _filesSkipped = 0;
|
|
37300
37446
|
const scannedFilePaths = [];
|
|
37301
|
-
|
|
37447
|
+
if (abort_signal?.aborted) {
|
|
37448
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37449
|
+
}
|
|
37450
|
+
const semgrepAvailable = !offline_only && await _internals52.checkSemgrepAvailable(directory, abort_signal);
|
|
37302
37451
|
const engine = semgrepAvailable ? "tier_a+tier_b" : "tier_a";
|
|
37303
37452
|
const filesByLanguage = new Map;
|
|
37453
|
+
let semgrepError = abort_signal?.aborted ? "SAST scan cancelled" : undefined;
|
|
37304
37454
|
for (const filePath of changed_files) {
|
|
37455
|
+
if (abort_signal?.aborted) {
|
|
37456
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37457
|
+
}
|
|
37305
37458
|
if (typeof filePath !== "string" || !filePath) {
|
|
37306
37459
|
_filesSkipped++;
|
|
37307
37460
|
continue;
|
|
@@ -37356,6 +37509,10 @@ async function sastScan(input, directory, config) {
|
|
|
37356
37509
|
if (semgrepAvailable && filesByLanguage.size > 0) {
|
|
37357
37510
|
try {
|
|
37358
37511
|
for (const [bucketKey, bucketFiles] of filesByLanguage.entries()) {
|
|
37512
|
+
if (abort_signal?.aborted) {
|
|
37513
|
+
semgrepError = "SAST scan cancelled";
|
|
37514
|
+
break;
|
|
37515
|
+
}
|
|
37359
37516
|
if (bucketFiles.length === 0)
|
|
37360
37517
|
continue;
|
|
37361
37518
|
let semgrepResult;
|
|
@@ -37364,13 +37521,21 @@ async function sastScan(input, directory, config) {
|
|
|
37364
37521
|
semgrepResult = await _internals52.runSemgrep({
|
|
37365
37522
|
files: bucketFiles,
|
|
37366
37523
|
lang,
|
|
37367
|
-
useAutoConfig: true
|
|
37524
|
+
useAutoConfig: true,
|
|
37525
|
+
cwd: directory,
|
|
37526
|
+
abortSignal: abort_signal
|
|
37368
37527
|
});
|
|
37369
37528
|
} else {
|
|
37370
37529
|
semgrepResult = await _internals52.runSemgrep({
|
|
37371
|
-
files: bucketFiles
|
|
37530
|
+
files: bucketFiles,
|
|
37531
|
+
cwd: directory,
|
|
37532
|
+
abortSignal: abort_signal
|
|
37372
37533
|
});
|
|
37373
37534
|
}
|
|
37535
|
+
if (semgrepResult.error) {
|
|
37536
|
+
semgrepError = safeSemgrepDiagnostic(semgrepResult.error);
|
|
37537
|
+
break;
|
|
37538
|
+
}
|
|
37374
37539
|
if (semgrepResult.findings.length > 0) {
|
|
37375
37540
|
const semgrepFindings = semgrepResult.findings.map((f) => ({
|
|
37376
37541
|
rule_id: f.rule_id,
|
|
@@ -37393,9 +37558,42 @@ async function sastScan(input, directory, config) {
|
|
|
37393
37558
|
}
|
|
37394
37559
|
}
|
|
37395
37560
|
}
|
|
37396
|
-
} catch
|
|
37397
|
-
|
|
37561
|
+
} catch {
|
|
37562
|
+
semgrepError = "Semgrep execution failed";
|
|
37563
|
+
}
|
|
37564
|
+
}
|
|
37565
|
+
if (abort_signal?.aborted) {
|
|
37566
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37567
|
+
}
|
|
37568
|
+
if (semgrepError) {
|
|
37569
|
+
const finalFindings2 = allFindings.slice(0, MAX_FINDINGS);
|
|
37570
|
+
const summary2 = {
|
|
37571
|
+
engine: "tier_a",
|
|
37572
|
+
files_scanned: filesScanned,
|
|
37573
|
+
findings_count: finalFindings2.length,
|
|
37574
|
+
findings_by_severity: countBySeverity(finalFindings2)
|
|
37575
|
+
};
|
|
37576
|
+
warn(`SAST Scan: Semgrep execution failed closed: ${semgrepError}`);
|
|
37577
|
+
if (abort_signal?.aborted) {
|
|
37578
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37398
37579
|
}
|
|
37580
|
+
await saveEvidence(directory, "sast_scan", {
|
|
37581
|
+
task_id: "sast_scan",
|
|
37582
|
+
type: "sast",
|
|
37583
|
+
timestamp: new Date().toISOString(),
|
|
37584
|
+
agent: "sast_scan",
|
|
37585
|
+
verdict: "fail",
|
|
37586
|
+
summary: `Semgrep execution failed: ${semgrepError}`,
|
|
37587
|
+
...summary2,
|
|
37588
|
+
findings: finalFindings2,
|
|
37589
|
+
baseline_used: false
|
|
37590
|
+
}, abort_signal);
|
|
37591
|
+
return {
|
|
37592
|
+
verdict: "fail",
|
|
37593
|
+
error: `Semgrep execution failed: ${semgrepError}`,
|
|
37594
|
+
findings: finalFindings2,
|
|
37595
|
+
summary: summary2
|
|
37596
|
+
};
|
|
37399
37597
|
}
|
|
37400
37598
|
if (capture_baseline) {
|
|
37401
37599
|
if (phase === undefined || !Number.isInteger(phase) || phase < 1) {
|
|
@@ -37426,7 +37624,10 @@ async function sastScan(input, directory, config) {
|
|
|
37426
37624
|
};
|
|
37427
37625
|
}
|
|
37428
37626
|
const captureFindings = allFindings.slice(0, MAX_BASELINE_FINDINGS);
|
|
37429
|
-
|
|
37627
|
+
if (abort_signal?.aborted) {
|
|
37628
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37629
|
+
}
|
|
37630
|
+
const captureResult = await captureOrMergeBaseline(directory, phase, captureFindings, engine, scannedFilePaths, { abortSignal: abort_signal });
|
|
37430
37631
|
const captureStatus = captureResult.status === "written" ? "baseline_captured" : captureResult.status === "merged" ? "baseline_merged" : undefined;
|
|
37431
37632
|
if (captureResult.status === "error") {
|
|
37432
37633
|
warn(`SAST Baseline: capture failed \u2014 ${captureResult.message}`);
|
|
@@ -37438,6 +37639,9 @@ async function sastScan(input, directory, config) {
|
|
|
37438
37639
|
findings_count: finalFindings2.length,
|
|
37439
37640
|
findings_by_severity: countBySeverity(finalFindings2)
|
|
37440
37641
|
};
|
|
37642
|
+
if (abort_signal?.aborted) {
|
|
37643
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37644
|
+
}
|
|
37441
37645
|
await saveEvidence(directory, "sast_scan", {
|
|
37442
37646
|
task_id: "sast_scan",
|
|
37443
37647
|
type: "sast",
|
|
@@ -37448,7 +37652,7 @@ async function sastScan(input, directory, config) {
|
|
|
37448
37652
|
...summary2,
|
|
37449
37653
|
findings: finalFindings2,
|
|
37450
37654
|
baseline_used: false
|
|
37451
|
-
});
|
|
37655
|
+
}, abort_signal);
|
|
37452
37656
|
return {
|
|
37453
37657
|
verdict: "pass",
|
|
37454
37658
|
findings: finalFindings2,
|
|
@@ -37516,6 +37720,9 @@ async function sastScan(input, directory, config) {
|
|
|
37516
37720
|
findings_count: finalFindings.length,
|
|
37517
37721
|
findings_by_severity: findingsBySeverity
|
|
37518
37722
|
};
|
|
37723
|
+
if (abort_signal?.aborted) {
|
|
37724
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37725
|
+
}
|
|
37519
37726
|
await saveEvidence(directory, "sast_scan", {
|
|
37520
37727
|
task_id: "sast_scan",
|
|
37521
37728
|
type: "sast",
|
|
@@ -37530,7 +37737,7 @@ async function sastScan(input, directory, config) {
|
|
|
37530
37737
|
pre_existing_findings: preExistingFindings,
|
|
37531
37738
|
baseline_used: true
|
|
37532
37739
|
}
|
|
37533
|
-
});
|
|
37740
|
+
}, abort_signal);
|
|
37534
37741
|
const result = {
|
|
37535
37742
|
verdict,
|
|
37536
37743
|
findings: finalFindings,
|
|
@@ -37554,7 +37761,7 @@ var sast_scan = createSwarmTool({
|
|
|
37554
37761
|
capture_baseline: exports_external.boolean().optional().describe("When true, capture/merge a phase-scoped baseline of pre-existing findings. Requires phase. Subsequent scans with phase only fail on NEW findings."),
|
|
37555
37762
|
phase: exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). Required with capture_baseline. Enables baseline diff when provided on non-capture scans.")
|
|
37556
37763
|
},
|
|
37557
|
-
execute: async (args, directory) => {
|
|
37764
|
+
execute: async (args, directory, ctx) => {
|
|
37558
37765
|
let safeArgs;
|
|
37559
37766
|
try {
|
|
37560
37767
|
if (args && typeof args === "object") {
|
|
@@ -37607,7 +37814,8 @@ var sast_scan = createSwarmTool({
|
|
|
37607
37814
|
changed_files: safeArgs.changed_files ?? [],
|
|
37608
37815
|
severity_threshold: safeArgs.severity_threshold ?? "medium",
|
|
37609
37816
|
capture_baseline: safeArgs.capture_baseline,
|
|
37610
|
-
phase: safeArgs.phase
|
|
37817
|
+
phase: safeArgs.phase,
|
|
37818
|
+
abort_signal: ctx?.abort
|
|
37611
37819
|
};
|
|
37612
37820
|
const result = await _internals52.sastScan(input, directory);
|
|
37613
37821
|
return JSON.stringify(result, null, 2);
|
|
@@ -37616,6 +37824,7 @@ var sast_scan = createSwarmTool({
|
|
|
37616
37824
|
var _internals52 = {
|
|
37617
37825
|
sastScan,
|
|
37618
37826
|
sast_scan,
|
|
37827
|
+
checkSemgrepAvailable: (directory, abortSignal) => checkSemgrepAvailable(directory, abortSignal),
|
|
37619
37828
|
isSemgrepAvailable: () => isSemgrepAvailable(),
|
|
37620
37829
|
runSemgrep: (options) => runSemgrep(options)
|
|
37621
37830
|
};
|
|
@@ -43167,6 +43376,22 @@ import * as fs30 from "fs";
|
|
|
43167
43376
|
import * as path76 from "path";
|
|
43168
43377
|
var MAX_OUTPUT_BYTES2 = 512000;
|
|
43169
43378
|
var MAX_COMMAND_LENGTH = 500;
|
|
43379
|
+
var SUPPORTED_LINTERS = ["biome", "eslint"];
|
|
43380
|
+
var LINTER_DETECT_TIMEOUT_MS = 2000;
|
|
43381
|
+
var LINTER_RUN_TIMEOUT_MS = 30000;
|
|
43382
|
+
var OUTPUT_TRUNCATION_SUFFIX = `
|
|
43383
|
+
... (output truncated)`;
|
|
43384
|
+
var NODE_MODULES = "node_modules";
|
|
43385
|
+
var BIN_DIRECTORY = ".bin";
|
|
43386
|
+
var MAX_PACKAGE_MANIFEST_BYTES = 256 * 1024;
|
|
43387
|
+
var MAX_PATH_SHIM_BYTES = 64 * 1024;
|
|
43388
|
+
var UNSAFE_SHELL_WRAPPER_EXTENSIONS = new Set([".bat", ".cmd", ".ps1"]);
|
|
43389
|
+
var WINDOWS_BATCH_WRAPPER_EXTENSIONS = [".cmd", ".bat"];
|
|
43390
|
+
var WINDOWS_CMD_UNSAFE_TOKEN = /["%!^&|<>\r\n]/;
|
|
43391
|
+
var LINTER_PACKAGES = {
|
|
43392
|
+
biome: "@biomejs/biome",
|
|
43393
|
+
eslint: "eslint"
|
|
43394
|
+
};
|
|
43170
43395
|
function validateArgs(args) {
|
|
43171
43396
|
if (typeof args !== "object" || args === null)
|
|
43172
43397
|
return false;
|
|
@@ -43175,112 +43400,533 @@ function validateArgs(args) {
|
|
|
43175
43400
|
return false;
|
|
43176
43401
|
return true;
|
|
43177
43402
|
}
|
|
43178
|
-
function
|
|
43179
|
-
|
|
43180
|
-
|
|
43181
|
-
|
|
43182
|
-
|
|
43183
|
-
|
|
43184
|
-
|
|
43185
|
-
|
|
43186
|
-
|
|
43403
|
+
function normalizeCaseForPlatform(value, platform) {
|
|
43404
|
+
return platform === "win32" ? value.toLowerCase() : value;
|
|
43405
|
+
}
|
|
43406
|
+
function normalizeRelativePathForPlatform(value, platform) {
|
|
43407
|
+
return normalizeCaseForPlatform(value.replaceAll("\\", "/").replace(/\/+/g, "/"), platform);
|
|
43408
|
+
}
|
|
43409
|
+
function isRegularFile(candidate) {
|
|
43410
|
+
try {
|
|
43411
|
+
return _internals64.statSync(candidate).isFile();
|
|
43412
|
+
} catch {
|
|
43413
|
+
return false;
|
|
43414
|
+
}
|
|
43415
|
+
}
|
|
43416
|
+
function readTextFileBounded(filePath, maxBytes) {
|
|
43417
|
+
let fd;
|
|
43418
|
+
try {
|
|
43419
|
+
fd = _internals64.openSync(filePath, "r");
|
|
43420
|
+
const stats = _internals64.fstatSync(fd);
|
|
43421
|
+
if (!stats.isFile() || !Number.isSafeInteger(stats.size) || stats.size < 0 || stats.size > maxBytes) {
|
|
43422
|
+
return null;
|
|
43423
|
+
}
|
|
43424
|
+
const bytes = Buffer.alloc(stats.size);
|
|
43425
|
+
let offset = 0;
|
|
43426
|
+
while (offset < bytes.byteLength) {
|
|
43427
|
+
const bytesRead = _internals64.readSync(fd, bytes, offset, bytes.byteLength - offset, null);
|
|
43428
|
+
if (bytesRead === 0)
|
|
43429
|
+
break;
|
|
43430
|
+
offset += bytesRead;
|
|
43431
|
+
}
|
|
43432
|
+
const overflowProbe = Buffer.alloc(1);
|
|
43433
|
+
if (_internals64.readSync(fd, overflowProbe, 0, 1, null) > 0)
|
|
43434
|
+
return null;
|
|
43435
|
+
return bytes.subarray(0, offset).toString("utf8");
|
|
43436
|
+
} catch {
|
|
43437
|
+
return null;
|
|
43438
|
+
} finally {
|
|
43439
|
+
if (fd !== undefined) {
|
|
43440
|
+
try {
|
|
43441
|
+
_internals64.closeSync(fd);
|
|
43442
|
+
} catch {}
|
|
43443
|
+
}
|
|
43444
|
+
}
|
|
43445
|
+
}
|
|
43446
|
+
function toAbsoluteDirectory(directory) {
|
|
43447
|
+
return path76.isAbsolute(directory) ? directory : path76.resolve(directory);
|
|
43448
|
+
}
|
|
43449
|
+
function getAncestorDirectories(directory) {
|
|
43450
|
+
const resolved = path76.resolve(directory);
|
|
43451
|
+
const roots = [];
|
|
43452
|
+
let current = resolved;
|
|
43453
|
+
for (;; ) {
|
|
43454
|
+
roots.push(current);
|
|
43455
|
+
const parent = path76.dirname(current);
|
|
43456
|
+
if (parent === current)
|
|
43457
|
+
break;
|
|
43458
|
+
current = parent;
|
|
43459
|
+
}
|
|
43460
|
+
return roots;
|
|
43461
|
+
}
|
|
43462
|
+
function getTrustedShimNames(linter, platform = _internals64.platform()) {
|
|
43463
|
+
const isWindows = platform === "win32";
|
|
43464
|
+
if (linter === "biome") {
|
|
43465
|
+
return isWindows ? ["biome.exe", "biome.cmd", "biome.ps1"] : ["biome"];
|
|
43466
|
+
}
|
|
43467
|
+
return isWindows ? ["eslint.exe", "eslint.cmd", "eslint.ps1"] : ["eslint"];
|
|
43468
|
+
}
|
|
43469
|
+
function getExpectedPackageBinRelativePath(linter) {
|
|
43470
|
+
return linter === "biome" ? "bin/biome" : "bin/eslint.js";
|
|
43471
|
+
}
|
|
43472
|
+
function getPackageRootFromSearchRoot(searchRoot, linter) {
|
|
43473
|
+
return path76.join(searchRoot, NODE_MODULES, ...LINTER_PACKAGES[linter].split("/"));
|
|
43474
|
+
}
|
|
43475
|
+
function getPackageManifestPath(searchRoot, linter) {
|
|
43476
|
+
return path76.join(getPackageRootFromSearchRoot(searchRoot, linter), "package.json");
|
|
43477
|
+
}
|
|
43478
|
+
function getPackageDisplayPath(searchRoot, linter) {
|
|
43479
|
+
return path76.join(searchRoot, NODE_MODULES, BIN_DIRECTORY, linter === "biome" ? _internals64.platform() === "win32" ? "biome.exe" : "biome" : _internals64.platform() === "win32" ? "eslint" : "eslint");
|
|
43480
|
+
}
|
|
43481
|
+
function getBiomeNativePackage(platform, arch) {
|
|
43482
|
+
const archMap = platform === "darwin" ? { arm64: "@biomejs/cli-darwin-arm64", x64: "@biomejs/cli-darwin-x64" } : platform === "linux" ? {
|
|
43483
|
+
arm64: "@biomejs/cli-linux-arm64",
|
|
43484
|
+
arm: "@biomejs/cli-linux-arm",
|
|
43485
|
+
x64: "@biomejs/cli-linux-x64"
|
|
43486
|
+
} : platform === "win32" ? {
|
|
43487
|
+
arm64: "@biomejs/cli-win32-arm64",
|
|
43488
|
+
x64: "@biomejs/cli-win32-x64"
|
|
43489
|
+
} : null;
|
|
43490
|
+
if (!archMap)
|
|
43491
|
+
return null;
|
|
43492
|
+
return archMap[arch] ?? null;
|
|
43493
|
+
}
|
|
43494
|
+
function getBiomeNativeExecutable(searchRoot, platform = _internals64.platform(), arch = _internals64.arch()) {
|
|
43495
|
+
const nativePackage = getBiomeNativePackage(platform, arch);
|
|
43496
|
+
if (!nativePackage)
|
|
43497
|
+
return null;
|
|
43498
|
+
const executableName = platform === "win32" ? "biome.exe" : "biome";
|
|
43499
|
+
const candidate = path76.join(searchRoot, NODE_MODULES, ...nativePackage.split("/"), executableName);
|
|
43500
|
+
return isRegularFile(candidate) ? candidate : null;
|
|
43501
|
+
}
|
|
43502
|
+
function resolvePackageBinEntry(manifestPath, linter) {
|
|
43503
|
+
try {
|
|
43504
|
+
const contents = readTextFileBounded(manifestPath, MAX_PACKAGE_MANIFEST_BYTES);
|
|
43505
|
+
if (contents === null)
|
|
43506
|
+
return null;
|
|
43507
|
+
const manifest = JSON.parse(contents);
|
|
43508
|
+
if (typeof manifest.bin === "string") {
|
|
43509
|
+
return manifest.bin;
|
|
43510
|
+
}
|
|
43511
|
+
if (manifest.bin && typeof manifest.bin === "object") {
|
|
43512
|
+
const key = linter === "biome" ? "biome" : "eslint";
|
|
43513
|
+
const entry = manifest.bin[key];
|
|
43514
|
+
return typeof entry === "string" ? entry : null;
|
|
43515
|
+
}
|
|
43516
|
+
} catch {}
|
|
43517
|
+
return null;
|
|
43518
|
+
}
|
|
43519
|
+
function resolveCanonicalPackageCommand(searchRoot, linter, source) {
|
|
43520
|
+
const manifestPath = getPackageManifestPath(searchRoot, linter);
|
|
43521
|
+
if (!isRegularFile(manifestPath))
|
|
43522
|
+
return null;
|
|
43523
|
+
const relativeBinPath = resolvePackageBinEntry(manifestPath, linter);
|
|
43524
|
+
if (!relativeBinPath)
|
|
43525
|
+
return null;
|
|
43526
|
+
let canonicalPackageRoot;
|
|
43527
|
+
let canonicalCandidate;
|
|
43528
|
+
try {
|
|
43529
|
+
const packageRoot = path76.dirname(manifestPath);
|
|
43530
|
+
canonicalPackageRoot = _internals64.realpathSync(packageRoot);
|
|
43531
|
+
canonicalCandidate = _internals64.realpathSync(path76.resolve(packageRoot, relativeBinPath));
|
|
43532
|
+
} catch {
|
|
43533
|
+
return null;
|
|
43534
|
+
}
|
|
43535
|
+
const relativeToPackage = path76.relative(canonicalPackageRoot, canonicalCandidate);
|
|
43536
|
+
if (relativeToPackage === "" || relativeToPackage.startsWith("..") || path76.isAbsolute(relativeToPackage)) {
|
|
43537
|
+
return null;
|
|
43538
|
+
}
|
|
43539
|
+
if (!isRegularFile(canonicalCandidate))
|
|
43540
|
+
return null;
|
|
43541
|
+
return {
|
|
43542
|
+
linter,
|
|
43543
|
+
executable: _internals64.execPath(),
|
|
43544
|
+
argsPrefix: [canonicalCandidate],
|
|
43545
|
+
displayPrefix: [getPackageDisplayPath(searchRoot, linter)],
|
|
43546
|
+
source
|
|
43547
|
+
};
|
|
43548
|
+
}
|
|
43549
|
+
function hasTrustedLocalShim(searchRoot, linter) {
|
|
43550
|
+
const binRoot = path76.join(searchRoot, NODE_MODULES, BIN_DIRECTORY);
|
|
43551
|
+
for (const name of getTrustedShimNames(linter)) {
|
|
43552
|
+
if (isRegularFile(path76.join(binRoot, name))) {
|
|
43553
|
+
return true;
|
|
43554
|
+
}
|
|
43555
|
+
}
|
|
43556
|
+
return false;
|
|
43557
|
+
}
|
|
43558
|
+
function resolveLocalLinterCommand(linter, directory) {
|
|
43559
|
+
const roots = getAncestorDirectories(directory);
|
|
43560
|
+
for (const root of roots) {
|
|
43561
|
+
if (linter === "biome") {
|
|
43562
|
+
const nativeExecutable = getBiomeNativeExecutable(root);
|
|
43563
|
+
if (nativeExecutable) {
|
|
43564
|
+
return {
|
|
43565
|
+
linter,
|
|
43566
|
+
executable: nativeExecutable,
|
|
43567
|
+
argsPrefix: [],
|
|
43568
|
+
displayPrefix: [nativeExecutable],
|
|
43569
|
+
source: "local-native"
|
|
43570
|
+
};
|
|
43187
43571
|
}
|
|
43188
|
-
|
|
43189
|
-
|
|
43190
|
-
|
|
43191
|
-
|
|
43572
|
+
}
|
|
43573
|
+
if (hasTrustedLocalShim(root, linter)) {
|
|
43574
|
+
const resolvedFromShim = resolveCanonicalPackageCommand(root, linter, "local-shim");
|
|
43575
|
+
if (resolvedFromShim)
|
|
43576
|
+
return resolvedFromShim;
|
|
43577
|
+
}
|
|
43578
|
+
const resolvedPackage = resolveCanonicalPackageCommand(root, linter, "safe-package-bin");
|
|
43579
|
+
if (resolvedPackage)
|
|
43580
|
+
return resolvedPackage;
|
|
43581
|
+
}
|
|
43582
|
+
return null;
|
|
43583
|
+
}
|
|
43584
|
+
function findPathShimCandidate(linter, envPath = _internals64.pathEnv(), platform = _internals64.platform()) {
|
|
43585
|
+
const entries = envPath.split(path76.delimiter).filter(Boolean);
|
|
43586
|
+
const shimNames = getTrustedShimNames(linter, platform).filter((name) => name.endsWith(".cmd") || name.endsWith(".ps1") || platform !== "win32");
|
|
43587
|
+
for (const entry of entries) {
|
|
43588
|
+
for (const shimName of shimNames) {
|
|
43589
|
+
const candidate = path76.join(entry, shimName);
|
|
43590
|
+
if (isRegularFile(candidate)) {
|
|
43591
|
+
return candidate;
|
|
43192
43592
|
}
|
|
43193
|
-
|
|
43593
|
+
}
|
|
43194
43594
|
}
|
|
43595
|
+
return null;
|
|
43195
43596
|
}
|
|
43196
|
-
function
|
|
43197
|
-
const
|
|
43198
|
-
const
|
|
43199
|
-
|
|
43200
|
-
|
|
43201
|
-
|
|
43202
|
-
|
|
43203
|
-
|
|
43204
|
-
|
|
43205
|
-
|
|
43206
|
-
|
|
43207
|
-
|
|
43208
|
-
|
|
43597
|
+
function getExpectedShimSuffixes(linter) {
|
|
43598
|
+
const packageParts = LINTER_PACKAGES[linter].split("/");
|
|
43599
|
+
const packageSuffix = path76.join("..", ...packageParts, ...getExpectedPackageBinRelativePath(linter).split("/"));
|
|
43600
|
+
const nestedNodeModulesSuffix = path76.join("..", NODE_MODULES, ...packageParts, ...getExpectedPackageBinRelativePath(linter).split("/"));
|
|
43601
|
+
const packageOnlySuffix = path76.join(...packageParts, ...getExpectedPackageBinRelativePath(linter).split("/"));
|
|
43602
|
+
const nodeModulesPackageOnlySuffix = path76.join(NODE_MODULES, ...packageParts, ...getExpectedPackageBinRelativePath(linter).split("/"));
|
|
43603
|
+
return [
|
|
43604
|
+
normalizeRelativePathForPlatform(packageSuffix, "win32"),
|
|
43605
|
+
normalizeRelativePathForPlatform(nestedNodeModulesSuffix, "win32"),
|
|
43606
|
+
normalizeRelativePathForPlatform(packageOnlySuffix, "win32"),
|
|
43607
|
+
normalizeRelativePathForPlatform(nodeModulesPackageOnlySuffix, "win32"),
|
|
43608
|
+
normalizeRelativePathForPlatform(packageSuffix, "linux"),
|
|
43609
|
+
normalizeRelativePathForPlatform(nestedNodeModulesSuffix, "linux"),
|
|
43610
|
+
normalizeRelativePathForPlatform(packageOnlySuffix, "linux"),
|
|
43611
|
+
normalizeRelativePathForPlatform(nodeModulesPackageOnlySuffix, "linux")
|
|
43612
|
+
];
|
|
43613
|
+
}
|
|
43614
|
+
function resolvePathShimTarget(shimPath, linter, platform = _internals64.platform()) {
|
|
43615
|
+
const contents = readTextFileBounded(shimPath, MAX_PATH_SHIM_BYTES);
|
|
43616
|
+
if (contents === null)
|
|
43617
|
+
return null;
|
|
43618
|
+
const ext = path76.extname(shimPath).toLowerCase();
|
|
43619
|
+
let relativeTarget = null;
|
|
43620
|
+
if (ext === ".cmd") {
|
|
43621
|
+
const regex = /"%(?:dp0%|~dp0)(?<suffix>(?:\\[^"%]+)+)"/gi;
|
|
43622
|
+
for (const match of contents.matchAll(regex)) {
|
|
43623
|
+
const suffix = match.groups?.suffix;
|
|
43624
|
+
if (!suffix)
|
|
43625
|
+
continue;
|
|
43626
|
+
const normalized = normalizeRelativePathForPlatform(suffix, "win32");
|
|
43627
|
+
if (getExpectedShimSuffixes(linter).some((expected) => normalized.endsWith(expected))) {
|
|
43628
|
+
relativeTarget = suffix;
|
|
43629
|
+
break;
|
|
43209
43630
|
}
|
|
43210
|
-
|
|
43211
|
-
|
|
43631
|
+
}
|
|
43632
|
+
} else if (ext === ".ps1") {
|
|
43633
|
+
const regex = /"\$basedir(?:_win)?\/(?<suffix>\.\.\/[^"\r\n]+)"/gi;
|
|
43634
|
+
for (const match of contents.matchAll(regex)) {
|
|
43635
|
+
const suffix = match.groups?.suffix;
|
|
43636
|
+
if (!suffix)
|
|
43637
|
+
continue;
|
|
43638
|
+
const normalized = normalizeRelativePathForPlatform(suffix, platform);
|
|
43639
|
+
if (getExpectedShimSuffixes(linter).some((expected) => normalized.endsWith(expected))) {
|
|
43640
|
+
relativeTarget = suffix;
|
|
43641
|
+
break;
|
|
43212
43642
|
}
|
|
43213
|
-
|
|
43214
|
-
|
|
43215
|
-
|
|
43216
|
-
|
|
43217
|
-
|
|
43218
|
-
|
|
43219
|
-
|
|
43220
|
-
|
|
43221
|
-
|
|
43222
|
-
|
|
43223
|
-
|
|
43224
|
-
|
|
43225
|
-
|
|
43226
|
-
|
|
43227
|
-
|
|
43228
|
-
|
|
43229
|
-
|
|
43230
|
-
|
|
43231
|
-
|
|
43232
|
-
|
|
43233
|
-
|
|
43234
|
-
|
|
43235
|
-
|
|
43236
|
-
|
|
43643
|
+
}
|
|
43644
|
+
} else {
|
|
43645
|
+
const regex = /"\$basedir(?:_win)?\/(?<suffix>\.\.\/[^"\r\n]+)"/gi;
|
|
43646
|
+
for (const match of contents.matchAll(regex)) {
|
|
43647
|
+
const suffix = match.groups?.suffix;
|
|
43648
|
+
if (!suffix)
|
|
43649
|
+
continue;
|
|
43650
|
+
const normalized = normalizeRelativePathForPlatform(suffix, platform);
|
|
43651
|
+
if (getExpectedShimSuffixes(linter).some((expected) => normalized.endsWith(expected))) {
|
|
43652
|
+
relativeTarget = suffix;
|
|
43653
|
+
break;
|
|
43654
|
+
}
|
|
43655
|
+
}
|
|
43656
|
+
}
|
|
43657
|
+
if (!relativeTarget)
|
|
43658
|
+
return null;
|
|
43659
|
+
let canonicalShimDir;
|
|
43660
|
+
try {
|
|
43661
|
+
canonicalShimDir = _internals64.realpathSync(path76.dirname(shimPath));
|
|
43662
|
+
} catch {
|
|
43663
|
+
return null;
|
|
43664
|
+
}
|
|
43665
|
+
const resolvedTarget = path76.resolve(canonicalShimDir, relativeTarget.replaceAll("\\", path76.sep).replace(/^[\\/]+/, ""));
|
|
43666
|
+
if (!isRegularFile(resolvedTarget))
|
|
43667
|
+
return null;
|
|
43668
|
+
let canonicalTarget;
|
|
43669
|
+
try {
|
|
43670
|
+
canonicalTarget = _internals64.realpathSync(resolvedTarget);
|
|
43671
|
+
} catch {
|
|
43672
|
+
return null;
|
|
43673
|
+
}
|
|
43674
|
+
const targetPackageMarker = path76.join(NODE_MODULES, ...LINTER_PACKAGES[linter].split("/"));
|
|
43675
|
+
if (!normalizeCaseForPlatform(canonicalTarget, platform).includes(normalizeCaseForPlatform(targetPackageMarker, platform))) {
|
|
43676
|
+
return null;
|
|
43677
|
+
}
|
|
43678
|
+
let canonicalShimParent;
|
|
43679
|
+
try {
|
|
43680
|
+
canonicalShimParent = _internals64.realpathSync(path76.dirname(canonicalShimDir));
|
|
43681
|
+
} catch {
|
|
43682
|
+
return null;
|
|
43683
|
+
}
|
|
43684
|
+
const allowedRoots = [canonicalShimDir, canonicalShimParent];
|
|
43685
|
+
const isContained2 = allowedRoots.some((root) => {
|
|
43686
|
+
const relative10 = path76.relative(root, canonicalTarget);
|
|
43687
|
+
return relative10 === "" || !relative10.startsWith("..") && !path76.isAbsolute(relative10);
|
|
43688
|
+
});
|
|
43689
|
+
if (!isContained2)
|
|
43690
|
+
return null;
|
|
43691
|
+
return canonicalTarget;
|
|
43692
|
+
}
|
|
43693
|
+
function resolvePathLinterCommand(linter, directory) {
|
|
43694
|
+
const platform = _internals64.platform();
|
|
43695
|
+
const envPath = _internals64.pathEnv();
|
|
43696
|
+
const nativeNames = platform === "win32" ? linter === "biome" ? ["biome.exe"] : ["eslint.exe"] : linter === "biome" ? ["biome"] : ["eslint"];
|
|
43697
|
+
const nativeExecutable = resolveExecutableFromPath(nativeNames, envPath, platform);
|
|
43698
|
+
if (nativeExecutable) {
|
|
43699
|
+
return {
|
|
43700
|
+
linter,
|
|
43701
|
+
executable: nativeExecutable,
|
|
43702
|
+
argsPrefix: [],
|
|
43703
|
+
displayPrefix: [nativeExecutable],
|
|
43704
|
+
source: "path-native"
|
|
43705
|
+
};
|
|
43706
|
+
}
|
|
43707
|
+
const shimCandidate = findPathShimCandidate(linter, envPath, platform);
|
|
43708
|
+
if (!shimCandidate)
|
|
43709
|
+
return null;
|
|
43710
|
+
const shimTarget = resolvePathShimTarget(shimCandidate, linter, platform);
|
|
43711
|
+
if (!shimTarget)
|
|
43712
|
+
return null;
|
|
43713
|
+
return {
|
|
43714
|
+
linter,
|
|
43715
|
+
executable: _internals64.execPath(),
|
|
43716
|
+
argsPrefix: [shimTarget],
|
|
43717
|
+
displayPrefix: [path76.join(directory, NODE_MODULES, BIN_DIRECTORY, linter)],
|
|
43718
|
+
source: "path-shim"
|
|
43719
|
+
};
|
|
43720
|
+
}
|
|
43721
|
+
function getLintModeArgs(linter, mode) {
|
|
43722
|
+
if (linter === "biome") {
|
|
43723
|
+
return mode === "fix" ? ["check", "--write", "."] : ["check", "."];
|
|
43724
|
+
}
|
|
43725
|
+
return mode === "fix" ? [".", "--fix"] : ["."];
|
|
43726
|
+
}
|
|
43727
|
+
function combineOutput(result) {
|
|
43728
|
+
let output = result.stdout;
|
|
43729
|
+
if (result.stderr) {
|
|
43730
|
+
output += `${output ? `
|
|
43731
|
+
` : ""}${result.stderr}`;
|
|
43732
|
+
}
|
|
43733
|
+
const shouldTruncate = result.stdoutTruncated || result.stderrTruncated || output.length > MAX_OUTPUT_BYTES2;
|
|
43734
|
+
if (!shouldTruncate)
|
|
43735
|
+
return output;
|
|
43736
|
+
const trimmed = output.slice(0, MAX_OUTPUT_BYTES2);
|
|
43737
|
+
return `${trimmed}${OUTPUT_TRUNCATION_SUFFIX}`;
|
|
43738
|
+
}
|
|
43739
|
+
function buildExecutionError(mode, command, linter, result) {
|
|
43740
|
+
const reason = result.message ?? (result.status === "timeout" ? "command timed out" : result.status === "cancelled" ? "command was cancelled" : "unknown error");
|
|
43741
|
+
return {
|
|
43742
|
+
success: false,
|
|
43743
|
+
mode,
|
|
43744
|
+
linter,
|
|
43745
|
+
command,
|
|
43746
|
+
exitCode: result.exitCode ?? undefined,
|
|
43747
|
+
output: combineOutput(result),
|
|
43748
|
+
error: `Execution failed: ${reason}`
|
|
43749
|
+
};
|
|
43750
|
+
}
|
|
43751
|
+
async function probeResolvedCommand(command, cwd, abortSignal) {
|
|
43752
|
+
const result = await _internals64.runExternalTool({
|
|
43753
|
+
executable: command.executable,
|
|
43754
|
+
args: [...command.argsPrefix, "--version"],
|
|
43755
|
+
cwd,
|
|
43756
|
+
timeoutMs: LINTER_DETECT_TIMEOUT_MS,
|
|
43757
|
+
maxStdoutBytes: 4096,
|
|
43758
|
+
maxStderrBytes: 4096,
|
|
43759
|
+
abortSignal
|
|
43760
|
+
});
|
|
43761
|
+
return result.status === "completed" && result.exitCode === 0;
|
|
43762
|
+
}
|
|
43763
|
+
async function resolveLinterCommand(linter, directory) {
|
|
43764
|
+
const cwd = toAbsoluteDirectory(directory);
|
|
43765
|
+
return resolveLocalLinterCommand(linter, cwd) ?? resolvePathLinterCommand(linter, cwd);
|
|
43766
|
+
}
|
|
43767
|
+
async function detectResolvedLinter(directory, abortSignal) {
|
|
43768
|
+
if (!directory)
|
|
43769
|
+
return null;
|
|
43770
|
+
if (!_internals64.existsSync(directory))
|
|
43771
|
+
return null;
|
|
43772
|
+
const cwd = toAbsoluteDirectory(directory);
|
|
43773
|
+
for (const linter of SUPPORTED_LINTERS) {
|
|
43774
|
+
const resolved = await resolveLinterCommand(linter, cwd);
|
|
43775
|
+
if (!resolved)
|
|
43776
|
+
continue;
|
|
43777
|
+
if (await probeResolvedCommand(resolved, cwd, abortSignal)) {
|
|
43778
|
+
return resolved;
|
|
43779
|
+
}
|
|
43237
43780
|
}
|
|
43781
|
+
return null;
|
|
43238
43782
|
}
|
|
43239
43783
|
function detectRuff(cwd) {
|
|
43240
|
-
if (
|
|
43241
|
-
return
|
|
43784
|
+
if (_internals64.existsSync(path76.join(cwd, "ruff.toml")))
|
|
43785
|
+
return hasAdditionalCommand("ruff");
|
|
43242
43786
|
try {
|
|
43243
43787
|
const pyproject = path76.join(cwd, "pyproject.toml");
|
|
43244
|
-
if (
|
|
43245
|
-
const content =
|
|
43788
|
+
if (_internals64.existsSync(pyproject)) {
|
|
43789
|
+
const content = _internals64.readFileSync(pyproject, "utf-8");
|
|
43246
43790
|
if (content.includes("[tool.ruff]"))
|
|
43247
|
-
return
|
|
43791
|
+
return hasAdditionalCommand("ruff");
|
|
43248
43792
|
}
|
|
43249
43793
|
} catch {}
|
|
43250
43794
|
return false;
|
|
43251
43795
|
}
|
|
43252
43796
|
function detectClippy(cwd) {
|
|
43253
|
-
return
|
|
43797
|
+
return _internals64.existsSync(path76.join(cwd, "Cargo.toml")) && hasAdditionalCommand("cargo");
|
|
43254
43798
|
}
|
|
43255
43799
|
function detectGolangciLint(cwd) {
|
|
43256
|
-
return
|
|
43800
|
+
return _internals64.existsSync(path76.join(cwd, "go.mod")) && hasAdditionalCommand("golangci-lint");
|
|
43257
43801
|
}
|
|
43258
43802
|
function readTextFileSafe(filePath) {
|
|
43259
43803
|
try {
|
|
43260
|
-
return
|
|
43804
|
+
return _internals64.readFileSync(filePath, "utf-8");
|
|
43261
43805
|
} catch {
|
|
43262
43806
|
return "";
|
|
43263
43807
|
}
|
|
43264
43808
|
}
|
|
43265
|
-
function
|
|
43266
|
-
const
|
|
43267
|
-
|
|
43809
|
+
function resolveAdditionalExecutable(name) {
|
|
43810
|
+
const platform = _internals64.platform();
|
|
43811
|
+
if (platform !== "win32") {
|
|
43812
|
+
return _internals64.isCommandAvailable(name) ? name : null;
|
|
43813
|
+
}
|
|
43814
|
+
return resolveExecutableFromPath([`${name}.exe`], _internals64.pathEnv(), platform);
|
|
43815
|
+
}
|
|
43816
|
+
function resolveWindowsCommandInterpreter() {
|
|
43817
|
+
const candidate = _internals64.comSpec();
|
|
43818
|
+
if (!candidate || !path76.isAbsolute(candidate) || path76.basename(candidate).toLowerCase() !== "cmd.exe" || !isRegularFile(candidate)) {
|
|
43819
|
+
return null;
|
|
43820
|
+
}
|
|
43821
|
+
try {
|
|
43822
|
+
const canonical = _internals64.realpathSync(candidate);
|
|
43823
|
+
return path76.basename(canonical).toLowerCase() === "cmd.exe" ? canonical : null;
|
|
43824
|
+
} catch {
|
|
43825
|
+
return null;
|
|
43826
|
+
}
|
|
43827
|
+
}
|
|
43828
|
+
function buildWindowsBatchCommand(wrapperPath, args) {
|
|
43829
|
+
const interpreter = resolveWindowsCommandInterpreter();
|
|
43830
|
+
if (!interpreter)
|
|
43831
|
+
return null;
|
|
43832
|
+
let canonicalWrapper;
|
|
43833
|
+
try {
|
|
43834
|
+
canonicalWrapper = _internals64.realpathSync(wrapperPath);
|
|
43835
|
+
} catch {
|
|
43836
|
+
return null;
|
|
43837
|
+
}
|
|
43838
|
+
if (!isRegularFile(canonicalWrapper) || !WINDOWS_BATCH_WRAPPER_EXTENSIONS.includes(path76.extname(canonicalWrapper).toLowerCase())) {
|
|
43839
|
+
return null;
|
|
43840
|
+
}
|
|
43841
|
+
const tokens = [canonicalWrapper, ...args];
|
|
43842
|
+
if (tokens.some((token) => WINDOWS_CMD_UNSAFE_TOKEN.test(token)))
|
|
43843
|
+
return null;
|
|
43844
|
+
const command = `call ${tokens.map((token) => `"${token}"`).join(" ")}`;
|
|
43845
|
+
return [interpreter, "/d", "/s", "/v:off", "/c", command];
|
|
43846
|
+
}
|
|
43847
|
+
function resolveWindowsBatchCommandFromPath(name, args) {
|
|
43848
|
+
if (_internals64.platform() !== "win32")
|
|
43849
|
+
return null;
|
|
43850
|
+
const wrapper = resolveExecutableFromPath(WINDOWS_BATCH_WRAPPER_EXTENSIONS.map((extension) => `${name}${extension}`), _internals64.pathEnv(), "win32");
|
|
43851
|
+
return wrapper ? buildWindowsBatchCommand(wrapper, args) : null;
|
|
43852
|
+
}
|
|
43853
|
+
function resolveContainedWindowsBatchCommand(cwd, fileName, args) {
|
|
43854
|
+
if (_internals64.platform() !== "win32")
|
|
43855
|
+
return null;
|
|
43856
|
+
const candidate = path76.join(cwd, fileName);
|
|
43857
|
+
if (!isRegularFile(candidate))
|
|
43858
|
+
return null;
|
|
43859
|
+
let canonicalCwd;
|
|
43860
|
+
let canonicalCandidate;
|
|
43861
|
+
try {
|
|
43862
|
+
canonicalCwd = _internals64.realpathSync(cwd);
|
|
43863
|
+
canonicalCandidate = _internals64.realpathSync(candidate);
|
|
43864
|
+
} catch {
|
|
43865
|
+
return null;
|
|
43866
|
+
}
|
|
43867
|
+
const relative10 = path76.relative(canonicalCwd, canonicalCandidate);
|
|
43868
|
+
if (relative10 === "" || relative10.startsWith("..") || path76.isAbsolute(relative10)) {
|
|
43869
|
+
return null;
|
|
43870
|
+
}
|
|
43871
|
+
return buildWindowsBatchCommand(canonicalCandidate, args);
|
|
43872
|
+
}
|
|
43873
|
+
function buildAdditionalCommand(name, args) {
|
|
43874
|
+
const executable = resolveAdditionalExecutable(name);
|
|
43875
|
+
if (executable)
|
|
43876
|
+
return [executable, ...args];
|
|
43877
|
+
return resolveWindowsBatchCommandFromPath(name, args);
|
|
43878
|
+
}
|
|
43879
|
+
function hasAdditionalCommand(name) {
|
|
43880
|
+
return buildAdditionalCommand(name, []) !== null;
|
|
43881
|
+
}
|
|
43882
|
+
function resolvePhpVendorCommand(cwd, name) {
|
|
43883
|
+
const relativeProxy = path76.join("vendor", "bin", name);
|
|
43884
|
+
if (!_internals64.existsSync(path76.join(cwd, relativeProxy)))
|
|
43885
|
+
return null;
|
|
43886
|
+
if (_internals64.platform() !== "win32")
|
|
43887
|
+
return [relativeProxy];
|
|
43888
|
+
const phpExecutable = resolveAdditionalExecutable("php");
|
|
43889
|
+
return phpExecutable ? [phpExecutable, relativeProxy] : null;
|
|
43890
|
+
}
|
|
43891
|
+
function hasCheckstyleGradleSignal(cwd) {
|
|
43892
|
+
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path76.join(cwd, file)).filter((file) => _internals64.existsSync(file));
|
|
43893
|
+
return _internals64.existsSync(path76.join(cwd, "checkstyle.xml")) || _internals64.existsSync(path76.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
|
|
43894
|
+
}
|
|
43895
|
+
function resolveCheckstyleCommand(cwd) {
|
|
43896
|
+
const hasMavenProject = _internals64.existsSync(path76.join(cwd, "pom.xml"));
|
|
43897
|
+
const hasGradleSignal = hasCheckstyleGradleSignal(cwd);
|
|
43898
|
+
if (hasGradleSignal) {
|
|
43899
|
+
if (_internals64.platform() === "win32") {
|
|
43900
|
+
const gradlew = resolveContainedWindowsBatchCommand(cwd, "gradlew.bat", [
|
|
43901
|
+
"checkstyleMain"
|
|
43902
|
+
]);
|
|
43903
|
+
if (gradlew)
|
|
43904
|
+
return gradlew;
|
|
43905
|
+
} else {
|
|
43906
|
+
const gradlew = path76.join(cwd, "gradlew");
|
|
43907
|
+
if (_internals64.existsSync(gradlew))
|
|
43908
|
+
return [gradlew, "checkstyleMain"];
|
|
43909
|
+
}
|
|
43910
|
+
const gradle = buildAdditionalCommand("gradle", ["checkstyleMain"]);
|
|
43911
|
+
if (gradle) {
|
|
43912
|
+
return gradle;
|
|
43913
|
+
}
|
|
43914
|
+
}
|
|
43915
|
+
const maven = buildAdditionalCommand("mvn", ["checkstyle:check"]);
|
|
43916
|
+
if (hasMavenProject && maven) {
|
|
43917
|
+
return maven;
|
|
43918
|
+
}
|
|
43919
|
+
return null;
|
|
43268
43920
|
}
|
|
43269
|
-
function
|
|
43270
|
-
|
|
43271
|
-
const localWin = path76.join(cwd, "vendor", "bin", `${name}.bat`);
|
|
43272
|
-
return fs30.existsSync(local) || fs30.existsSync(localWin);
|
|
43921
|
+
function isUnsafeShellWrapperExecutable(executable, platform = _internals64.platform()) {
|
|
43922
|
+
return platform === "win32" && UNSAFE_SHELL_WRAPPER_EXTENSIONS.has(path76.extname(executable).toLowerCase());
|
|
43273
43923
|
}
|
|
43274
43924
|
function detectCheckstyle(cwd) {
|
|
43275
|
-
|
|
43276
|
-
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path76.join(cwd, file)).filter((file) => fs30.existsSync(file));
|
|
43277
|
-
const hasGradleCheckstyleSignal = fs30.existsSync(path76.join(cwd, "checkstyle.xml")) || fs30.existsSync(path76.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
|
|
43278
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs30.existsSync(path76.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
43279
|
-
return (hasMaven || hasGradleCheckstyleSignal) && hasBinary;
|
|
43925
|
+
return resolveCheckstyleCommand(cwd) !== null;
|
|
43280
43926
|
}
|
|
43281
43927
|
function hasRootKotlinFile(cwd) {
|
|
43282
43928
|
try {
|
|
43283
|
-
return
|
|
43929
|
+
return _internals64.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
43284
43930
|
} catch {
|
|
43285
43931
|
return false;
|
|
43286
43932
|
}
|
|
@@ -43290,59 +43936,59 @@ function buildGradleHasKotlinSignal(cwd) {
|
|
|
43290
43936
|
return /\b(kotlin|org\.jetbrains\.kotlin|ktlint)\b/i.test(content);
|
|
43291
43937
|
}
|
|
43292
43938
|
function detectKtlint(cwd) {
|
|
43293
|
-
const hasKotlin =
|
|
43294
|
-
return hasKotlin &&
|
|
43939
|
+
const hasKotlin = _internals64.existsSync(path76.join(cwd, "build.gradle.kts")) || _internals64.existsSync(path76.join(cwd, "build.gradle")) && buildGradleHasKotlinSignal(cwd) || hasRootKotlinFile(cwd);
|
|
43940
|
+
return hasKotlin && hasAdditionalCommand("ktlint");
|
|
43295
43941
|
}
|
|
43296
43942
|
function detectPhpLinter(cwd) {
|
|
43297
|
-
if ((
|
|
43943
|
+
if ((_internals64.existsSync(path76.join(cwd, "phpstan.neon")) || _internals64.existsSync(path76.join(cwd, "phpstan.neon.dist"))) && resolvePhpVendorCommand(cwd, "phpstan") !== null) {
|
|
43298
43944
|
return "phpstan";
|
|
43299
43945
|
}
|
|
43300
|
-
if (
|
|
43946
|
+
if (_internals64.existsSync(path76.join(cwd, "pint.json")) && resolvePhpVendorCommand(cwd, "pint") !== null) {
|
|
43301
43947
|
return "pint";
|
|
43302
43948
|
}
|
|
43303
|
-
if (
|
|
43949
|
+
if (_internals64.existsSync(path76.join(cwd, ".php-cs-fixer.php")) && resolvePhpVendorCommand(cwd, "php-cs-fixer") !== null) {
|
|
43304
43950
|
return "php-cs-fixer";
|
|
43305
43951
|
}
|
|
43306
|
-
if (
|
|
43952
|
+
if (_internals64.existsSync(path76.join(cwd, "phpcs.xml")) && resolvePhpVendorCommand(cwd, "phpcs") !== null) {
|
|
43307
43953
|
return "phpcs";
|
|
43308
43954
|
}
|
|
43309
43955
|
return null;
|
|
43310
43956
|
}
|
|
43311
43957
|
function detectDotnetFormat(cwd) {
|
|
43312
43958
|
try {
|
|
43313
|
-
const files =
|
|
43959
|
+
const files = _internals64.readdirSync(cwd);
|
|
43314
43960
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
43315
|
-
return hasCsproj &&
|
|
43961
|
+
return hasCsproj && hasAdditionalCommand("dotnet");
|
|
43316
43962
|
} catch {
|
|
43317
43963
|
return false;
|
|
43318
43964
|
}
|
|
43319
43965
|
}
|
|
43320
43966
|
function detectCppcheck(cwd) {
|
|
43321
|
-
if (
|
|
43322
|
-
return
|
|
43967
|
+
if (_internals64.existsSync(path76.join(cwd, "CMakeLists.txt"))) {
|
|
43968
|
+
return hasAdditionalCommand("cppcheck");
|
|
43323
43969
|
}
|
|
43324
43970
|
try {
|
|
43325
43971
|
const dirsToCheck = [cwd, path76.join(cwd, "src")];
|
|
43326
43972
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
43327
43973
|
try {
|
|
43328
|
-
return
|
|
43974
|
+
return _internals64.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
43329
43975
|
} catch {
|
|
43330
43976
|
return false;
|
|
43331
43977
|
}
|
|
43332
43978
|
});
|
|
43333
|
-
return hasCpp &&
|
|
43979
|
+
return hasCpp && hasAdditionalCommand("cppcheck");
|
|
43334
43980
|
} catch {
|
|
43335
43981
|
return false;
|
|
43336
43982
|
}
|
|
43337
43983
|
}
|
|
43338
43984
|
function detectSwiftlint(cwd) {
|
|
43339
|
-
return
|
|
43985
|
+
return _internals64.existsSync(path76.join(cwd, "Package.swift")) && hasAdditionalCommand("swiftlint");
|
|
43340
43986
|
}
|
|
43341
43987
|
function detectDartAnalyze(cwd) {
|
|
43342
|
-
return
|
|
43988
|
+
return _internals64.existsSync(path76.join(cwd, "pubspec.yaml")) && hasAdditionalCommand("dart");
|
|
43343
43989
|
}
|
|
43344
43990
|
function detectRubocop(cwd) {
|
|
43345
|
-
return (
|
|
43991
|
+
return (_internals64.existsSync(path76.join(cwd, "Gemfile")) || _internals64.existsSync(path76.join(cwd, "gems.rb")) || _internals64.existsSync(path76.join(cwd, ".rubocop.yml"))) && (hasAdditionalCommand("rubocop") || hasAdditionalCommand("bundle"));
|
|
43346
43992
|
}
|
|
43347
43993
|
function detectAdditionalLinter(cwd) {
|
|
43348
43994
|
if (detectRuff(cwd))
|
|
@@ -43370,208 +44016,179 @@ function detectAdditionalLinter(cwd) {
|
|
|
43370
44016
|
return "rubocop";
|
|
43371
44017
|
return null;
|
|
43372
44018
|
}
|
|
43373
|
-
function findBinInAncestors(startDir, binName) {
|
|
43374
|
-
let dir = startDir;
|
|
43375
|
-
while (true) {
|
|
43376
|
-
const candidate = path76.join(dir, "node_modules", ".bin", binName);
|
|
43377
|
-
if (fs30.existsSync(candidate))
|
|
43378
|
-
return candidate;
|
|
43379
|
-
const parent = path76.dirname(dir);
|
|
43380
|
-
if (parent === dir)
|
|
43381
|
-
break;
|
|
43382
|
-
dir = parent;
|
|
43383
|
-
}
|
|
43384
|
-
return null;
|
|
43385
|
-
}
|
|
43386
|
-
function findBinInEnvPath(binName) {
|
|
43387
|
-
const searchPath = process.env.PATH ?? "";
|
|
43388
|
-
for (const dir of searchPath.split(path76.delimiter)) {
|
|
43389
|
-
if (!dir)
|
|
43390
|
-
continue;
|
|
43391
|
-
const candidate = path76.join(dir, binName);
|
|
43392
|
-
if (fs30.existsSync(candidate))
|
|
43393
|
-
return candidate;
|
|
43394
|
-
}
|
|
43395
|
-
return null;
|
|
43396
|
-
}
|
|
43397
44019
|
async function detectAvailableLinter(directory) {
|
|
43398
|
-
|
|
43399
|
-
|
|
43400
|
-
if (!fs30.existsSync(directory))
|
|
43401
|
-
return null;
|
|
43402
|
-
const projectDir = directory;
|
|
43403
|
-
const isWindows = process.platform === "win32";
|
|
43404
|
-
const biomeBin = isWindows ? path76.join(projectDir, "node_modules", ".bin", "biome.EXE") : path76.join(projectDir, "node_modules", ".bin", "biome");
|
|
43405
|
-
const eslintBin = isWindows ? path76.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path76.join(projectDir, "node_modules", ".bin", "eslint");
|
|
43406
|
-
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
43407
|
-
if (localResult)
|
|
43408
|
-
return localResult;
|
|
43409
|
-
const biomeAncestor = findBinInAncestors(path76.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
43410
|
-
const eslintAncestor = findBinInAncestors(path76.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
43411
|
-
if (biomeAncestor || eslintAncestor) {
|
|
43412
|
-
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
43413
|
-
}
|
|
43414
|
-
const pathBiome = findBinInEnvPath(isWindows ? "biome.EXE" : "biome");
|
|
43415
|
-
const pathEslint = findBinInEnvPath(isWindows ? "eslint.cmd" : "eslint");
|
|
43416
|
-
if (pathBiome || pathEslint) {
|
|
43417
|
-
return _detectAvailableLinter(projectDir, pathBiome ?? biomeBin, pathEslint ?? eslintBin);
|
|
43418
|
-
}
|
|
43419
|
-
return null;
|
|
44020
|
+
const resolved = await detectResolvedLinter(directory);
|
|
44021
|
+
return resolved?.linter ?? null;
|
|
43420
44022
|
}
|
|
43421
|
-
async function
|
|
43422
|
-
const
|
|
43423
|
-
|
|
43424
|
-
|
|
43425
|
-
stdout: "pipe",
|
|
43426
|
-
stderr: "pipe"
|
|
43427
|
-
});
|
|
43428
|
-
const biomeExit = biomeProc.exited;
|
|
43429
|
-
const timeout = new Promise((resolve23) => setTimeout(() => resolve23("timeout"), DETECT_TIMEOUT));
|
|
43430
|
-
const result = await Promise.race([biomeExit, timeout]);
|
|
43431
|
-
if (result === "timeout") {
|
|
43432
|
-
biomeProc.kill();
|
|
43433
|
-
} else if (biomeProc.exitCode === 0 && fs30.existsSync(biomeBin)) {
|
|
43434
|
-
return "biome";
|
|
43435
|
-
}
|
|
43436
|
-
} catch {}
|
|
43437
|
-
try {
|
|
43438
|
-
const eslintProc = bunSpawn([eslintBin, "--version"], {
|
|
43439
|
-
stdout: "pipe",
|
|
43440
|
-
stderr: "pipe"
|
|
43441
|
-
});
|
|
43442
|
-
const eslintExit = eslintProc.exited;
|
|
43443
|
-
const timeout = new Promise((resolve23) => setTimeout(() => resolve23("timeout"), DETECT_TIMEOUT));
|
|
43444
|
-
const result = await Promise.race([eslintExit, timeout]);
|
|
43445
|
-
if (result === "timeout") {
|
|
43446
|
-
eslintProc.kill();
|
|
43447
|
-
} else if (eslintProc.exitCode === 0 && fs30.existsSync(eslintBin)) {
|
|
43448
|
-
return "eslint";
|
|
43449
|
-
}
|
|
43450
|
-
} catch {}
|
|
43451
|
-
return null;
|
|
43452
|
-
}
|
|
43453
|
-
async function runLint(linter, mode, directory) {
|
|
43454
|
-
const command = getLinterCommand(linter, mode, directory);
|
|
43455
|
-
const commandStr = command.join(" ");
|
|
44023
|
+
async function runResolvedLint(command, mode, directory, abortSignal) {
|
|
44024
|
+
const lintArgs = getLintModeArgs(command.linter, mode);
|
|
44025
|
+
const displayCommand = [...command.displayPrefix, ...lintArgs];
|
|
44026
|
+
const commandStr = displayCommand.join(" ");
|
|
43456
44027
|
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
43457
44028
|
return {
|
|
43458
44029
|
success: false,
|
|
43459
44030
|
mode,
|
|
43460
|
-
linter,
|
|
43461
|
-
command,
|
|
44031
|
+
linter: command.linter,
|
|
44032
|
+
command: displayCommand,
|
|
43462
44033
|
error: "Command exceeds maximum allowed length"
|
|
43463
44034
|
};
|
|
43464
44035
|
}
|
|
43465
|
-
|
|
43466
|
-
|
|
43467
|
-
|
|
43468
|
-
|
|
43469
|
-
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
|
|
43473
|
-
|
|
43474
|
-
|
|
43475
|
-
|
|
43476
|
-
|
|
43477
|
-
|
|
43478
|
-
|
|
43479
|
-
|
|
44036
|
+
const runResult = await _internals64.runExternalTool({
|
|
44037
|
+
executable: command.executable,
|
|
44038
|
+
args: [...command.argsPrefix, ...lintArgs],
|
|
44039
|
+
cwd: toAbsoluteDirectory(directory),
|
|
44040
|
+
timeoutMs: LINTER_RUN_TIMEOUT_MS,
|
|
44041
|
+
maxStdoutBytes: MAX_OUTPUT_BYTES2,
|
|
44042
|
+
maxStderrBytes: MAX_OUTPUT_BYTES2,
|
|
44043
|
+
abortSignal
|
|
44044
|
+
});
|
|
44045
|
+
if (runResult.status !== "completed") {
|
|
44046
|
+
return buildExecutionError(mode, displayCommand, command.linter, runResult);
|
|
44047
|
+
}
|
|
44048
|
+
const exitCode = runResult.exitCode ?? 0;
|
|
44049
|
+
const result = {
|
|
44050
|
+
success: true,
|
|
44051
|
+
mode,
|
|
44052
|
+
linter: command.linter,
|
|
44053
|
+
command: displayCommand,
|
|
44054
|
+
exitCode,
|
|
44055
|
+
output: combineOutput(runResult)
|
|
44056
|
+
};
|
|
44057
|
+
if (exitCode === 0) {
|
|
44058
|
+
result.message = `${command.linter} ${mode} completed successfully with no issues`;
|
|
44059
|
+
} else if (mode === "fix") {
|
|
44060
|
+
result.message = `${command.linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
44061
|
+
} else {
|
|
44062
|
+
result.message = `${command.linter} check found issues (exit code ${exitCode}).`;
|
|
44063
|
+
}
|
|
44064
|
+
return result;
|
|
44065
|
+
}
|
|
44066
|
+
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
44067
|
+
switch (linter) {
|
|
44068
|
+
case "ruff":
|
|
44069
|
+
return buildAdditionalCommand("ruff", mode === "fix" ? ["check", "--fix", "."] : ["check", "."]);
|
|
44070
|
+
case "clippy":
|
|
44071
|
+
return buildAdditionalCommand("cargo", mode === "fix" ? ["clippy", "--fix", "--allow-dirty"] : ["clippy"]);
|
|
44072
|
+
case "golangci-lint":
|
|
44073
|
+
return buildAdditionalCommand("golangci-lint", mode === "fix" ? ["run", "--fix"] : ["run"]);
|
|
44074
|
+
case "checkstyle":
|
|
44075
|
+
return resolveCheckstyleCommand(cwd);
|
|
44076
|
+
case "ktlint":
|
|
44077
|
+
return buildAdditionalCommand("ktlint", mode === "fix" ? ["--format"] : []);
|
|
44078
|
+
case "dotnet-format":
|
|
44079
|
+
return buildAdditionalCommand("dotnet", mode === "fix" ? ["format"] : ["format", "--verify-no-changes"]);
|
|
44080
|
+
case "cppcheck":
|
|
44081
|
+
return buildAdditionalCommand("cppcheck", ["--enable=all", "."]);
|
|
44082
|
+
case "swiftlint":
|
|
44083
|
+
return buildAdditionalCommand("swiftlint", mode === "fix" ? ["--fix"] : []);
|
|
44084
|
+
case "dart-analyze":
|
|
44085
|
+
return buildAdditionalCommand("dart", mode === "fix" ? ["fix"] : ["analyze"]);
|
|
44086
|
+
case "rubocop": {
|
|
44087
|
+
const bundle = buildAdditionalCommand("bundle", [
|
|
44088
|
+
"exec",
|
|
44089
|
+
"rubocop",
|
|
44090
|
+
...mode === "fix" ? ["-A"] : []
|
|
44091
|
+
]);
|
|
44092
|
+
if (bundle) {
|
|
44093
|
+
return bundle;
|
|
44094
|
+
}
|
|
44095
|
+
return buildAdditionalCommand("rubocop", mode === "fix" ? ["-A"] : []);
|
|
43480
44096
|
}
|
|
43481
|
-
|
|
43482
|
-
|
|
43483
|
-
...
|
|
44097
|
+
case "phpstan": {
|
|
44098
|
+
const base = resolvePhpVendorCommand(cwd, "phpstan");
|
|
44099
|
+
return base ? [...base, "analyse"] : null;
|
|
43484
44100
|
}
|
|
43485
|
-
|
|
43486
|
-
|
|
43487
|
-
mode,
|
|
43488
|
-
linter,
|
|
43489
|
-
command,
|
|
43490
|
-
exitCode,
|
|
43491
|
-
output
|
|
43492
|
-
};
|
|
43493
|
-
if (exitCode === 0) {
|
|
43494
|
-
result.message = `${linter} ${mode} completed successfully with no issues`;
|
|
43495
|
-
} else if (mode === "fix") {
|
|
43496
|
-
result.message = `${linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
43497
|
-
} else {
|
|
43498
|
-
result.message = `${linter} check found issues (exit code ${exitCode}).`;
|
|
44101
|
+
case "pint": {
|
|
44102
|
+
const base = resolvePhpVendorCommand(cwd, "pint");
|
|
44103
|
+
return base ? mode === "fix" ? base : [...base, "--test"] : null;
|
|
43499
44104
|
}
|
|
43500
|
-
|
|
43501
|
-
|
|
44105
|
+
case "php-cs-fixer": {
|
|
44106
|
+
const base = resolvePhpVendorCommand(cwd, "php-cs-fixer");
|
|
44107
|
+
return base ? mode === "fix" ? [...base, "fix"] : [...base, "fix", "--dry-run", "--diff"] : null;
|
|
44108
|
+
}
|
|
44109
|
+
case "phpcs":
|
|
44110
|
+
return resolvePhpVendorCommand(cwd, "phpcs");
|
|
44111
|
+
}
|
|
44112
|
+
}
|
|
44113
|
+
async function runLint(linter, mode, directory, abortSignal) {
|
|
44114
|
+
const resolved = await _internals64.resolveLinterCommand(linter, directory);
|
|
44115
|
+
if (!resolved) {
|
|
43502
44116
|
return {
|
|
43503
44117
|
success: false,
|
|
43504
44118
|
mode,
|
|
43505
44119
|
linter,
|
|
43506
|
-
|
|
43507
|
-
error: error2 instanceof Error ? `Execution failed: ${error2.message}` : "Execution failed: unknown error"
|
|
44120
|
+
error: `No safely resolved ${linter} executable found`
|
|
43508
44121
|
};
|
|
43509
44122
|
}
|
|
44123
|
+
return runResolvedLint(resolved, mode, directory, abortSignal);
|
|
43510
44124
|
}
|
|
43511
|
-
async function runAdditionalLint(linter, mode, cwd) {
|
|
44125
|
+
async function runAdditionalLint(linter, mode, cwd, abortSignal) {
|
|
43512
44126
|
const command = getAdditionalLinterCommand(linter, mode, cwd);
|
|
43513
|
-
|
|
43514
|
-
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
44127
|
+
if (!command) {
|
|
43515
44128
|
return {
|
|
43516
44129
|
success: false,
|
|
43517
44130
|
mode,
|
|
43518
44131
|
linter,
|
|
43519
|
-
command
|
|
43520
|
-
error: "Command exceeds maximum allowed length"
|
|
44132
|
+
error: `No safely executable ${linter} command found`
|
|
43521
44133
|
};
|
|
43522
44134
|
}
|
|
43523
|
-
|
|
43524
|
-
|
|
43525
|
-
|
|
43526
|
-
|
|
43527
|
-
cwd
|
|
43528
|
-
});
|
|
43529
|
-
const [stdout, stderr] = await Promise.all([
|
|
43530
|
-
proc.stdout.text(),
|
|
43531
|
-
proc.stderr.text()
|
|
43532
|
-
]);
|
|
43533
|
-
const exitCode = await proc.exited;
|
|
43534
|
-
let output = stdout;
|
|
43535
|
-
if (stderr) {
|
|
43536
|
-
output += (output ? `
|
|
43537
|
-
` : "") + stderr;
|
|
43538
|
-
}
|
|
43539
|
-
if (output.length > MAX_OUTPUT_BYTES2) {
|
|
43540
|
-
output = `${output.slice(0, MAX_OUTPUT_BYTES2)}
|
|
43541
|
-
... (output truncated)`;
|
|
43542
|
-
}
|
|
43543
|
-
const result = {
|
|
43544
|
-
success: true,
|
|
44135
|
+
const commandStr = command.join(" ");
|
|
44136
|
+
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
44137
|
+
return {
|
|
44138
|
+
success: false,
|
|
43545
44139
|
mode,
|
|
43546
44140
|
linter,
|
|
43547
44141
|
command,
|
|
43548
|
-
|
|
43549
|
-
output
|
|
44142
|
+
error: "Command exceeds maximum allowed length"
|
|
43550
44143
|
};
|
|
43551
|
-
|
|
43552
|
-
|
|
43553
|
-
|
|
43554
|
-
result.message = `${linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
43555
|
-
} else {
|
|
43556
|
-
result.message = `${linter} check found issues (exit code ${exitCode}).`;
|
|
43557
|
-
}
|
|
43558
|
-
return result;
|
|
43559
|
-
} catch (error2) {
|
|
44144
|
+
}
|
|
44145
|
+
const [executable, ...args] = command;
|
|
44146
|
+
if (isUnsafeShellWrapperExecutable(executable)) {
|
|
43560
44147
|
return {
|
|
43561
44148
|
success: false,
|
|
43562
44149
|
mode,
|
|
43563
44150
|
linter,
|
|
43564
44151
|
command,
|
|
43565
|
-
error:
|
|
44152
|
+
error: `No safely executable ${linter} command found`
|
|
43566
44153
|
};
|
|
43567
44154
|
}
|
|
44155
|
+
const runResult = await _internals64.runExternalTool({
|
|
44156
|
+
executable,
|
|
44157
|
+
args,
|
|
44158
|
+
cwd: toAbsoluteDirectory(cwd),
|
|
44159
|
+
timeoutMs: LINTER_RUN_TIMEOUT_MS,
|
|
44160
|
+
maxStdoutBytes: MAX_OUTPUT_BYTES2,
|
|
44161
|
+
maxStderrBytes: MAX_OUTPUT_BYTES2,
|
|
44162
|
+
abortSignal,
|
|
44163
|
+
windowsVerbatimArguments: _internals64.platform() === "win32" && path76.basename(executable).toLowerCase() === "cmd.exe"
|
|
44164
|
+
});
|
|
44165
|
+
if (runResult.status !== "completed") {
|
|
44166
|
+
return buildExecutionError(mode, command, linter, runResult);
|
|
44167
|
+
}
|
|
44168
|
+
const exitCode = runResult.exitCode ?? 0;
|
|
44169
|
+
const result = {
|
|
44170
|
+
success: true,
|
|
44171
|
+
mode,
|
|
44172
|
+
linter,
|
|
44173
|
+
command,
|
|
44174
|
+
exitCode,
|
|
44175
|
+
output: combineOutput(runResult)
|
|
44176
|
+
};
|
|
44177
|
+
if (exitCode === 0) {
|
|
44178
|
+
result.message = `${linter} ${mode} completed successfully with no issues`;
|
|
44179
|
+
} else if (mode === "fix") {
|
|
44180
|
+
result.message = `${linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
44181
|
+
} else {
|
|
44182
|
+
result.message = `${linter} check found issues (exit code ${exitCode}).`;
|
|
44183
|
+
}
|
|
44184
|
+
return result;
|
|
43568
44185
|
}
|
|
43569
44186
|
var lint = createSwarmTool({
|
|
43570
44187
|
description: "Run project linter in check or fix mode. Supports biome, eslint (JS/TS), ruff (Python), clippy (Rust), golangci-lint (Go), checkstyle (Java), ktlint (Kotlin), dotnet-format (C#), cppcheck (C/C++), swiftlint (Swift), dart analyze (Dart), and rubocop (Ruby). Returns JSON with success status, exit code, and output for architect pre-reviewer gate. Use check mode for CI/linting and fix mode to automatically apply fixes.",
|
|
43571
44188
|
args: {
|
|
43572
44189
|
mode: exports_external.enum(["fix", "check"]).describe('Linting mode: "check" for read-only lint check, "fix" to automatically apply fixes')
|
|
43573
44190
|
},
|
|
43574
|
-
async execute(args, directory) {
|
|
44191
|
+
async execute(args, directory, ctx) {
|
|
43575
44192
|
if (!validateArgs(args)) {
|
|
43576
44193
|
const errorResult2 = {
|
|
43577
44194
|
success: false,
|
|
@@ -43590,15 +44207,15 @@ var lint = createSwarmTool({
|
|
|
43590
44207
|
}
|
|
43591
44208
|
const { mode } = args;
|
|
43592
44209
|
const cwd = directory;
|
|
43593
|
-
const
|
|
43594
|
-
if (
|
|
43595
|
-
const result = await _internals64.
|
|
44210
|
+
const resolvedLinter = await _internals64.detectResolvedLinter(directory, ctx?.abort);
|
|
44211
|
+
if (resolvedLinter) {
|
|
44212
|
+
const result = await _internals64.runResolvedLint(resolvedLinter, mode, directory, ctx?.abort);
|
|
43596
44213
|
return JSON.stringify(result, null, 2);
|
|
43597
44214
|
}
|
|
43598
44215
|
const additionalLinter = _internals64.detectAdditionalLinter(cwd);
|
|
43599
44216
|
if (additionalLinter) {
|
|
43600
44217
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
43601
|
-
const result = await _internals64.runAdditionalLint(additionalLinter, mode, cwd);
|
|
44218
|
+
const result = await _internals64.runAdditionalLint(additionalLinter, mode, cwd, ctx?.abort);
|
|
43602
44219
|
return JSON.stringify(result, null, 2);
|
|
43603
44220
|
}
|
|
43604
44221
|
const errorResult = {
|
|
@@ -43613,10 +44230,31 @@ For Rust: rustup component add clippy`
|
|
|
43613
44230
|
}
|
|
43614
44231
|
});
|
|
43615
44232
|
var _internals64 = {
|
|
44233
|
+
MAX_PACKAGE_MANIFEST_BYTES,
|
|
44234
|
+
MAX_PATH_SHIM_BYTES,
|
|
44235
|
+
arch: () => process.arch,
|
|
44236
|
+
closeSync: fs30.closeSync,
|
|
44237
|
+
comSpec: () => process.env.ComSpec,
|
|
44238
|
+
detectAdditionalLinter,
|
|
43616
44239
|
detectAvailableLinter,
|
|
44240
|
+
detectResolvedLinter,
|
|
44241
|
+
execPath: () => process.execPath,
|
|
44242
|
+
existsSync: fs30.existsSync,
|
|
44243
|
+
fstatSync: fs30.fstatSync,
|
|
44244
|
+
isCommandAvailable,
|
|
44245
|
+
openSync: fs30.openSync,
|
|
44246
|
+
pathEnv: () => process.env.PATH ?? "",
|
|
44247
|
+
platform: () => process.platform,
|
|
44248
|
+
readFileSync: fs30.readFileSync,
|
|
44249
|
+
readSync: fs30.readSync,
|
|
44250
|
+
readdirSync: fs30.readdirSync,
|
|
44251
|
+
realpathSync: fs30.realpathSync,
|
|
44252
|
+
resolveLinterCommand,
|
|
44253
|
+
runAdditionalLint,
|
|
44254
|
+
runExternalTool,
|
|
43617
44255
|
runLint,
|
|
43618
|
-
|
|
43619
|
-
|
|
44256
|
+
runResolvedLint,
|
|
44257
|
+
statSync: fs30.statSync
|
|
43620
44258
|
};
|
|
43621
44259
|
|
|
43622
44260
|
// src/tools/secretscan.ts
|
|
@@ -43980,8 +44618,19 @@ function createRedactedContext(line, findings) {
|
|
|
43980
44618
|
return `${result.slice(0, edgeLength)}${truncationMarker}${result.slice(-remaining)}`;
|
|
43981
44619
|
}
|
|
43982
44620
|
var O_NOFOLLOW = process.platform !== "win32" ? fs31.constants.O_NOFOLLOW : undefined;
|
|
43983
|
-
function
|
|
43984
|
-
|
|
44621
|
+
function getStableFileIdentity(stat6) {
|
|
44622
|
+
const { dev, ino } = stat6;
|
|
44623
|
+
if (dev < 0n || ino < 0n || dev === 0n && ino === 0n) {
|
|
44624
|
+
return null;
|
|
44625
|
+
}
|
|
44626
|
+
return `${dev}:${ino}`;
|
|
44627
|
+
}
|
|
44628
|
+
function readBoundedFile(filePath, expectedPathStat) {
|
|
44629
|
+
const expectedIdentity = getStableFileIdentity(expectedPathStat);
|
|
44630
|
+
if (expectedIdentity === null) {
|
|
44631
|
+
return { status: "incomplete", reason: "read_error" };
|
|
44632
|
+
}
|
|
44633
|
+
let fd = null;
|
|
43985
44634
|
try {
|
|
43986
44635
|
const flags = fs31.constants.O_RDONLY | (O_NOFOLLOW !== undefined ? O_NOFOLLOW : 0);
|
|
43987
44636
|
fd = _internals65.openFile(filePath, flags);
|
|
@@ -43989,13 +44638,17 @@ function readBoundedFile(filePath) {
|
|
|
43989
44638
|
return { status: "incomplete", reason: "read_error" };
|
|
43990
44639
|
}
|
|
43991
44640
|
let outcome;
|
|
44641
|
+
let closeFailed = false;
|
|
43992
44642
|
try {
|
|
43993
44643
|
const stat6 = _internals65.fstatFile(fd);
|
|
44644
|
+
const descriptorIdentity = getStableFileIdentity(stat6);
|
|
43994
44645
|
const initialSize = stat6.size;
|
|
43995
44646
|
if (!stat6.isFile()) {
|
|
43996
44647
|
outcome = { status: "incomplete", reason: "non_file" };
|
|
44648
|
+
} else if (descriptorIdentity === null || descriptorIdentity !== expectedIdentity) {
|
|
44649
|
+
outcome = { status: "incomplete", reason: "read_error" };
|
|
43997
44650
|
} else {
|
|
43998
|
-
const bufferLength =
|
|
44651
|
+
const bufferLength = initialSize >= BigInt(MAX_FILE_SIZE_BYTES3) ? MAX_FILE_SIZE_BYTES3 + 1 : Number(initialSize) + 1;
|
|
43999
44652
|
const buffer = Buffer.allocUnsafe(bufferLength);
|
|
44000
44653
|
let bytesRead = 0;
|
|
44001
44654
|
while (bytesRead < buffer.length) {
|
|
@@ -44005,10 +44658,15 @@ function readBoundedFile(filePath) {
|
|
|
44005
44658
|
bytesRead += count;
|
|
44006
44659
|
}
|
|
44007
44660
|
const postStat = _internals65.fstatFile(fd);
|
|
44008
|
-
|
|
44661
|
+
const postDescriptorIdentity = getStableFileIdentity(postStat);
|
|
44662
|
+
const postPathStat = _internals65.lstatFile(filePath);
|
|
44663
|
+
const postPathIdentity = getStableFileIdentity(postPathStat);
|
|
44664
|
+
if (!postStat.isFile() || postDescriptorIdentity === null || postDescriptorIdentity !== descriptorIdentity || postPathStat.isSymbolicLink() || !postPathStat.isFile() || postPathIdentity === null || postPathIdentity !== descriptorIdentity) {
|
|
44665
|
+
outcome = { status: "incomplete", reason: "read_error" };
|
|
44666
|
+
} else if (postStat.size !== initialSize) {
|
|
44009
44667
|
outcome = {
|
|
44010
44668
|
status: "incomplete",
|
|
44011
|
-
reason: postStat.size > MAX_FILE_SIZE_BYTES3 ? "oversized" : "read_error"
|
|
44669
|
+
reason: postStat.size > BigInt(MAX_FILE_SIZE_BYTES3) ? "oversized" : "read_error"
|
|
44012
44670
|
};
|
|
44013
44671
|
} else {
|
|
44014
44672
|
outcome = {
|
|
@@ -44020,25 +44678,30 @@ function readBoundedFile(filePath) {
|
|
|
44020
44678
|
}
|
|
44021
44679
|
} catch {
|
|
44022
44680
|
outcome = { status: "incomplete", reason: "read_error" };
|
|
44681
|
+
} finally {
|
|
44682
|
+
if (fd !== null) {
|
|
44683
|
+
try {
|
|
44684
|
+
_internals65.closeFile(fd);
|
|
44685
|
+
} catch {
|
|
44686
|
+
closeFailed = true;
|
|
44687
|
+
}
|
|
44688
|
+
}
|
|
44023
44689
|
}
|
|
44024
|
-
|
|
44025
|
-
_internals65.closeFile(fd);
|
|
44026
|
-
} catch {
|
|
44690
|
+
if (closeFailed)
|
|
44027
44691
|
return { status: "incomplete", reason: "read_error" };
|
|
44028
|
-
}
|
|
44029
44692
|
return outcome;
|
|
44030
44693
|
}
|
|
44031
44694
|
function scanFileForSecrets(filePath, mode) {
|
|
44032
44695
|
const findings = [];
|
|
44033
44696
|
try {
|
|
44034
|
-
const lstat3 =
|
|
44697
|
+
const lstat3 = _internals65.lstatFile(filePath);
|
|
44035
44698
|
if (lstat3.isSymbolicLink()) {
|
|
44036
44699
|
return mode === "explicit" ? { status: "incomplete", reason: "symlink" } : { status: "skipped", reason: "symlink" };
|
|
44037
44700
|
}
|
|
44038
44701
|
if (!lstat3.isFile()) {
|
|
44039
44702
|
return { status: "incomplete", reason: "non_file" };
|
|
44040
44703
|
}
|
|
44041
|
-
const readOutcome = readBoundedFile(filePath);
|
|
44704
|
+
const readOutcome = readBoundedFile(filePath, lstat3);
|
|
44042
44705
|
if (readOutcome.status === "incomplete")
|
|
44043
44706
|
return readOutcome;
|
|
44044
44707
|
const { buffer, truncated } = readOutcome;
|
|
@@ -44086,7 +44749,7 @@ function assertNever(value) {
|
|
|
44086
44749
|
throw new Error(`Unhandled secretscan outcome: ${String(value)}`);
|
|
44087
44750
|
}
|
|
44088
44751
|
async function yieldToEventLoop() {
|
|
44089
|
-
await new Promise((
|
|
44752
|
+
await new Promise((resolve25) => setImmediate(resolve25));
|
|
44090
44753
|
}
|
|
44091
44754
|
function serializeSecretscanResult(result) {
|
|
44092
44755
|
let findings = result.findings;
|
|
@@ -44125,14 +44788,14 @@ function isPathWithinScope(realPath, scanDir) {
|
|
|
44125
44788
|
}
|
|
44126
44789
|
var DISCOVERY_YIELD_INTERVAL = 100;
|
|
44127
44790
|
function toSafeRelativePath(rootDir, targetPath) {
|
|
44128
|
-
const
|
|
44129
|
-
if (!
|
|
44791
|
+
const relative11 = path77.relative(rootDir, targetPath).replace(/\\/g, "/");
|
|
44792
|
+
if (!relative11 || relative11 === ".")
|
|
44130
44793
|
return ".";
|
|
44131
|
-
if (
|
|
44132
|
-
const
|
|
44133
|
-
return
|
|
44794
|
+
if (relative11.startsWith("..") || path77.isAbsolute(relative11)) {
|
|
44795
|
+
const basename16 = path77.basename(targetPath).replace(/\\/g, "/");
|
|
44796
|
+
return basename16 || ".";
|
|
44134
44797
|
}
|
|
44135
|
-
return
|
|
44798
|
+
return relative11;
|
|
44136
44799
|
}
|
|
44137
44800
|
function recordIncompletePath(target, rootDir, targetPath, reason) {
|
|
44138
44801
|
if (target.length >= MAX_INCOMPLETE_PATHS) {
|
|
@@ -44714,10 +45377,10 @@ var _internals65 = {
|
|
|
44714
45377
|
now: Date.now,
|
|
44715
45378
|
yieldToEventLoop,
|
|
44716
45379
|
openFile: fs31.openSync,
|
|
44717
|
-
fstatFile: fs31.fstatSync,
|
|
45380
|
+
fstatFile: (fd) => fs31.fstatSync(fd, { bigint: true }),
|
|
44718
45381
|
readFileChunk: fs31.readSync,
|
|
44719
45382
|
closeFile: fs31.closeSync,
|
|
44720
|
-
lstatFile: fs31.lstatSync,
|
|
45383
|
+
lstatFile: (path78) => fs31.lstatSync(path78, { bigint: true }),
|
|
44721
45384
|
closeDirectory: (directory) => directory.closeSync()
|
|
44722
45385
|
};
|
|
44723
45386
|
|
|
@@ -45721,7 +46384,7 @@ var DISPATCH_FRAMEWORK_MAP = {
|
|
|
45721
46384
|
};
|
|
45722
46385
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
45723
46386
|
try {
|
|
45724
|
-
const { pickBackend } = await import("./dispatch-
|
|
46387
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45725
46388
|
const backend = await pickBackend(cwd);
|
|
45726
46389
|
if (!backend?.selectTestFramework)
|
|
45727
46390
|
return "none";
|
|
@@ -45737,7 +46400,7 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
|
|
|
45737
46400
|
if (framework === "none")
|
|
45738
46401
|
return null;
|
|
45739
46402
|
try {
|
|
45740
|
-
const { pickBackend } = await import("./dispatch-
|
|
46403
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45741
46404
|
const backend = await pickBackend(baseDir);
|
|
45742
46405
|
if (backend?.buildTestCommand) {
|
|
45743
46406
|
const cmd = backend.buildTestCommand(framework, files, baseDir, {
|
|
@@ -45757,7 +46420,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
45757
46420
|
if (framework === "none")
|
|
45758
46421
|
return null;
|
|
45759
46422
|
try {
|
|
45760
|
-
const { pickBackend } = await import("./dispatch-
|
|
46423
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45761
46424
|
const backend = await pickBackend(baseDir);
|
|
45762
46425
|
if (!backend?.parseTestOutput)
|
|
45763
46426
|
return null;
|
|
@@ -45967,21 +46630,21 @@ function hasCompoundTestExtension(filename) {
|
|
|
45967
46630
|
const lower = filename.toLowerCase();
|
|
45968
46631
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
45969
46632
|
}
|
|
45970
|
-
function isLanguageSpecificTestFile(
|
|
45971
|
-
const lower =
|
|
46633
|
+
function isLanguageSpecificTestFile(basename17) {
|
|
46634
|
+
const lower = basename17.toLowerCase();
|
|
45972
46635
|
if (lower.endsWith("_test.go"))
|
|
45973
46636
|
return true;
|
|
45974
46637
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
45975
46638
|
return true;
|
|
45976
46639
|
if (lower.endsWith("_spec.rb"))
|
|
45977
46640
|
return true;
|
|
45978
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
46641
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename17) || basename17.endsWith("Test.java") || basename17.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
45979
46642
|
return true;
|
|
45980
46643
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
45981
46644
|
return true;
|
|
45982
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
46645
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename17) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
45983
46646
|
return true;
|
|
45984
|
-
if (lower.endsWith(".php") && (/^Test[A-Z]/.test(
|
|
46647
|
+
if (lower.endsWith(".php") && (/^Test[A-Z]/.test(basename17) || basename17.endsWith("Test.php") || basename17.endsWith("Tests.php")))
|
|
45985
46648
|
return true;
|
|
45986
46649
|
if (lower.endsWith(".tests.ps1"))
|
|
45987
46650
|
return true;
|
|
@@ -45989,23 +46652,23 @@ function isLanguageSpecificTestFile(basename16) {
|
|
|
45989
46652
|
}
|
|
45990
46653
|
function isConventionTestFilePath(filePath) {
|
|
45991
46654
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
45992
|
-
const
|
|
45993
|
-
return hasCompoundTestExtension(
|
|
46655
|
+
const basename17 = path81.basename(filePath);
|
|
46656
|
+
return hasCompoundTestExtension(basename17) || basename17.includes(".spec.") || basename17.includes(".test.") || isLanguageSpecificTestFile(basename17) || isTestDirectoryPath(normalizedPath);
|
|
45994
46657
|
}
|
|
45995
46658
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
45996
46659
|
const testFiles = [];
|
|
45997
46660
|
for (const file of sourceFiles) {
|
|
45998
46661
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
45999
46662
|
const relativeFile = path81.relative(workingDir, absoluteFile);
|
|
46000
|
-
const
|
|
46663
|
+
const basename17 = path81.basename(absoluteFile);
|
|
46001
46664
|
const dirname30 = path81.dirname(absoluteFile);
|
|
46002
46665
|
const preferRelativeOutput = !path81.isAbsolute(file);
|
|
46003
46666
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
46004
46667
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
46005
46668
|
continue;
|
|
46006
46669
|
}
|
|
46007
|
-
const nameWithoutExt =
|
|
46008
|
-
const ext = path81.extname(
|
|
46670
|
+
const nameWithoutExt = basename17.replace(/\.[^.]+$/, "");
|
|
46671
|
+
const ext = path81.extname(basename17);
|
|
46009
46672
|
const genericTestNames = [
|
|
46010
46673
|
`${nameWithoutExt}.spec${ext}`,
|
|
46011
46674
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -46016,7 +46679,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
46016
46679
|
...languageSpecificTestNames
|
|
46017
46680
|
].map((candidateName) => path81.join(dirname30, candidateName));
|
|
46018
46681
|
const testDirectoryNames = [
|
|
46019
|
-
|
|
46682
|
+
basename17,
|
|
46020
46683
|
...genericTestNames,
|
|
46021
46684
|
...languageSpecificTestNames
|
|
46022
46685
|
];
|
|
@@ -46281,13 +46944,13 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
46281
46944
|
'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'
|
|
46282
46945
|
];
|
|
46283
46946
|
case "pest": {
|
|
46284
|
-
const args = [
|
|
46947
|
+
const args = [phpVendorBin("pest")];
|
|
46285
46948
|
if (scope !== "all" && files.length > 0)
|
|
46286
46949
|
args.push(...files);
|
|
46287
46950
|
return args;
|
|
46288
46951
|
}
|
|
46289
46952
|
case "phpunit": {
|
|
46290
|
-
const args = [
|
|
46953
|
+
const args = [phpVendorBin("phpunit")];
|
|
46291
46954
|
if (scope !== "all" && files.length > 0)
|
|
46292
46955
|
args.push(...files);
|
|
46293
46956
|
return args;
|
|
@@ -46302,7 +46965,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
46302
46965
|
return null;
|
|
46303
46966
|
}
|
|
46304
46967
|
}
|
|
46305
|
-
function
|
|
46968
|
+
function phpVendorBin(name) {
|
|
46306
46969
|
return path81.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
|
|
46307
46970
|
}
|
|
46308
46971
|
function mapFrameworkStatusToResult(status) {
|
|
@@ -46741,9 +47404,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
46741
47404
|
stderr: "pipe",
|
|
46742
47405
|
cwd
|
|
46743
47406
|
});
|
|
46744
|
-
const timeoutPromise = new Promise((
|
|
47407
|
+
const timeoutPromise = new Promise((resolve27) => setTimeout(() => {
|
|
46745
47408
|
proc.kill();
|
|
46746
|
-
|
|
47409
|
+
resolve27(-1);
|
|
46747
47410
|
}, timeout_ms));
|
|
46748
47411
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
46749
47412
|
Promise.race([proc.exited, timeoutPromise]),
|
|
@@ -46901,11 +47564,11 @@ function normalizeHistoryTestFile(testFile, workingDir) {
|
|
|
46901
47564
|
const normalized = testFile.replace(/\\/g, "/");
|
|
46902
47565
|
if (!path81.isAbsolute(testFile))
|
|
46903
47566
|
return normalized;
|
|
46904
|
-
const
|
|
46905
|
-
if (
|
|
47567
|
+
const relative12 = path81.relative(workingDir, testFile);
|
|
47568
|
+
if (relative12.startsWith("..") || path81.isAbsolute(relative12)) {
|
|
46906
47569
|
return normalized;
|
|
46907
47570
|
}
|
|
46908
|
-
return
|
|
47571
|
+
return relative12.replace(/\\/g, "/");
|
|
46909
47572
|
}
|
|
46910
47573
|
function combineAggregateResult(current, next) {
|
|
46911
47574
|
if (current === "fail" || next === "fail")
|
|
@@ -48329,13 +48992,13 @@ class CircuitBreaker {
|
|
|
48329
48992
|
if (this.config.callTimeoutMs <= 0) {
|
|
48330
48993
|
return fn();
|
|
48331
48994
|
}
|
|
48332
|
-
return new Promise((
|
|
48995
|
+
return new Promise((resolve28, reject) => {
|
|
48333
48996
|
const timeout = setTimeout(() => {
|
|
48334
48997
|
reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
|
|
48335
48998
|
}, this.config.callTimeoutMs);
|
|
48336
48999
|
fn().then((result) => {
|
|
48337
49000
|
clearTimeout(timeout);
|
|
48338
|
-
|
|
49001
|
+
resolve28(result);
|
|
48339
49002
|
}).catch((error2) => {
|
|
48340
49003
|
clearTimeout(timeout);
|
|
48341
49004
|
reject(error2);
|
|
@@ -48634,7 +49297,7 @@ class AutomationQueue {
|
|
|
48634
49297
|
|
|
48635
49298
|
// src/background/worker.ts
|
|
48636
49299
|
function sleep(ms) {
|
|
48637
|
-
return new Promise((
|
|
49300
|
+
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
48638
49301
|
}
|
|
48639
49302
|
|
|
48640
49303
|
class WorkerManager {
|
|
@@ -50584,7 +51247,7 @@ function resolveReviewFallbackModels(agentName, registry) {
|
|
|
50584
51247
|
init_logger();
|
|
50585
51248
|
|
|
50586
51249
|
// src/hooks/review-receipt-scope.ts
|
|
50587
|
-
import * as
|
|
51250
|
+
import * as child_process6 from "child_process";
|
|
50588
51251
|
import { createHash as createHash14 } from "crypto";
|
|
50589
51252
|
import * as fs42 from "fs";
|
|
50590
51253
|
import * as path89 from "path";
|
|
@@ -50596,7 +51259,7 @@ var HEAD_OUTPUT_BYTES = 256;
|
|
|
50596
51259
|
var HEAD_SHA_PATTERN = /^[0-9a-f]{40,64}$/i;
|
|
50597
51260
|
var REVIEWER_TASK_SCOPE_DESCRIPTION = "reviewer-task-files-v1";
|
|
50598
51261
|
var _internals74 = {
|
|
50599
|
-
spawn:
|
|
51262
|
+
spawn: child_process6.spawn,
|
|
50600
51263
|
realpath: fs42.promises.realpath,
|
|
50601
51264
|
lstatBigInt: (path90) => fs42.promises.lstat(path90, { bigint: true }),
|
|
50602
51265
|
open: fs42.promises.open,
|
|
@@ -50611,8 +51274,8 @@ function hasControlCharacter2(value) {
|
|
|
50611
51274
|
return false;
|
|
50612
51275
|
}
|
|
50613
51276
|
function isContained2(root, candidate) {
|
|
50614
|
-
const
|
|
50615
|
-
return
|
|
51277
|
+
const relative15 = path89.relative(root, candidate);
|
|
51278
|
+
return relative15.length > 0 && relative15 !== ".." && !relative15.startsWith(`..${path89.sep}`) && !path89.isAbsolute(relative15);
|
|
50616
51279
|
}
|
|
50617
51280
|
function canonicalPath(relativePath2) {
|
|
50618
51281
|
return relativePath2.split(path89.sep).join("/");
|
|
@@ -50668,7 +51331,7 @@ async function resolveHeadSha(directory) {
|
|
|
50668
51331
|
timeout: HEAD_TIMEOUT_MS,
|
|
50669
51332
|
windowsHide: true
|
|
50670
51333
|
});
|
|
50671
|
-
return await new Promise((
|
|
51334
|
+
return await new Promise((resolve31) => {
|
|
50672
51335
|
let settled = false;
|
|
50673
51336
|
let stdoutBytes = 0;
|
|
50674
51337
|
const stdoutChunks = [];
|
|
@@ -50678,7 +51341,7 @@ async function resolveHeadSha(directory) {
|
|
|
50678
51341
|
settled = true;
|
|
50679
51342
|
if (timeoutHandle !== undefined)
|
|
50680
51343
|
clearTimeout(timeoutHandle);
|
|
50681
|
-
|
|
51344
|
+
resolve31(value);
|
|
50682
51345
|
};
|
|
50683
51346
|
const killAndFail = () => {
|
|
50684
51347
|
try {
|
|
@@ -51398,8 +52061,8 @@ function normalizedRelativePath(file) {
|
|
|
51398
52061
|
return normalized.replace(/^\.\//, "");
|
|
51399
52062
|
}
|
|
51400
52063
|
function isWithinRoot2(root, candidate) {
|
|
51401
|
-
const
|
|
51402
|
-
return
|
|
52064
|
+
const relative17 = path91.relative(root, candidate);
|
|
52065
|
+
return relative17.length > 0 && relative17 !== ".." && !relative17.startsWith(`..${path91.sep}`) && !path91.isAbsolute(relative17);
|
|
51403
52066
|
}
|
|
51404
52067
|
function rangesOverlap(start, end, ranges) {
|
|
51405
52068
|
return ranges.some((range) => start <= range.end && end >= range.start);
|
|
@@ -51963,8 +52626,8 @@ function formatSelector(selector) {
|
|
|
51963
52626
|
}
|
|
51964
52627
|
}
|
|
51965
52628
|
function isPathInside(parent, candidate) {
|
|
51966
|
-
const
|
|
51967
|
-
return
|
|
52629
|
+
const relative18 = path92.relative(parent, candidate);
|
|
52630
|
+
return relative18.length > 0 && relative18 !== ".." && !relative18.startsWith(`..${path92.sep}`) && !path92.isAbsolute(relative18);
|
|
51968
52631
|
}
|
|
51969
52632
|
function sameFileSnapshot4(left, right) {
|
|
51970
52633
|
return (left.dev !== 0n || left.ino !== 0n) && (right.dev !== 0n || right.ino !== 0n) && left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
|
|
@@ -53059,14 +53722,14 @@ import * as path96 from "path";
|
|
|
53059
53722
|
// src/services/skill-optimizer/store.ts
|
|
53060
53723
|
import { createHash as createHash15, randomUUID as randomUUID10 } from "crypto";
|
|
53061
53724
|
import {
|
|
53062
|
-
closeSync as
|
|
53725
|
+
closeSync as closeSync13,
|
|
53063
53726
|
existsSync as existsSync53,
|
|
53064
53727
|
fsyncSync as fsyncSync3,
|
|
53065
53728
|
mkdirSync as mkdirSync27,
|
|
53066
|
-
openSync as
|
|
53729
|
+
openSync as openSync13,
|
|
53067
53730
|
readFileSync as readFileSync39,
|
|
53068
53731
|
renameSync as renameSync18,
|
|
53069
|
-
statSync as
|
|
53732
|
+
statSync as statSync16,
|
|
53070
53733
|
unlinkSync as unlinkSync20,
|
|
53071
53734
|
writeFileSync as writeFileSync17,
|
|
53072
53735
|
writeFileSync as writeFileSyncAsync
|
|
@@ -53132,12 +53795,12 @@ function ensureCandidateDir(directory, skillSlug, candidateId2) {
|
|
|
53132
53795
|
return dir;
|
|
53133
53796
|
}
|
|
53134
53797
|
function writeFileFsyncedThenRename(tempPath, targetPath, data) {
|
|
53135
|
-
const fd =
|
|
53798
|
+
const fd = openSync13(tempPath, "w");
|
|
53136
53799
|
try {
|
|
53137
53800
|
writeFileSync17(fd, data, "utf8");
|
|
53138
53801
|
fsyncSync3(fd);
|
|
53139
53802
|
} finally {
|
|
53140
|
-
|
|
53803
|
+
closeSync13(fd);
|
|
53141
53804
|
}
|
|
53142
53805
|
try {
|
|
53143
53806
|
renameSync18(tempPath, targetPath);
|
|
@@ -53156,7 +53819,7 @@ var _internals79 = {
|
|
|
53156
53819
|
renameSync: renameSync18,
|
|
53157
53820
|
unlinkSync: unlinkSync20,
|
|
53158
53821
|
existsSync: existsSync53,
|
|
53159
|
-
statSync:
|
|
53822
|
+
statSync: statSync16
|
|
53160
53823
|
};
|
|
53161
53824
|
async function appendEvent(directory, eventInput) {
|
|
53162
53825
|
if (!isValidSkillSlug(eventInput.skillSlug)) {
|
|
@@ -53974,17 +54637,17 @@ async function deterministicSeed(input) {
|
|
|
53974
54637
|
}
|
|
53975
54638
|
|
|
53976
54639
|
// src/services/skill-optimizer/smoke.ts
|
|
53977
|
-
import { existsSync as existsSync55, lstatSync as lstatSync10, readFileSync as readFileSync41, realpathSync as
|
|
54640
|
+
import { existsSync as existsSync55, lstatSync as lstatSync10, readFileSync as readFileSync41, realpathSync as realpathSync11 } from "fs";
|
|
53978
54641
|
import * as path98 from "path";
|
|
53979
54642
|
|
|
53980
54643
|
// src/hooks/spawn-helper.ts
|
|
53981
|
-
import * as
|
|
54644
|
+
import * as child_process7 from "child_process";
|
|
53982
54645
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
53983
54646
|
var _internals82 = {
|
|
53984
|
-
spawn:
|
|
54647
|
+
spawn: child_process7.spawn
|
|
53985
54648
|
};
|
|
53986
54649
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
53987
|
-
return new Promise((
|
|
54650
|
+
return new Promise((resolve34) => {
|
|
53988
54651
|
try {
|
|
53989
54652
|
const [rawCmd, ...args] = command;
|
|
53990
54653
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -54031,24 +54694,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
54031
54694
|
try {
|
|
54032
54695
|
proc.kill();
|
|
54033
54696
|
} catch {}
|
|
54034
|
-
|
|
54697
|
+
resolve34(null);
|
|
54035
54698
|
}, timeoutMs);
|
|
54036
54699
|
proc.on("close", (code) => {
|
|
54037
54700
|
if (done)
|
|
54038
54701
|
return;
|
|
54039
54702
|
done = true;
|
|
54040
54703
|
clearTimeout(timer);
|
|
54041
|
-
|
|
54704
|
+
resolve34({ exitCode: code ?? 1, stdout, stderr });
|
|
54042
54705
|
});
|
|
54043
54706
|
proc.on("error", () => {
|
|
54044
54707
|
if (done)
|
|
54045
54708
|
return;
|
|
54046
54709
|
done = true;
|
|
54047
54710
|
clearTimeout(timer);
|
|
54048
|
-
|
|
54711
|
+
resolve34(null);
|
|
54049
54712
|
});
|
|
54050
54713
|
} catch {
|
|
54051
|
-
|
|
54714
|
+
resolve34(null);
|
|
54052
54715
|
}
|
|
54053
54716
|
});
|
|
54054
54717
|
}
|
|
@@ -54067,7 +54730,7 @@ var _internals83 = {
|
|
|
54067
54730
|
const rel = path98.relative(path98.resolve(root), path98.resolve(target));
|
|
54068
54731
|
return rel.startsWith("..") || path98.isAbsolute(rel);
|
|
54069
54732
|
},
|
|
54070
|
-
realpath: (p) =>
|
|
54733
|
+
realpath: (p) => realpathSync11(p),
|
|
54071
54734
|
evaluateSkillChange,
|
|
54072
54735
|
isRejectedSkillContent,
|
|
54073
54736
|
spawnAsync
|
|
@@ -54431,7 +55094,7 @@ async function runValidationWithTransientRetry(input, candidateContent, baseline
|
|
|
54431
55094
|
if (!input.dispatcher) {
|
|
54432
55095
|
throw new Error("no evaluation dispatcher available (cannot run validation)");
|
|
54433
55096
|
}
|
|
54434
|
-
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-
|
|
55097
|
+
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-mzb3e2s6.js");
|
|
54435
55098
|
const executor = createModelEvaluationExecutor2(input.dispatcher, input.sessionId);
|
|
54436
55099
|
const result = await _internals84.evaluateCandidateV1({
|
|
54437
55100
|
projectRoot: input.directory,
|
|
@@ -55304,11 +55967,18 @@ function makeInitialState() {
|
|
|
55304
55967
|
};
|
|
55305
55968
|
}
|
|
55306
55969
|
var sessionStates = new Map;
|
|
55970
|
+
var MAX_TRACKED_COMPACTION_SESSIONS = 500;
|
|
55307
55971
|
function getSessionState(sessionId) {
|
|
55308
55972
|
let state = sessionStates.get(sessionId);
|
|
55309
|
-
if (
|
|
55310
|
-
state
|
|
55311
|
-
|
|
55973
|
+
if (state)
|
|
55974
|
+
return state;
|
|
55975
|
+
state = makeInitialState();
|
|
55976
|
+
sessionStates.set(sessionId, state);
|
|
55977
|
+
if (sessionStates.size > MAX_TRACKED_COMPACTION_SESSIONS) {
|
|
55978
|
+
const oldest = sessionStates.keys().next().value;
|
|
55979
|
+
if (oldest !== undefined && oldest !== sessionId) {
|
|
55980
|
+
sessionStates.delete(oldest);
|
|
55981
|
+
}
|
|
55312
55982
|
}
|
|
55313
55983
|
return state;
|
|
55314
55984
|
}
|
|
@@ -55393,8 +56063,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55393
56063
|
agentCount,
|
|
55394
56064
|
isLegacy: false,
|
|
55395
56065
|
turboMode: hasActiveTurboMode(),
|
|
55396
|
-
contextBudgetPct:
|
|
55397
|
-
contextBudgetTokens:
|
|
56066
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56067
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55398
56068
|
compactionCount: metrics.compactionCount,
|
|
55399
56069
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55400
56070
|
};
|
|
@@ -55410,8 +56080,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55410
56080
|
agentCount: Object.keys(agents).length,
|
|
55411
56081
|
isLegacy: true,
|
|
55412
56082
|
turboMode: hasActiveTurboMode(),
|
|
55413
|
-
contextBudgetPct:
|
|
55414
|
-
contextBudgetTokens:
|
|
56083
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56084
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55415
56085
|
compactionCount: metrics.compactionCount,
|
|
55416
56086
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55417
56087
|
};
|
|
@@ -55430,8 +56100,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55430
56100
|
agentCount,
|
|
55431
56101
|
isLegacy: true,
|
|
55432
56102
|
turboMode: hasActiveTurboMode(),
|
|
55433
|
-
contextBudgetPct:
|
|
55434
|
-
contextBudgetTokens:
|
|
56103
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56104
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55435
56105
|
compactionCount: metrics.compactionCount,
|
|
55436
56106
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55437
56107
|
};
|
|
@@ -56255,7 +56925,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
56255
56925
|
async function handleHelpCommand(ctx) {
|
|
56256
56926
|
const targetCommand = ctx.args.join(" ");
|
|
56257
56927
|
if (!targetCommand) {
|
|
56258
|
-
const { buildHelpText } = await import("./index-
|
|
56928
|
+
const { buildHelpText } = await import("./index-5hyq2mw6.js");
|
|
56259
56929
|
return buildHelpText();
|
|
56260
56930
|
}
|
|
56261
56931
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -56264,7 +56934,7 @@ async function handleHelpCommand(ctx) {
|
|
|
56264
56934
|
return _internals14.buildDetailedHelp(resolved.key, resolved.entry);
|
|
56265
56935
|
}
|
|
56266
56936
|
const similar = _internals14.findSimilarCommands(targetCommand);
|
|
56267
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
56937
|
+
const { buildHelpText: fullHelp } = await import("./index-5hyq2mw6.js");
|
|
56268
56938
|
if (similar.length > 0) {
|
|
56269
56939
|
return `Command '/swarm ${targetCommand}' not found.
|
|
56270
56940
|
|
|
@@ -56441,7 +57111,7 @@ var COMMAND_REGISTRY = {
|
|
|
56441
57111
|
},
|
|
56442
57112
|
"guardrail explain": {
|
|
56443
57113
|
handler: async (ctx) => {
|
|
56444
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
57114
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-y2wg00dp.js");
|
|
56445
57115
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
56446
57116
|
},
|
|
56447
57117
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -56451,7 +57121,7 @@ var COMMAND_REGISTRY = {
|
|
|
56451
57121
|
},
|
|
56452
57122
|
"guardrail-explain": {
|
|
56453
57123
|
handler: async (ctx) => {
|
|
56454
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
57124
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-y2wg00dp.js");
|
|
56455
57125
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
56456
57126
|
},
|
|
56457
57127
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -56461,7 +57131,7 @@ var COMMAND_REGISTRY = {
|
|
|
56461
57131
|
},
|
|
56462
57132
|
"guardrail-log": {
|
|
56463
57133
|
handler: async (ctx) => {
|
|
56464
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
57134
|
+
const { handleGuardrailLog } = await import("./guardrail-log-320grggj.js");
|
|
56465
57135
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
56466
57136
|
},
|
|
56467
57137
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -56915,7 +57585,7 @@ Subcommands:
|
|
|
56915
57585
|
handler: (ctx) => handleApprovePlanCriticCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
56916
57586
|
description: "Record a MANUAL plan-critic approval to unblock the critic_pre_plan execution gate [reason...]",
|
|
56917
57587
|
args: "[reason...]",
|
|
56918
|
-
details: 'Human-only escape hatch for the ratchet-tighter critic_pre_plan execution gate (issue #2012). When the critic already returned APPROVED but the mechanical snapshot recorder failed to persist it (verdict-format mismatch, dispatch-signal miss, or a plan.json read race),
|
|
57588
|
+
details: 'Human-only escape hatch for the ratchet-tighter critic_pre_plan execution gate (issue #2012). When the critic already returned APPROVED but the mechanical snapshot recorder failed to persist it (verdict-format mismatch, dispatch-signal miss, or a plan.json read race), an enabled critic_pre_plan gate blocks coder delegation. Running this records a manual plan_critic_gate approval snapshot so the gate unblocks, with a distinct method: "manual_override" audit marker. The agent itself cannot run this command; it must call the approve_plan_critic tool (or ask you to run this command). Both paths funnel into the same forceRecordPlanCriticApproval hook, which requires an active architect session. An audit event is appended to .swarm/events.jsonl. Prefer re-running MODE: CRITIC-GATE first; use this only as an escape hatch when a legitimate APPROVED was lost.',
|
|
56919
57589
|
category: "utility",
|
|
56920
57590
|
toolPolicy: "restricted"
|
|
56921
57591
|
},
|
|
@@ -59900,14 +60570,6 @@ function getSwarmAgents(swarmId) {
|
|
|
59900
60570
|
const id = swarmId ?? "default";
|
|
59901
60571
|
return _swarmAgentsMap.get(id);
|
|
59902
60572
|
}
|
|
59903
|
-
var KNOWN_VARIANT_VALUES = new Set([
|
|
59904
|
-
"low",
|
|
59905
|
-
"medium",
|
|
59906
|
-
"high",
|
|
59907
|
-
"max",
|
|
59908
|
-
"xhigh",
|
|
59909
|
-
"thinking"
|
|
59910
|
-
]);
|
|
59911
60573
|
|
|
59912
60574
|
// src/hooks/curator-llm-factory.ts
|
|
59913
60575
|
init_schema();
|