opencode-swarm 7.139.1 → 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/.opencode/skills/swarm-pr-review/SKILL.md +15 -0
- package/dist/background/stage-b-gates.d.ts +5 -1
- package/dist/background/task-envelope.d.ts +4 -4
- package/dist/cli/{config-doctor-tgnr91q3.js → config-doctor-75qky762.js} +3 -3
- package/dist/cli/{core-g2dfh9fq.js → core-nn8ffy5h.js} +3 -3
- package/dist/cli/{curation-policy-2qnhgdtt.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-1ftzece0.js → curator-llm-factory-1r9vz0g2.js} +28 -28
- package/dist/cli/{curator-nbsag633.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-vb9k9zwm.js → guardrail-explain-y2wg00dp.js} +29 -29
- package/dist/cli/{guardrail-log-0djnvfas.js → guardrail-log-320grggj.js} +5 -5
- package/dist/cli/{hive-promoter-bpt26yew.js → hive-promoter-v4w7cjvk.js} +28 -28
- package/dist/cli/{index-3eddtgxt.js → index-05mms0va.js} +1 -1
- package/dist/cli/{index-y1zcsf2a.js → index-0mzz46we.js} +2 -2
- package/dist/cli/{index-ywysg26s.js → index-1jbj7vzv.js} +4 -4
- package/dist/cli/{index-91s653xx.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-xka8s8jw.js → index-5hyq2mw6.js} +30 -30
- package/dist/cli/{index-5zyk8qgv.js → index-5syvwd8g.js} +1 -1
- package/dist/cli/{index-en6qq954.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-0ymhx85c.js → index-ba5e5e3n.js} +2 -2
- package/dist/cli/{index-hn0mdcmj.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-aymt7hzw.js → index-hwnpd4tw.js} +3 -3
- package/dist/cli/{index-xec724kg.js → index-jqn332jx.js} +2 -2
- package/dist/cli/{index-x9q4bbhd.js → index-k87hs2ff.js} +1 -1
- package/dist/cli/{index-15526t16.js → index-kyz7259r.js} +2 -2
- package/dist/cli/{index-prmb5qfp.js → index-mv0czd9c.js} +2 -2
- package/dist/cli/{index-hgrkhxbk.js → index-mzck763x.js} +2 -2
- package/dist/cli/{index-xr07r80d.js → index-tkg6rapy.js} +1345 -682
- package/dist/cli/{index-ht4q3548.js → index-v7g8dnyh.js} +3 -3
- package/dist/cli/{index-vxbppwvf.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-dw09fz3w.js → index-yawwwhmc.js} +2 -2
- package/dist/cli/{index-q7ezzgwq.js → index-yh0q21nj.js} +1 -1
- package/dist/cli/{index-db7wf6ke.js → index-z6qe8wft.js} +6 -6
- package/dist/cli/index.js +28 -28
- package/dist/cli/{knowledge-escalator-pjg2x75c.js → knowledge-escalator-kkjsjtza.js} +6 -6
- package/dist/cli/{knowledge-events-vxheptk8.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-36mascwz.js → knowledge-store-m7vnz62z.js} +4 -4
- package/dist/cli/{knowledge-validator-anats6rj.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-apbz9eez.js → scan-cursor-8e6ryhjq.js} +5 -5
- package/dist/cli/{schema-x9fr2ey8.js → schema-g7rs20c6.js} +2 -2
- package/dist/cli/{scope-persistence-3f0d4fwv.js → scope-persistence-wy65zyha.js} +2 -2
- package/dist/cli/{skill-generator-20czn4kd.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/hooks/pr-workflow-gate.d.ts +8 -1
- package/dist/index.js +421 -416
- 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();
|
|
@@ -2199,6 +2213,7 @@ var PrWorkflowGateStateSchema = exports_external.object({
|
|
|
2199
2213
|
prReviewBaseDispatch: PrReviewBaseDispatchRecordSchema.optional(),
|
|
2200
2214
|
prReviewTriggerLedger: exports_external.array(PrReviewInlineTriggerRowSchema).length(PR_REVIEW_REQUIRED_TRIGGER_IDS.length).optional(),
|
|
2201
2215
|
prReviewTriggerEvalPath: exports_external.string().min(1).optional(),
|
|
2216
|
+
prReviewTriggerEvalRunId: exports_external.string().min(1).optional(),
|
|
2202
2217
|
prReviewValidationBatches: exports_external.array(PrReviewValidationBatchRecordSchema).max(MAX_WORKFLOW_BATCHES).optional(),
|
|
2203
2218
|
prReviewBatchCoherence: exports_external.record(exports_external.string().min(1), PrReviewBatchCoherenceRecordSchema).refine((entries) => Object.keys(entries).length <= MAX_WORKFLOW_BATCHES, `prReviewBatchCoherence may not exceed ${MAX_WORKFLOW_BATCHES} entries`).optional(),
|
|
2204
2219
|
prReviewRetiredReviewerSessionIds: exports_external.array(exports_external.string().min(1)).max(MAX_RETIRED_REVIEWER_SESSION_IDS).optional(),
|
|
@@ -4899,71 +4914,6 @@ import * as path20 from "path";
|
|
|
4899
4914
|
init_agent_names();
|
|
4900
4915
|
init_schema();
|
|
4901
4916
|
|
|
4902
|
-
// src/turbo/epic/cochange-conflict.ts
|
|
4903
|
-
function pathMatches(scopePath, cochangePath) {
|
|
4904
|
-
if (scopePath === cochangePath)
|
|
4905
|
-
return true;
|
|
4906
|
-
return scopePath.endsWith(`/${cochangePath}`);
|
|
4907
|
-
}
|
|
4908
|
-
function epicPairConflict(scopeA, scopeB, cochangePairs, threshold) {
|
|
4909
|
-
const normA = scopeA.map(normalizePath);
|
|
4910
|
-
const normB = scopeB.map(normalizePath);
|
|
4911
|
-
const pathPairs = [];
|
|
4912
|
-
for (const a of normA) {
|
|
4913
|
-
for (const b of normB) {
|
|
4914
|
-
if (pathsConflict(a, b)) {
|
|
4915
|
-
pathPairs.push([a, b]);
|
|
4916
|
-
}
|
|
4917
|
-
}
|
|
4918
|
-
}
|
|
4919
|
-
const pathConflict = pathPairs.length > 0;
|
|
4920
|
-
const activePairs = cochangePairs.filter((e) => e.coChangeCount >= threshold.minCoChanges && e.npmi >= threshold.npmi);
|
|
4921
|
-
const cochangeMatches = [];
|
|
4922
|
-
for (const entry of activePairs) {
|
|
4923
|
-
const fa = entry.fileA;
|
|
4924
|
-
const fb = entry.fileB;
|
|
4925
|
-
const aTouchesFa = normA.some((p) => pathMatches(p, fa));
|
|
4926
|
-
const aTouchesFb = normA.some((p) => pathMatches(p, fb));
|
|
4927
|
-
const bTouchesFa = normB.some((p) => pathMatches(p, fa));
|
|
4928
|
-
const bTouchesFb = normB.some((p) => pathMatches(p, fb));
|
|
4929
|
-
const aExclusivelyFa = aTouchesFa && !aTouchesFb;
|
|
4930
|
-
const aExclusivelyFb = aTouchesFb && !aTouchesFa;
|
|
4931
|
-
const bExclusivelyFa = bTouchesFa && !bTouchesFb;
|
|
4932
|
-
const bExclusivelyFb = bTouchesFb && !bTouchesFa;
|
|
4933
|
-
const crossCouple = aExclusivelyFa && bExclusivelyFb || aExclusivelyFb && bExclusivelyFa;
|
|
4934
|
-
if (crossCouple) {
|
|
4935
|
-
cochangeMatches.push({
|
|
4936
|
-
a: fa,
|
|
4937
|
-
b: fb,
|
|
4938
|
-
npmi: entry.npmi,
|
|
4939
|
-
coChangeCount: entry.coChangeCount
|
|
4940
|
-
});
|
|
4941
|
-
}
|
|
4942
|
-
}
|
|
4943
|
-
const cochangeConflict = cochangeMatches.length > 0;
|
|
4944
|
-
let reason;
|
|
4945
|
-
if (pathConflict && cochangeConflict)
|
|
4946
|
-
reason = "both";
|
|
4947
|
-
else if (pathConflict)
|
|
4948
|
-
reason = "path";
|
|
4949
|
-
else if (cochangeConflict)
|
|
4950
|
-
reason = "cochange";
|
|
4951
|
-
else
|
|
4952
|
-
reason = "none";
|
|
4953
|
-
return {
|
|
4954
|
-
conflict: pathConflict || cochangeConflict,
|
|
4955
|
-
reason,
|
|
4956
|
-
evidence: { pathPairs, cochangePairs: cochangeMatches }
|
|
4957
|
-
};
|
|
4958
|
-
}
|
|
4959
|
-
|
|
4960
|
-
// src/state.ts
|
|
4961
|
-
init_constants();
|
|
4962
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
4963
|
-
import * as fs2 from "fs/promises";
|
|
4964
|
-
import * as path7 from "path";
|
|
4965
|
-
init_schema();
|
|
4966
|
-
|
|
4967
4917
|
// src/db/qa-gate-profile.ts
|
|
4968
4918
|
import { createHash as createHash3 } from "crypto";
|
|
4969
4919
|
|
|
@@ -5066,7 +5016,8 @@ var _internals5 = {
|
|
|
5066
5016
|
setGates,
|
|
5067
5017
|
getEffectiveGates,
|
|
5068
5018
|
computeProfileHash,
|
|
5069
|
-
hasAnyProfileWithEnabledGate
|
|
5019
|
+
hasAnyProfileWithEnabledGate,
|
|
5020
|
+
afterSetGatesRead: () => {}
|
|
5070
5021
|
};
|
|
5071
5022
|
var DEFAULT_QA_GATES = {
|
|
5072
5023
|
reviewer: true,
|
|
@@ -5081,6 +5032,7 @@ var DEFAULT_QA_GATES = {
|
|
|
5081
5032
|
drift_check: true,
|
|
5082
5033
|
final_council: false
|
|
5083
5034
|
};
|
|
5035
|
+
var qaGateProfileSavepointCounter = 0;
|
|
5084
5036
|
function rowToProfile(row) {
|
|
5085
5037
|
let parsed = {};
|
|
5086
5038
|
try {
|
|
@@ -5099,7 +5051,7 @@ function rowToProfile(row) {
|
|
|
5099
5051
|
const knownKeys = new Set(Object.keys(DEFAULT_QA_GATES));
|
|
5100
5052
|
const filteredParsed = {};
|
|
5101
5053
|
for (const key of Object.keys(parsed)) {
|
|
5102
|
-
if (knownKeys.has(key)) {
|
|
5054
|
+
if (knownKeys.has(key) && typeof parsed[key] === "boolean") {
|
|
5103
5055
|
filteredParsed[key] = parsed[key];
|
|
5104
5056
|
}
|
|
5105
5057
|
}
|
|
@@ -5135,12 +5087,18 @@ function hasAnyProfileWithEnabledGate(directory, gate) {
|
|
|
5135
5087
|
}
|
|
5136
5088
|
return false;
|
|
5137
5089
|
}
|
|
5138
|
-
function getOrCreateProfile(directory, planId, projectType) {
|
|
5090
|
+
function getOrCreateProfile(directory, planId, projectType, initialGates = {}) {
|
|
5139
5091
|
const existing = _internals5.getProfile(directory, planId);
|
|
5140
5092
|
if (existing)
|
|
5141
5093
|
return existing;
|
|
5142
5094
|
const db = getProjectDb(directory);
|
|
5143
|
-
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);
|
|
5144
5102
|
const insert = db.transaction(() => {
|
|
5145
5103
|
db.run("INSERT INTO qa_gate_profile (plan_id, project_type, gates) VALUES (?, ?, ?)", [planId, projectType ?? null, gatesJson]);
|
|
5146
5104
|
});
|
|
@@ -5159,35 +5117,51 @@ function getOrCreateProfile(directory, planId, projectType) {
|
|
|
5159
5117
|
return after;
|
|
5160
5118
|
}
|
|
5161
5119
|
function setGates(directory, planId, gates) {
|
|
5162
|
-
const
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
}
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
const
|
|
5172
|
-
if (
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
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
|
+
}
|
|
5176
5145
|
}
|
|
5177
|
-
|
|
5178
|
-
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}`);
|
|
5179
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;
|
|
5180
5164
|
}
|
|
5181
|
-
const db = getProjectDb(directory);
|
|
5182
|
-
db.run("UPDATE qa_gate_profile SET gates = ? WHERE plan_id = ?", [
|
|
5183
|
-
JSON.stringify(merged),
|
|
5184
|
-
planId
|
|
5185
|
-
]);
|
|
5186
|
-
const updated = _internals5.getProfile(directory, planId);
|
|
5187
|
-
if (!updated) {
|
|
5188
|
-
throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
|
|
5189
|
-
}
|
|
5190
|
-
return updated;
|
|
5191
5165
|
}
|
|
5192
5166
|
function computeProfileHash(profile) {
|
|
5193
5167
|
const payload = JSON.stringify({
|
|
@@ -5206,6 +5180,71 @@ function getEffectiveGates(profile, sessionOverrides) {
|
|
|
5206
5180
|
return merged;
|
|
5207
5181
|
}
|
|
5208
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
|
+
|
|
5209
5248
|
// src/hooks/realtime-learning-nudge.ts
|
|
5210
5249
|
var realtimeLearningNudgeBySession = new Map;
|
|
5211
5250
|
function resetRealtimeLearningNudgeState() {
|
|
@@ -5685,8 +5724,7 @@ var swarmState = {
|
|
|
5685
5724
|
knowledgeAckDedup: new Set,
|
|
5686
5725
|
gateDenialCounts: new Map,
|
|
5687
5726
|
generatedAgentNames: [],
|
|
5688
|
-
|
|
5689
|
-
lastBudgetTokens: 0,
|
|
5727
|
+
lastBudgetBySession: new Map,
|
|
5690
5728
|
liveContextWindows: new Map,
|
|
5691
5729
|
agentSessions: defaultRunContext.agentSessions,
|
|
5692
5730
|
pendingRehydrations: new Set,
|
|
@@ -5699,8 +5737,7 @@ function resetSwarmState() {
|
|
|
5699
5737
|
swarmState.activeAgent.clear();
|
|
5700
5738
|
swarmState.delegationChains.clear();
|
|
5701
5739
|
swarmState.pendingEvents = 0;
|
|
5702
|
-
swarmState.
|
|
5703
|
-
swarmState.lastBudgetTokens = 0;
|
|
5740
|
+
swarmState.lastBudgetBySession.clear();
|
|
5704
5741
|
swarmState.liveContextWindows.clear();
|
|
5705
5742
|
swarmState.agentSessions.clear();
|
|
5706
5743
|
_lastIdleSweepAtMs = 0;
|
|
@@ -6529,10 +6566,19 @@ function hasActiveEpicMode(sessionID) {
|
|
|
6529
6566
|
}
|
|
6530
6567
|
return false;
|
|
6531
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
|
+
}
|
|
6532
6578
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
6533
6579
|
const map = new Map;
|
|
6534
6580
|
try {
|
|
6535
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
6581
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-qdwfm1a8.js");
|
|
6536
6582
|
const records = await listActive2(directory);
|
|
6537
6583
|
for (const record of records) {
|
|
6538
6584
|
if (record.sessionID !== sessionID)
|
|
@@ -18988,7 +19034,7 @@ function planMerges(active, threshold, maxComparisons, maxMerges) {
|
|
|
18988
19034
|
};
|
|
18989
19035
|
}
|
|
18990
19036
|
async function sweepActiveNearDuplicates(directory, options = {}) {
|
|
18991
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
19037
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
18992
19038
|
const { config } = loadPluginConfigWithMeta2(directory);
|
|
18993
19039
|
const sweepConfig = config.learning?.dedup_sweep;
|
|
18994
19040
|
if (sweepConfig?.enabled === false)
|
|
@@ -20583,7 +20629,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20583
20629
|
}
|
|
20584
20630
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
20585
20631
|
try {
|
|
20586
|
-
const skillModule = await import("./skill-generator-
|
|
20632
|
+
const skillModule = await import("./skill-generator-2rv6ftre.js");
|
|
20587
20633
|
for (const cand of skillCandidates) {
|
|
20588
20634
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
20589
20635
|
continue;
|
|
@@ -21043,7 +21089,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
21043
21089
|
} catch {}
|
|
21044
21090
|
}
|
|
21045
21091
|
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
21046
|
-
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-
|
|
21092
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-kkjsjtza.js");
|
|
21047
21093
|
for (const { id } of contradictedEntries) {
|
|
21048
21094
|
try {
|
|
21049
21095
|
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
@@ -21862,7 +21908,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
21862
21908
|
warnings.push("Failed to collect knowledge summary.");
|
|
21863
21909
|
}
|
|
21864
21910
|
try {
|
|
21865
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
21911
|
+
const { getScanStatus } = await import("./scan-cursor-8e6ryhjq.js");
|
|
21866
21912
|
const scanStatus = await getScanStatus(directory);
|
|
21867
21913
|
if (scanStatus.remaining_estimate > 0) {
|
|
21868
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.`);
|
|
@@ -22034,9 +22080,9 @@ var _internals24 = {
|
|
|
22034
22080
|
verifyPostMortemKnowledgeActions,
|
|
22035
22081
|
repairPostMortemActions,
|
|
22036
22082
|
loadDefaultKnowledgeConfig: async (directory) => {
|
|
22037
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
22083
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
22038
22084
|
try {
|
|
22039
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
22085
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
22040
22086
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
22041
22087
|
return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
22042
22088
|
} catch {
|
|
@@ -22044,11 +22090,11 @@ var _internals24 = {
|
|
|
22044
22090
|
}
|
|
22045
22091
|
},
|
|
22046
22092
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
|
|
22047
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
22093
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-m6mk2v1n.js");
|
|
22048
22094
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
|
|
22049
22095
|
},
|
|
22050
22096
|
checkHivePromotions: async (entries, knowledgeConfig, directory) => {
|
|
22051
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
22097
|
+
const { checkHivePromotions } = await import("./hive-promoter-v4w7cjvk.js");
|
|
22052
22098
|
return checkHivePromotions(entries, knowledgeConfig, directory);
|
|
22053
22099
|
},
|
|
22054
22100
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -22057,7 +22103,7 @@ var _internals24 = {
|
|
|
22057
22103
|
activateProposal,
|
|
22058
22104
|
listSkills: listSkills2,
|
|
22059
22105
|
sanitizeSlug
|
|
22060
|
-
} = await import("./skill-generator-
|
|
22106
|
+
} = await import("./skill-generator-2rv6ftre.js");
|
|
22061
22107
|
const result = {
|
|
22062
22108
|
approved: [],
|
|
22063
22109
|
rejected: [],
|
|
@@ -22099,7 +22145,7 @@ var _internals24 = {
|
|
|
22099
22145
|
return result;
|
|
22100
22146
|
},
|
|
22101
22147
|
readPriorDriftReports: async (directory) => {
|
|
22102
|
-
const { readPriorDriftReports } = await import("./curator-drift-
|
|
22148
|
+
const { readPriorDriftReports } = await import("./curator-drift-r52hjskk.js");
|
|
22103
22149
|
return readPriorDriftReports(directory);
|
|
22104
22150
|
},
|
|
22105
22151
|
readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
|
|
@@ -24685,9 +24731,9 @@ function hashContent(content) {
|
|
|
24685
24731
|
return createHash9("sha1").update(content).digest("hex");
|
|
24686
24732
|
}
|
|
24687
24733
|
async function loadConfigForPolicyCurator(directory) {
|
|
24688
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
24734
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
24689
24735
|
try {
|
|
24690
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
24736
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
24691
24737
|
const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
|
|
24692
24738
|
return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
|
|
24693
24739
|
} catch {
|
|
@@ -28696,7 +28742,7 @@ async function runFinalizeStage(ctx) {
|
|
|
28696
28742
|
}
|
|
28697
28743
|
}
|
|
28698
28744
|
try {
|
|
28699
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
28745
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-g7rs20c6.js");
|
|
28700
28746
|
const { config: pmLoadedConfig } = _internals37.loadPluginConfigWithMeta(ctx.directory);
|
|
28701
28747
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
28702
28748
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -30969,9 +31015,9 @@ var _internals42 = {
|
|
|
30969
31015
|
loadPluginConfigWithMeta,
|
|
30970
31016
|
loadCuratorDeps: async () => {
|
|
30971
31017
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
30972
|
-
import("./schema-
|
|
30973
|
-
import("./curator-
|
|
30974
|
-
import("./curator-llm-factory-
|
|
31018
|
+
import("./schema-g7rs20c6.js"),
|
|
31019
|
+
import("./curator-m6mk2v1n.js"),
|
|
31020
|
+
import("./curator-llm-factory-1r9vz0g2.js")
|
|
30975
31021
|
]);
|
|
30976
31022
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
30977
31023
|
}
|
|
@@ -31876,7 +31922,7 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
31876
31922
|
let scanCompleted = false;
|
|
31877
31923
|
let scanRemaining = 0;
|
|
31878
31924
|
try {
|
|
31879
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
31925
|
+
const { getScanStatus } = await import("./scan-cursor-8e6ryhjq.js");
|
|
31880
31926
|
const status = await getScanStatus(directory);
|
|
31881
31927
|
scanGeneration = status.generation;
|
|
31882
31928
|
scanCompleted = status.completed;
|
|
@@ -31884,19 +31930,19 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
31884
31930
|
} catch {}
|
|
31885
31931
|
let configMatch = null;
|
|
31886
31932
|
try {
|
|
31887
|
-
const { isLinked: isLinked2 } = await import("./knowledge-link-
|
|
31933
|
+
const { isLinked: isLinked2 } = await import("./knowledge-link-f6akgbdn.js");
|
|
31888
31934
|
if (isLinked2(directory)) {
|
|
31889
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
31935
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-g7rs20c6.js");
|
|
31890
31936
|
let config;
|
|
31891
31937
|
try {
|
|
31892
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
31938
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-v7g8dnyh.js");
|
|
31893
31939
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
31894
31940
|
config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
31895
31941
|
} catch {
|
|
31896
31942
|
config = KnowledgeConfigSchema2.parse({});
|
|
31897
31943
|
}
|
|
31898
31944
|
const { cohortConfigFingerprint: cohortConfigFingerprint2 } = await import("./config-fingerprint-v22xh5a2.js");
|
|
31899
|
-
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-
|
|
31945
|
+
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-f46tf3dw.js");
|
|
31900
31946
|
const currentFp = cohortConfigFingerprint2(buildConfigFingerprintInput2(config));
|
|
31901
31947
|
const cohortFp = await readCohortConfigFingerprint(directory);
|
|
31902
31948
|
configMatch = cohortFp === null ? null : currentFp === cohortFp;
|
|
@@ -33107,7 +33153,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
33107
33153
|
const result = runConfigDoctor(config, directory);
|
|
33108
33154
|
let output;
|
|
33109
33155
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
33110
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
33156
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-75qky762.js");
|
|
33111
33157
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true, {
|
|
33112
33158
|
applyLossy: true
|
|
33113
33159
|
});
|
|
@@ -33944,7 +33990,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
33944
33990
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
33945
33991
|
}
|
|
33946
33992
|
async function handleEvidenceSummaryCommand(directory) {
|
|
33947
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
33993
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-sxcq5nrt.js");
|
|
33948
33994
|
const artifact = await buildEvidenceSummary(directory);
|
|
33949
33995
|
if (!artifact) {
|
|
33950
33996
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -35620,7 +35666,8 @@ function validateInput(input) {
|
|
|
35620
35666
|
}
|
|
35621
35667
|
return { valid: true };
|
|
35622
35668
|
}
|
|
35623
|
-
async function qualityBudget(input, directory) {
|
|
35669
|
+
async function qualityBudget(input, directory, abortSignal) {
|
|
35670
|
+
abortSignal?.throwIfAborted();
|
|
35624
35671
|
const validation = validateInput(input);
|
|
35625
35672
|
if (!validation.valid) {
|
|
35626
35673
|
throw new Error(`Invalid input: ${validation.error}`);
|
|
@@ -35660,10 +35707,12 @@ async function qualityBudget(input, directory) {
|
|
|
35660
35707
|
}
|
|
35661
35708
|
};
|
|
35662
35709
|
}
|
|
35663
|
-
const metrics = await computeQualityMetrics(changedFiles, thresholds, directory);
|
|
35710
|
+
const metrics = await _internals49.computeQualityMetrics(changedFiles, thresholds, directory);
|
|
35711
|
+
abortSignal?.throwIfAborted();
|
|
35664
35712
|
const errorsCount = metrics.violations.filter((v) => v.severity === "error").length;
|
|
35665
35713
|
const warningsCount = metrics.violations.filter((v) => v.severity === "warning").length;
|
|
35666
35714
|
const verdict = errorsCount > 0 ? "fail" : "pass";
|
|
35715
|
+
abortSignal?.throwIfAborted();
|
|
35667
35716
|
await saveEvidence(directory, "quality_budget", {
|
|
35668
35717
|
task_id: "quality_budget",
|
|
35669
35718
|
type: "quality_budget",
|
|
@@ -35690,7 +35739,8 @@ async function qualityBudget(input, directory) {
|
|
|
35690
35739
|
files: v.files
|
|
35691
35740
|
})),
|
|
35692
35741
|
files_analyzed: metrics.files_analyzed
|
|
35693
|
-
});
|
|
35742
|
+
}, abortSignal);
|
|
35743
|
+
abortSignal?.throwIfAborted();
|
|
35694
35744
|
return {
|
|
35695
35745
|
verdict,
|
|
35696
35746
|
metrics,
|
|
@@ -35717,13 +35767,14 @@ var quality_budget = createSwarmTool({
|
|
|
35717
35767
|
exclude_globs: exports_external.array(exports_external.string()).optional()
|
|
35718
35768
|
}).optional().describe("Quality budget thresholds")
|
|
35719
35769
|
},
|
|
35720
|
-
async execute(args, directory) {
|
|
35721
|
-
const result = await _internals49.qualityBudget(args, directory);
|
|
35770
|
+
async execute(args, directory, ctx) {
|
|
35771
|
+
const result = await _internals49.qualityBudget(args, directory, ctx?.abort);
|
|
35722
35772
|
return JSON.stringify(result);
|
|
35723
35773
|
}
|
|
35724
35774
|
});
|
|
35725
35775
|
var _internals49 = {
|
|
35726
|
-
qualityBudget
|
|
35776
|
+
qualityBudget,
|
|
35777
|
+
computeQualityMetrics
|
|
35727
35778
|
};
|
|
35728
35779
|
|
|
35729
35780
|
// src/tools/sast-scan.ts
|
|
@@ -36582,15 +36633,75 @@ function executeRulesSync(filePath, content, language) {
|
|
|
36582
36633
|
}
|
|
36583
36634
|
|
|
36584
36635
|
// src/sast/semgrep.ts
|
|
36585
|
-
init_logger();
|
|
36586
|
-
import * as child_process6 from "child_process";
|
|
36587
36636
|
import * as fs24 from "fs";
|
|
36588
36637
|
import * as path61 from "path";
|
|
36589
36638
|
var semgrepAvailableCache = null;
|
|
36639
|
+
var semgrepAvailabilityProbe = null;
|
|
36640
|
+
var semgrepAvailabilityGeneration = 0;
|
|
36590
36641
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
36591
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;
|
|
36592
36646
|
var MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
|
|
36593
|
-
|
|
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
|
+
}
|
|
36594
36705
|
var _internals50 = {
|
|
36595
36706
|
isSemgrepAvailable,
|
|
36596
36707
|
checkSemgrepAvailable,
|
|
@@ -36598,60 +36709,117 @@ var _internals50 = {
|
|
|
36598
36709
|
runSemgrep,
|
|
36599
36710
|
getRulesDirectory,
|
|
36600
36711
|
hasBundledRules,
|
|
36601
|
-
|
|
36712
|
+
resolveExecutableFromPath,
|
|
36713
|
+
resolveSemgrepBinary,
|
|
36714
|
+
runExternalTool,
|
|
36715
|
+
getAvailabilityProbeCwd
|
|
36602
36716
|
};
|
|
36603
36717
|
function isSemgrepAvailable() {
|
|
36604
36718
|
if (semgrepAvailableCache !== null) {
|
|
36605
36719
|
return semgrepAvailableCache;
|
|
36606
36720
|
}
|
|
36607
|
-
|
|
36608
|
-
|
|
36609
|
-
|
|
36610
|
-
|
|
36611
|
-
|
|
36612
|
-
|
|
36613
|
-
return
|
|
36614
|
-
}
|
|
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) {
|
|
36615
36731
|
semgrepAvailableCache = false;
|
|
36616
36732
|
return false;
|
|
36617
36733
|
}
|
|
36618
|
-
|
|
36619
|
-
|
|
36620
|
-
|
|
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);
|
|
36621
36749
|
}
|
|
36622
36750
|
function resetSemgrepCache() {
|
|
36751
|
+
semgrepAvailabilityGeneration++;
|
|
36623
36752
|
semgrepAvailableCache = null;
|
|
36753
|
+
semgrepAvailabilityProbe = null;
|
|
36624
36754
|
}
|
|
36625
36755
|
function parseSemgrepResults(semgrepOutput) {
|
|
36626
36756
|
const findings = [];
|
|
36627
36757
|
try {
|
|
36628
36758
|
const parsed = JSON.parse(semgrepOutput);
|
|
36629
|
-
|
|
36630
|
-
if (
|
|
36631
|
-
|
|
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;
|
|
36632
36771
|
}
|
|
36772
|
+
if (!Array.isArray(results))
|
|
36773
|
+
throw new Error("invalid Semgrep result shape");
|
|
36633
36774
|
for (const result of results) {
|
|
36634
|
-
if (!result || typeof result !== "object")
|
|
36635
|
-
|
|
36636
|
-
|
|
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);
|
|
36637
36800
|
findings.push({
|
|
36638
|
-
rule_id:
|
|
36801
|
+
rule_id: ruleId,
|
|
36639
36802
|
severity,
|
|
36640
|
-
message:
|
|
36803
|
+
message: message ?? "Security issue detected",
|
|
36641
36804
|
location: {
|
|
36642
|
-
file
|
|
36643
|
-
line
|
|
36644
|
-
column
|
|
36805
|
+
file,
|
|
36806
|
+
line,
|
|
36807
|
+
column
|
|
36645
36808
|
},
|
|
36646
|
-
remediation:
|
|
36647
|
-
excerpt:
|
|
36809
|
+
remediation: extra?.fix,
|
|
36810
|
+
excerpt: extra?.lines ?? entry.lines ?? ""
|
|
36648
36811
|
});
|
|
36649
36812
|
}
|
|
36650
|
-
} catch {
|
|
36651
|
-
|
|
36813
|
+
} catch (error2) {
|
|
36814
|
+
if (error2 instanceof SemgrepScanError)
|
|
36815
|
+
throw error2;
|
|
36816
|
+
throw new Error("Semgrep returned invalid JSON output", { cause: error2 });
|
|
36652
36817
|
}
|
|
36653
36818
|
return findings;
|
|
36654
36819
|
}
|
|
36820
|
+
|
|
36821
|
+
class SemgrepScanError extends Error {
|
|
36822
|
+
}
|
|
36655
36823
|
function mapSemgrepSeverity(severity) {
|
|
36656
36824
|
const severityLower = (severity || "").toLowerCase();
|
|
36657
36825
|
switch (severityLower) {
|
|
@@ -36668,136 +36836,6 @@ function mapSemgrepSeverity(severity) {
|
|
|
36668
36836
|
return "medium";
|
|
36669
36837
|
}
|
|
36670
36838
|
}
|
|
36671
|
-
async function executeWithTimeout(command, args, options) {
|
|
36672
|
-
const maxOutputBytes = options.maxOutputBytes ?? MAX_OUTPUT_BYTES;
|
|
36673
|
-
return new Promise((resolve18) => {
|
|
36674
|
-
const child = child_process6.spawn(command, args, {
|
|
36675
|
-
shell: false,
|
|
36676
|
-
cwd: options.cwd,
|
|
36677
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
36678
|
-
});
|
|
36679
|
-
options.onSpawn?.(child.pid);
|
|
36680
|
-
let stdout = "";
|
|
36681
|
-
let stderr = "";
|
|
36682
|
-
let stdoutBytes = 0;
|
|
36683
|
-
let stderrBytes = 0;
|
|
36684
|
-
let stdoutTruncated = false;
|
|
36685
|
-
let stderrTruncated = false;
|
|
36686
|
-
let settled = false;
|
|
36687
|
-
let timeout;
|
|
36688
|
-
let escalation;
|
|
36689
|
-
const settle = (result) => {
|
|
36690
|
-
if (settled)
|
|
36691
|
-
return;
|
|
36692
|
-
settled = true;
|
|
36693
|
-
if (timeout)
|
|
36694
|
-
clearTimeout(timeout);
|
|
36695
|
-
if (escalation)
|
|
36696
|
-
clearTimeout(escalation);
|
|
36697
|
-
const truncated = stdoutTruncated || stderrTruncated;
|
|
36698
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
36699
|
-
try {
|
|
36700
|
-
child.kill("SIGTERM");
|
|
36701
|
-
} catch (e) {
|
|
36702
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36703
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36704
|
-
}
|
|
36705
|
-
}
|
|
36706
|
-
escalation = setTimeout(() => {
|
|
36707
|
-
try {
|
|
36708
|
-
child.kill("SIGKILL");
|
|
36709
|
-
} catch (e) {
|
|
36710
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36711
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36712
|
-
}
|
|
36713
|
-
}
|
|
36714
|
-
}, KILL_GRACE_MS);
|
|
36715
|
-
if (typeof escalation.unref === "function") {
|
|
36716
|
-
escalation.unref();
|
|
36717
|
-
}
|
|
36718
|
-
}
|
|
36719
|
-
resolve18({ ...result, truncated });
|
|
36720
|
-
};
|
|
36721
|
-
timeout = setTimeout(() => {
|
|
36722
|
-
settle({
|
|
36723
|
-
stdout,
|
|
36724
|
-
stderr: "Process timed out",
|
|
36725
|
-
exitCode: 124
|
|
36726
|
-
});
|
|
36727
|
-
}, options.timeoutMs);
|
|
36728
|
-
if (typeof timeout.unref === "function") {
|
|
36729
|
-
timeout.unref();
|
|
36730
|
-
}
|
|
36731
|
-
child.stdout?.on("data", (data) => {
|
|
36732
|
-
if (stdoutTruncated)
|
|
36733
|
-
return;
|
|
36734
|
-
const chunk = data.toString();
|
|
36735
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
36736
|
-
if (stdoutBytes + chunkBytes > maxOutputBytes) {
|
|
36737
|
-
const remaining = Math.max(0, maxOutputBytes - stdoutBytes);
|
|
36738
|
-
stdout += Buffer.from(chunk, "utf8").subarray(0, remaining).toString("utf8");
|
|
36739
|
-
stdoutBytes = maxOutputBytes;
|
|
36740
|
-
stdoutTruncated = true;
|
|
36741
|
-
settle({
|
|
36742
|
-
stdout,
|
|
36743
|
-
stderr,
|
|
36744
|
-
exitCode: -1
|
|
36745
|
-
});
|
|
36746
|
-
try {
|
|
36747
|
-
child.kill("SIGTERM");
|
|
36748
|
-
} catch (e) {
|
|
36749
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36750
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36751
|
-
}
|
|
36752
|
-
}
|
|
36753
|
-
} else {
|
|
36754
|
-
stdout += chunk;
|
|
36755
|
-
stdoutBytes += chunkBytes;
|
|
36756
|
-
}
|
|
36757
|
-
});
|
|
36758
|
-
child.stderr?.on("data", (data) => {
|
|
36759
|
-
if (stderrTruncated)
|
|
36760
|
-
return;
|
|
36761
|
-
const chunk = data.toString();
|
|
36762
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
36763
|
-
if (stderrBytes + chunkBytes > maxOutputBytes) {
|
|
36764
|
-
const remaining = Math.max(0, maxOutputBytes - stderrBytes);
|
|
36765
|
-
stderr += Buffer.from(chunk, "utf8").subarray(0, remaining).toString("utf8");
|
|
36766
|
-
stderrBytes = maxOutputBytes;
|
|
36767
|
-
stderrTruncated = true;
|
|
36768
|
-
settle({
|
|
36769
|
-
stdout,
|
|
36770
|
-
stderr,
|
|
36771
|
-
exitCode: -1
|
|
36772
|
-
});
|
|
36773
|
-
try {
|
|
36774
|
-
child.kill("SIGTERM");
|
|
36775
|
-
} catch (e) {
|
|
36776
|
-
if (e instanceof Error && !e.message.includes("ESRCH")) {
|
|
36777
|
-
log("[semgrep] child.kill failed:", e.message);
|
|
36778
|
-
}
|
|
36779
|
-
}
|
|
36780
|
-
} else {
|
|
36781
|
-
stderr += chunk;
|
|
36782
|
-
stderrBytes += chunkBytes;
|
|
36783
|
-
}
|
|
36784
|
-
});
|
|
36785
|
-
child.on("close", (code) => {
|
|
36786
|
-
settle({
|
|
36787
|
-
stdout,
|
|
36788
|
-
stderr,
|
|
36789
|
-
exitCode: code ?? 0
|
|
36790
|
-
});
|
|
36791
|
-
});
|
|
36792
|
-
child.on("error", (err) => {
|
|
36793
|
-
settle({
|
|
36794
|
-
stdout,
|
|
36795
|
-
stderr: err.message,
|
|
36796
|
-
exitCode: 1
|
|
36797
|
-
});
|
|
36798
|
-
});
|
|
36799
|
-
});
|
|
36800
|
-
}
|
|
36801
36839
|
async function runSemgrep(options) {
|
|
36802
36840
|
const files = options.files || [];
|
|
36803
36841
|
const rulesDir = options.rulesDir || DEFAULT_RULES_DIR;
|
|
@@ -36809,7 +36847,24 @@ async function runSemgrep(options) {
|
|
|
36809
36847
|
engine: "tier_a"
|
|
36810
36848
|
};
|
|
36811
36849
|
}
|
|
36812
|
-
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) {
|
|
36813
36868
|
return {
|
|
36814
36869
|
available: false,
|
|
36815
36870
|
findings: [],
|
|
@@ -36827,11 +36882,16 @@ async function runSemgrep(options) {
|
|
|
36827
36882
|
}
|
|
36828
36883
|
args.push(...files);
|
|
36829
36884
|
try {
|
|
36830
|
-
const result = await
|
|
36885
|
+
const result = await _internals50.runExternalTool({
|
|
36886
|
+
executable,
|
|
36887
|
+
args,
|
|
36888
|
+
cwd: options.cwd ?? _internals50.getAvailabilityProbeCwd(),
|
|
36831
36889
|
timeoutMs,
|
|
36832
|
-
|
|
36890
|
+
maxStdoutBytes: MAX_OUTPUT_BYTES,
|
|
36891
|
+
maxStderrBytes: MAX_OUTPUT_BYTES,
|
|
36892
|
+
abortSignal: options.abortSignal
|
|
36833
36893
|
});
|
|
36834
|
-
if (result.
|
|
36894
|
+
if (result.stdoutTruncated || result.stderrTruncated) {
|
|
36835
36895
|
return {
|
|
36836
36896
|
available: true,
|
|
36837
36897
|
findings: [],
|
|
@@ -36839,6 +36899,14 @@ async function runSemgrep(options) {
|
|
|
36839
36899
|
engine: "tier_a"
|
|
36840
36900
|
};
|
|
36841
36901
|
}
|
|
36902
|
+
if (result.status !== "completed") {
|
|
36903
|
+
return {
|
|
36904
|
+
available: true,
|
|
36905
|
+
findings: [],
|
|
36906
|
+
error: describeExternalToolFailure(result.status),
|
|
36907
|
+
engine: "tier_a"
|
|
36908
|
+
};
|
|
36909
|
+
}
|
|
36842
36910
|
if (result.exitCode !== 0) {
|
|
36843
36911
|
if (result.exitCode === 1 && result.stdout) {
|
|
36844
36912
|
const findings2 = parseSemgrepResults(result.stdout);
|
|
@@ -36851,7 +36919,7 @@ async function runSemgrep(options) {
|
|
|
36851
36919
|
return {
|
|
36852
36920
|
available: true,
|
|
36853
36921
|
findings: [],
|
|
36854
|
-
error:
|
|
36922
|
+
error: `Semgrep exited with code ${result.exitCode}`,
|
|
36855
36923
|
engine: "tier_a"
|
|
36856
36924
|
};
|
|
36857
36925
|
}
|
|
@@ -36862,11 +36930,11 @@ async function runSemgrep(options) {
|
|
|
36862
36930
|
engine: "tier_a+tier_b"
|
|
36863
36931
|
};
|
|
36864
36932
|
} catch (error2) {
|
|
36865
|
-
const
|
|
36933
|
+
const safeError = error2 instanceof SemgrepScanError || error2 instanceof Error && error2.message === "Semgrep returned invalid JSON output" ? error2.message : "Semgrep execution failed unexpectedly";
|
|
36866
36934
|
return {
|
|
36867
36935
|
available: true,
|
|
36868
36936
|
findings: [],
|
|
36869
|
-
error:
|
|
36937
|
+
error: safeError,
|
|
36870
36938
|
engine: "tier_a"
|
|
36871
36939
|
};
|
|
36872
36940
|
}
|
|
@@ -36980,8 +37048,30 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
36980
37048
|
};
|
|
36981
37049
|
});
|
|
36982
37050
|
}
|
|
36983
|
-
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) {
|
|
36984
37072
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
37073
|
+
if (abortSignal?.aborted)
|
|
37074
|
+
return null;
|
|
36985
37075
|
try {
|
|
36986
37076
|
const fd = fs25.openSync(lockPath, "wx");
|
|
36987
37077
|
fs25.closeSync(fd);
|
|
@@ -36993,7 +37083,9 @@ async function acquireLock2(lockPath) {
|
|
|
36993
37083
|
};
|
|
36994
37084
|
} catch {
|
|
36995
37085
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
36996
|
-
|
|
37086
|
+
if (!await waitForLockRetry(LOCK_RETRY_DELAYS_MS[attempt], abortSignal)) {
|
|
37087
|
+
return null;
|
|
37088
|
+
}
|
|
36997
37089
|
}
|
|
36998
37090
|
}
|
|
36999
37091
|
}
|
|
@@ -37028,9 +37120,19 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37028
37120
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
37029
37121
|
};
|
|
37030
37122
|
}
|
|
37123
|
+
if (opts?.abortSignal?.aborted) {
|
|
37124
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37125
|
+
}
|
|
37031
37126
|
fs25.mkdirSync(path62.dirname(baselinePath), { recursive: true });
|
|
37032
37127
|
fs25.mkdirSync(path62.dirname(tempPath), { recursive: true });
|
|
37033
|
-
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
|
+
}
|
|
37034
37136
|
try {
|
|
37035
37137
|
let existing = null;
|
|
37036
37138
|
try {
|
|
@@ -37094,7 +37196,14 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37094
37196
|
message: `Baseline would exceed size cap (${json2.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
37095
37197
|
};
|
|
37096
37198
|
}
|
|
37199
|
+
if (opts?.abortSignal?.aborted) {
|
|
37200
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37201
|
+
}
|
|
37097
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
|
+
}
|
|
37098
37207
|
fs25.renameSync(tempPath, baselinePath);
|
|
37099
37208
|
invalidateCachedArtifact(baselinePath);
|
|
37100
37209
|
return {
|
|
@@ -37127,7 +37236,14 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
37127
37236
|
message: `Baseline would exceed size cap (${json.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
37128
37237
|
};
|
|
37129
37238
|
}
|
|
37239
|
+
if (opts?.abortSignal?.aborted) {
|
|
37240
|
+
return { status: "error", message: "SAST baseline capture cancelled" };
|
|
37241
|
+
}
|
|
37130
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
|
+
}
|
|
37131
37247
|
fs25.renameSync(tempPath, baselinePath);
|
|
37132
37248
|
invalidateCachedArtifact(baselinePath);
|
|
37133
37249
|
return {
|
|
@@ -37249,6 +37365,36 @@ function countBySeverity(findings) {
|
|
|
37249
37365
|
}
|
|
37250
37366
|
return counts;
|
|
37251
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
|
+
}
|
|
37252
37398
|
function scanFileWithTierA(filePath, language) {
|
|
37253
37399
|
try {
|
|
37254
37400
|
const content = fs26.readFileSync(filePath, "utf-8");
|
|
@@ -37274,7 +37420,8 @@ async function sastScan(input, directory, config) {
|
|
|
37274
37420
|
severity_threshold = "medium",
|
|
37275
37421
|
capture_baseline = false,
|
|
37276
37422
|
phase,
|
|
37277
|
-
offline_only = false
|
|
37423
|
+
offline_only = false,
|
|
37424
|
+
abort_signal
|
|
37278
37425
|
} = input;
|
|
37279
37426
|
if (config?.gates?.sast_scan?.enabled === false) {
|
|
37280
37427
|
return {
|
|
@@ -37297,10 +37444,17 @@ async function sastScan(input, directory, config) {
|
|
|
37297
37444
|
let filesScanned = 0;
|
|
37298
37445
|
let _filesSkipped = 0;
|
|
37299
37446
|
const scannedFilePaths = [];
|
|
37300
|
-
|
|
37447
|
+
if (abort_signal?.aborted) {
|
|
37448
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37449
|
+
}
|
|
37450
|
+
const semgrepAvailable = !offline_only && await _internals52.checkSemgrepAvailable(directory, abort_signal);
|
|
37301
37451
|
const engine = semgrepAvailable ? "tier_a+tier_b" : "tier_a";
|
|
37302
37452
|
const filesByLanguage = new Map;
|
|
37453
|
+
let semgrepError = abort_signal?.aborted ? "SAST scan cancelled" : undefined;
|
|
37303
37454
|
for (const filePath of changed_files) {
|
|
37455
|
+
if (abort_signal?.aborted) {
|
|
37456
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37457
|
+
}
|
|
37304
37458
|
if (typeof filePath !== "string" || !filePath) {
|
|
37305
37459
|
_filesSkipped++;
|
|
37306
37460
|
continue;
|
|
@@ -37355,6 +37509,10 @@ async function sastScan(input, directory, config) {
|
|
|
37355
37509
|
if (semgrepAvailable && filesByLanguage.size > 0) {
|
|
37356
37510
|
try {
|
|
37357
37511
|
for (const [bucketKey, bucketFiles] of filesByLanguage.entries()) {
|
|
37512
|
+
if (abort_signal?.aborted) {
|
|
37513
|
+
semgrepError = "SAST scan cancelled";
|
|
37514
|
+
break;
|
|
37515
|
+
}
|
|
37358
37516
|
if (bucketFiles.length === 0)
|
|
37359
37517
|
continue;
|
|
37360
37518
|
let semgrepResult;
|
|
@@ -37363,13 +37521,21 @@ async function sastScan(input, directory, config) {
|
|
|
37363
37521
|
semgrepResult = await _internals52.runSemgrep({
|
|
37364
37522
|
files: bucketFiles,
|
|
37365
37523
|
lang,
|
|
37366
|
-
useAutoConfig: true
|
|
37524
|
+
useAutoConfig: true,
|
|
37525
|
+
cwd: directory,
|
|
37526
|
+
abortSignal: abort_signal
|
|
37367
37527
|
});
|
|
37368
37528
|
} else {
|
|
37369
37529
|
semgrepResult = await _internals52.runSemgrep({
|
|
37370
|
-
files: bucketFiles
|
|
37530
|
+
files: bucketFiles,
|
|
37531
|
+
cwd: directory,
|
|
37532
|
+
abortSignal: abort_signal
|
|
37371
37533
|
});
|
|
37372
37534
|
}
|
|
37535
|
+
if (semgrepResult.error) {
|
|
37536
|
+
semgrepError = safeSemgrepDiagnostic(semgrepResult.error);
|
|
37537
|
+
break;
|
|
37538
|
+
}
|
|
37373
37539
|
if (semgrepResult.findings.length > 0) {
|
|
37374
37540
|
const semgrepFindings = semgrepResult.findings.map((f) => ({
|
|
37375
37541
|
rule_id: f.rule_id,
|
|
@@ -37392,9 +37558,42 @@ async function sastScan(input, directory, config) {
|
|
|
37392
37558
|
}
|
|
37393
37559
|
}
|
|
37394
37560
|
}
|
|
37395
|
-
} catch
|
|
37396
|
-
|
|
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);
|
|
37397
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
|
+
};
|
|
37398
37597
|
}
|
|
37399
37598
|
if (capture_baseline) {
|
|
37400
37599
|
if (phase === undefined || !Number.isInteger(phase) || phase < 1) {
|
|
@@ -37425,7 +37624,10 @@ async function sastScan(input, directory, config) {
|
|
|
37425
37624
|
};
|
|
37426
37625
|
}
|
|
37427
37626
|
const captureFindings = allFindings.slice(0, MAX_BASELINE_FINDINGS);
|
|
37428
|
-
|
|
37627
|
+
if (abort_signal?.aborted) {
|
|
37628
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37629
|
+
}
|
|
37630
|
+
const captureResult = await captureOrMergeBaseline(directory, phase, captureFindings, engine, scannedFilePaths, { abortSignal: abort_signal });
|
|
37429
37631
|
const captureStatus = captureResult.status === "written" ? "baseline_captured" : captureResult.status === "merged" ? "baseline_merged" : undefined;
|
|
37430
37632
|
if (captureResult.status === "error") {
|
|
37431
37633
|
warn(`SAST Baseline: capture failed \u2014 ${captureResult.message}`);
|
|
@@ -37437,6 +37639,9 @@ async function sastScan(input, directory, config) {
|
|
|
37437
37639
|
findings_count: finalFindings2.length,
|
|
37438
37640
|
findings_by_severity: countBySeverity(finalFindings2)
|
|
37439
37641
|
};
|
|
37642
|
+
if (abort_signal?.aborted) {
|
|
37643
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37644
|
+
}
|
|
37440
37645
|
await saveEvidence(directory, "sast_scan", {
|
|
37441
37646
|
task_id: "sast_scan",
|
|
37442
37647
|
type: "sast",
|
|
@@ -37447,7 +37652,7 @@ async function sastScan(input, directory, config) {
|
|
|
37447
37652
|
...summary2,
|
|
37448
37653
|
findings: finalFindings2,
|
|
37449
37654
|
baseline_used: false
|
|
37450
|
-
});
|
|
37655
|
+
}, abort_signal);
|
|
37451
37656
|
return {
|
|
37452
37657
|
verdict: "pass",
|
|
37453
37658
|
findings: finalFindings2,
|
|
@@ -37515,6 +37720,9 @@ async function sastScan(input, directory, config) {
|
|
|
37515
37720
|
findings_count: finalFindings.length,
|
|
37516
37721
|
findings_by_severity: findingsBySeverity
|
|
37517
37722
|
};
|
|
37723
|
+
if (abort_signal?.aborted) {
|
|
37724
|
+
return cancelledScanResult(allFindings, filesScanned);
|
|
37725
|
+
}
|
|
37518
37726
|
await saveEvidence(directory, "sast_scan", {
|
|
37519
37727
|
task_id: "sast_scan",
|
|
37520
37728
|
type: "sast",
|
|
@@ -37529,7 +37737,7 @@ async function sastScan(input, directory, config) {
|
|
|
37529
37737
|
pre_existing_findings: preExistingFindings,
|
|
37530
37738
|
baseline_used: true
|
|
37531
37739
|
}
|
|
37532
|
-
});
|
|
37740
|
+
}, abort_signal);
|
|
37533
37741
|
const result = {
|
|
37534
37742
|
verdict,
|
|
37535
37743
|
findings: finalFindings,
|
|
@@ -37553,7 +37761,7 @@ var sast_scan = createSwarmTool({
|
|
|
37553
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."),
|
|
37554
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.")
|
|
37555
37763
|
},
|
|
37556
|
-
execute: async (args, directory) => {
|
|
37764
|
+
execute: async (args, directory, ctx) => {
|
|
37557
37765
|
let safeArgs;
|
|
37558
37766
|
try {
|
|
37559
37767
|
if (args && typeof args === "object") {
|
|
@@ -37606,7 +37814,8 @@ var sast_scan = createSwarmTool({
|
|
|
37606
37814
|
changed_files: safeArgs.changed_files ?? [],
|
|
37607
37815
|
severity_threshold: safeArgs.severity_threshold ?? "medium",
|
|
37608
37816
|
capture_baseline: safeArgs.capture_baseline,
|
|
37609
|
-
phase: safeArgs.phase
|
|
37817
|
+
phase: safeArgs.phase,
|
|
37818
|
+
abort_signal: ctx?.abort
|
|
37610
37819
|
};
|
|
37611
37820
|
const result = await _internals52.sastScan(input, directory);
|
|
37612
37821
|
return JSON.stringify(result, null, 2);
|
|
@@ -37615,6 +37824,7 @@ var sast_scan = createSwarmTool({
|
|
|
37615
37824
|
var _internals52 = {
|
|
37616
37825
|
sastScan,
|
|
37617
37826
|
sast_scan,
|
|
37827
|
+
checkSemgrepAvailable: (directory, abortSignal) => checkSemgrepAvailable(directory, abortSignal),
|
|
37618
37828
|
isSemgrepAvailable: () => isSemgrepAvailable(),
|
|
37619
37829
|
runSemgrep: (options) => runSemgrep(options)
|
|
37620
37830
|
};
|
|
@@ -43166,6 +43376,22 @@ import * as fs30 from "fs";
|
|
|
43166
43376
|
import * as path76 from "path";
|
|
43167
43377
|
var MAX_OUTPUT_BYTES2 = 512000;
|
|
43168
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
|
+
};
|
|
43169
43395
|
function validateArgs(args) {
|
|
43170
43396
|
if (typeof args !== "object" || args === null)
|
|
43171
43397
|
return false;
|
|
@@ -43174,112 +43400,533 @@ function validateArgs(args) {
|
|
|
43174
43400
|
return false;
|
|
43175
43401
|
return true;
|
|
43176
43402
|
}
|
|
43177
|
-
function
|
|
43178
|
-
|
|
43179
|
-
|
|
43180
|
-
|
|
43181
|
-
|
|
43182
|
-
|
|
43183
|
-
|
|
43184
|
-
|
|
43185
|
-
|
|
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
|
+
};
|
|
43186
43571
|
}
|
|
43187
|
-
|
|
43188
|
-
|
|
43189
|
-
|
|
43190
|
-
|
|
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;
|
|
43191
43592
|
}
|
|
43192
|
-
|
|
43593
|
+
}
|
|
43193
43594
|
}
|
|
43595
|
+
return null;
|
|
43194
43596
|
}
|
|
43195
|
-
function
|
|
43196
|
-
const
|
|
43197
|
-
const
|
|
43198
|
-
|
|
43199
|
-
|
|
43200
|
-
|
|
43201
|
-
|
|
43202
|
-
|
|
43203
|
-
|
|
43204
|
-
|
|
43205
|
-
|
|
43206
|
-
|
|
43207
|
-
|
|
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;
|
|
43208
43630
|
}
|
|
43209
|
-
|
|
43210
|
-
|
|
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;
|
|
43211
43642
|
}
|
|
43212
|
-
|
|
43213
|
-
|
|
43214
|
-
|
|
43215
|
-
|
|
43216
|
-
|
|
43217
|
-
|
|
43218
|
-
|
|
43219
|
-
|
|
43220
|
-
|
|
43221
|
-
|
|
43222
|
-
|
|
43223
|
-
|
|
43224
|
-
|
|
43225
|
-
|
|
43226
|
-
|
|
43227
|
-
|
|
43228
|
-
|
|
43229
|
-
|
|
43230
|
-
|
|
43231
|
-
|
|
43232
|
-
|
|
43233
|
-
|
|
43234
|
-
|
|
43235
|
-
|
|
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
|
+
}
|
|
43236
43780
|
}
|
|
43781
|
+
return null;
|
|
43237
43782
|
}
|
|
43238
43783
|
function detectRuff(cwd) {
|
|
43239
|
-
if (
|
|
43240
|
-
return
|
|
43784
|
+
if (_internals64.existsSync(path76.join(cwd, "ruff.toml")))
|
|
43785
|
+
return hasAdditionalCommand("ruff");
|
|
43241
43786
|
try {
|
|
43242
43787
|
const pyproject = path76.join(cwd, "pyproject.toml");
|
|
43243
|
-
if (
|
|
43244
|
-
const content =
|
|
43788
|
+
if (_internals64.existsSync(pyproject)) {
|
|
43789
|
+
const content = _internals64.readFileSync(pyproject, "utf-8");
|
|
43245
43790
|
if (content.includes("[tool.ruff]"))
|
|
43246
|
-
return
|
|
43791
|
+
return hasAdditionalCommand("ruff");
|
|
43247
43792
|
}
|
|
43248
43793
|
} catch {}
|
|
43249
43794
|
return false;
|
|
43250
43795
|
}
|
|
43251
43796
|
function detectClippy(cwd) {
|
|
43252
|
-
return
|
|
43797
|
+
return _internals64.existsSync(path76.join(cwd, "Cargo.toml")) && hasAdditionalCommand("cargo");
|
|
43253
43798
|
}
|
|
43254
43799
|
function detectGolangciLint(cwd) {
|
|
43255
|
-
return
|
|
43800
|
+
return _internals64.existsSync(path76.join(cwd, "go.mod")) && hasAdditionalCommand("golangci-lint");
|
|
43256
43801
|
}
|
|
43257
43802
|
function readTextFileSafe(filePath) {
|
|
43258
43803
|
try {
|
|
43259
|
-
return
|
|
43804
|
+
return _internals64.readFileSync(filePath, "utf-8");
|
|
43260
43805
|
} catch {
|
|
43261
43806
|
return "";
|
|
43262
43807
|
}
|
|
43263
43808
|
}
|
|
43264
|
-
function
|
|
43265
|
-
const
|
|
43266
|
-
|
|
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;
|
|
43267
43920
|
}
|
|
43268
|
-
function
|
|
43269
|
-
|
|
43270
|
-
const localWin = path76.join(cwd, "vendor", "bin", `${name}.bat`);
|
|
43271
|
-
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());
|
|
43272
43923
|
}
|
|
43273
43924
|
function detectCheckstyle(cwd) {
|
|
43274
|
-
|
|
43275
|
-
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path76.join(cwd, file)).filter((file) => fs30.existsSync(file));
|
|
43276
|
-
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)));
|
|
43277
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs30.existsSync(path76.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
43278
|
-
return (hasMaven || hasGradleCheckstyleSignal) && hasBinary;
|
|
43925
|
+
return resolveCheckstyleCommand(cwd) !== null;
|
|
43279
43926
|
}
|
|
43280
43927
|
function hasRootKotlinFile(cwd) {
|
|
43281
43928
|
try {
|
|
43282
|
-
return
|
|
43929
|
+
return _internals64.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
43283
43930
|
} catch {
|
|
43284
43931
|
return false;
|
|
43285
43932
|
}
|
|
@@ -43289,59 +43936,59 @@ function buildGradleHasKotlinSignal(cwd) {
|
|
|
43289
43936
|
return /\b(kotlin|org\.jetbrains\.kotlin|ktlint)\b/i.test(content);
|
|
43290
43937
|
}
|
|
43291
43938
|
function detectKtlint(cwd) {
|
|
43292
|
-
const hasKotlin =
|
|
43293
|
-
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");
|
|
43294
43941
|
}
|
|
43295
43942
|
function detectPhpLinter(cwd) {
|
|
43296
|
-
if ((
|
|
43943
|
+
if ((_internals64.existsSync(path76.join(cwd, "phpstan.neon")) || _internals64.existsSync(path76.join(cwd, "phpstan.neon.dist"))) && resolvePhpVendorCommand(cwd, "phpstan") !== null) {
|
|
43297
43944
|
return "phpstan";
|
|
43298
43945
|
}
|
|
43299
|
-
if (
|
|
43946
|
+
if (_internals64.existsSync(path76.join(cwd, "pint.json")) && resolvePhpVendorCommand(cwd, "pint") !== null) {
|
|
43300
43947
|
return "pint";
|
|
43301
43948
|
}
|
|
43302
|
-
if (
|
|
43949
|
+
if (_internals64.existsSync(path76.join(cwd, ".php-cs-fixer.php")) && resolvePhpVendorCommand(cwd, "php-cs-fixer") !== null) {
|
|
43303
43950
|
return "php-cs-fixer";
|
|
43304
43951
|
}
|
|
43305
|
-
if (
|
|
43952
|
+
if (_internals64.existsSync(path76.join(cwd, "phpcs.xml")) && resolvePhpVendorCommand(cwd, "phpcs") !== null) {
|
|
43306
43953
|
return "phpcs";
|
|
43307
43954
|
}
|
|
43308
43955
|
return null;
|
|
43309
43956
|
}
|
|
43310
43957
|
function detectDotnetFormat(cwd) {
|
|
43311
43958
|
try {
|
|
43312
|
-
const files =
|
|
43959
|
+
const files = _internals64.readdirSync(cwd);
|
|
43313
43960
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
43314
|
-
return hasCsproj &&
|
|
43961
|
+
return hasCsproj && hasAdditionalCommand("dotnet");
|
|
43315
43962
|
} catch {
|
|
43316
43963
|
return false;
|
|
43317
43964
|
}
|
|
43318
43965
|
}
|
|
43319
43966
|
function detectCppcheck(cwd) {
|
|
43320
|
-
if (
|
|
43321
|
-
return
|
|
43967
|
+
if (_internals64.existsSync(path76.join(cwd, "CMakeLists.txt"))) {
|
|
43968
|
+
return hasAdditionalCommand("cppcheck");
|
|
43322
43969
|
}
|
|
43323
43970
|
try {
|
|
43324
43971
|
const dirsToCheck = [cwd, path76.join(cwd, "src")];
|
|
43325
43972
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
43326
43973
|
try {
|
|
43327
|
-
return
|
|
43974
|
+
return _internals64.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
43328
43975
|
} catch {
|
|
43329
43976
|
return false;
|
|
43330
43977
|
}
|
|
43331
43978
|
});
|
|
43332
|
-
return hasCpp &&
|
|
43979
|
+
return hasCpp && hasAdditionalCommand("cppcheck");
|
|
43333
43980
|
} catch {
|
|
43334
43981
|
return false;
|
|
43335
43982
|
}
|
|
43336
43983
|
}
|
|
43337
43984
|
function detectSwiftlint(cwd) {
|
|
43338
|
-
return
|
|
43985
|
+
return _internals64.existsSync(path76.join(cwd, "Package.swift")) && hasAdditionalCommand("swiftlint");
|
|
43339
43986
|
}
|
|
43340
43987
|
function detectDartAnalyze(cwd) {
|
|
43341
|
-
return
|
|
43988
|
+
return _internals64.existsSync(path76.join(cwd, "pubspec.yaml")) && hasAdditionalCommand("dart");
|
|
43342
43989
|
}
|
|
43343
43990
|
function detectRubocop(cwd) {
|
|
43344
|
-
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"));
|
|
43345
43992
|
}
|
|
43346
43993
|
function detectAdditionalLinter(cwd) {
|
|
43347
43994
|
if (detectRuff(cwd))
|
|
@@ -43369,208 +44016,179 @@ function detectAdditionalLinter(cwd) {
|
|
|
43369
44016
|
return "rubocop";
|
|
43370
44017
|
return null;
|
|
43371
44018
|
}
|
|
43372
|
-
function findBinInAncestors(startDir, binName) {
|
|
43373
|
-
let dir = startDir;
|
|
43374
|
-
while (true) {
|
|
43375
|
-
const candidate = path76.join(dir, "node_modules", ".bin", binName);
|
|
43376
|
-
if (fs30.existsSync(candidate))
|
|
43377
|
-
return candidate;
|
|
43378
|
-
const parent = path76.dirname(dir);
|
|
43379
|
-
if (parent === dir)
|
|
43380
|
-
break;
|
|
43381
|
-
dir = parent;
|
|
43382
|
-
}
|
|
43383
|
-
return null;
|
|
43384
|
-
}
|
|
43385
|
-
function findBinInEnvPath(binName) {
|
|
43386
|
-
const searchPath = process.env.PATH ?? "";
|
|
43387
|
-
for (const dir of searchPath.split(path76.delimiter)) {
|
|
43388
|
-
if (!dir)
|
|
43389
|
-
continue;
|
|
43390
|
-
const candidate = path76.join(dir, binName);
|
|
43391
|
-
if (fs30.existsSync(candidate))
|
|
43392
|
-
return candidate;
|
|
43393
|
-
}
|
|
43394
|
-
return null;
|
|
43395
|
-
}
|
|
43396
44019
|
async function detectAvailableLinter(directory) {
|
|
43397
|
-
|
|
43398
|
-
|
|
43399
|
-
if (!fs30.existsSync(directory))
|
|
43400
|
-
return null;
|
|
43401
|
-
const projectDir = directory;
|
|
43402
|
-
const isWindows = process.platform === "win32";
|
|
43403
|
-
const biomeBin = isWindows ? path76.join(projectDir, "node_modules", ".bin", "biome.EXE") : path76.join(projectDir, "node_modules", ".bin", "biome");
|
|
43404
|
-
const eslintBin = isWindows ? path76.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path76.join(projectDir, "node_modules", ".bin", "eslint");
|
|
43405
|
-
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
43406
|
-
if (localResult)
|
|
43407
|
-
return localResult;
|
|
43408
|
-
const biomeAncestor = findBinInAncestors(path76.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
43409
|
-
const eslintAncestor = findBinInAncestors(path76.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
43410
|
-
if (biomeAncestor || eslintAncestor) {
|
|
43411
|
-
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
43412
|
-
}
|
|
43413
|
-
const pathBiome = findBinInEnvPath(isWindows ? "biome.EXE" : "biome");
|
|
43414
|
-
const pathEslint = findBinInEnvPath(isWindows ? "eslint.cmd" : "eslint");
|
|
43415
|
-
if (pathBiome || pathEslint) {
|
|
43416
|
-
return _detectAvailableLinter(projectDir, pathBiome ?? biomeBin, pathEslint ?? eslintBin);
|
|
43417
|
-
}
|
|
43418
|
-
return null;
|
|
44020
|
+
const resolved = await detectResolvedLinter(directory);
|
|
44021
|
+
return resolved?.linter ?? null;
|
|
43419
44022
|
}
|
|
43420
|
-
async function
|
|
43421
|
-
const
|
|
43422
|
-
|
|
43423
|
-
|
|
43424
|
-
stdout: "pipe",
|
|
43425
|
-
stderr: "pipe"
|
|
43426
|
-
});
|
|
43427
|
-
const biomeExit = biomeProc.exited;
|
|
43428
|
-
const timeout = new Promise((resolve23) => setTimeout(() => resolve23("timeout"), DETECT_TIMEOUT));
|
|
43429
|
-
const result = await Promise.race([biomeExit, timeout]);
|
|
43430
|
-
if (result === "timeout") {
|
|
43431
|
-
biomeProc.kill();
|
|
43432
|
-
} else if (biomeProc.exitCode === 0 && fs30.existsSync(biomeBin)) {
|
|
43433
|
-
return "biome";
|
|
43434
|
-
}
|
|
43435
|
-
} catch {}
|
|
43436
|
-
try {
|
|
43437
|
-
const eslintProc = bunSpawn([eslintBin, "--version"], {
|
|
43438
|
-
stdout: "pipe",
|
|
43439
|
-
stderr: "pipe"
|
|
43440
|
-
});
|
|
43441
|
-
const eslintExit = eslintProc.exited;
|
|
43442
|
-
const timeout = new Promise((resolve23) => setTimeout(() => resolve23("timeout"), DETECT_TIMEOUT));
|
|
43443
|
-
const result = await Promise.race([eslintExit, timeout]);
|
|
43444
|
-
if (result === "timeout") {
|
|
43445
|
-
eslintProc.kill();
|
|
43446
|
-
} else if (eslintProc.exitCode === 0 && fs30.existsSync(eslintBin)) {
|
|
43447
|
-
return "eslint";
|
|
43448
|
-
}
|
|
43449
|
-
} catch {}
|
|
43450
|
-
return null;
|
|
43451
|
-
}
|
|
43452
|
-
async function runLint(linter, mode, directory) {
|
|
43453
|
-
const command = getLinterCommand(linter, mode, directory);
|
|
43454
|
-
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(" ");
|
|
43455
44027
|
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
43456
44028
|
return {
|
|
43457
44029
|
success: false,
|
|
43458
44030
|
mode,
|
|
43459
|
-
linter,
|
|
43460
|
-
command,
|
|
44031
|
+
linter: command.linter,
|
|
44032
|
+
command: displayCommand,
|
|
43461
44033
|
error: "Command exceeds maximum allowed length"
|
|
43462
44034
|
};
|
|
43463
44035
|
}
|
|
43464
|
-
|
|
43465
|
-
|
|
43466
|
-
|
|
43467
|
-
|
|
43468
|
-
|
|
43469
|
-
|
|
43470
|
-
|
|
43471
|
-
|
|
43472
|
-
|
|
43473
|
-
|
|
43474
|
-
|
|
43475
|
-
|
|
43476
|
-
|
|
43477
|
-
|
|
43478
|
-
|
|
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"] : []);
|
|
43479
44096
|
}
|
|
43480
|
-
|
|
43481
|
-
|
|
43482
|
-
...
|
|
44097
|
+
case "phpstan": {
|
|
44098
|
+
const base = resolvePhpVendorCommand(cwd, "phpstan");
|
|
44099
|
+
return base ? [...base, "analyse"] : null;
|
|
43483
44100
|
}
|
|
43484
|
-
|
|
43485
|
-
|
|
43486
|
-
mode,
|
|
43487
|
-
linter,
|
|
43488
|
-
command,
|
|
43489
|
-
exitCode,
|
|
43490
|
-
output
|
|
43491
|
-
};
|
|
43492
|
-
if (exitCode === 0) {
|
|
43493
|
-
result.message = `${linter} ${mode} completed successfully with no issues`;
|
|
43494
|
-
} else if (mode === "fix") {
|
|
43495
|
-
result.message = `${linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
43496
|
-
} else {
|
|
43497
|
-
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;
|
|
43498
44104
|
}
|
|
43499
|
-
|
|
43500
|
-
|
|
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) {
|
|
43501
44116
|
return {
|
|
43502
44117
|
success: false,
|
|
43503
44118
|
mode,
|
|
43504
44119
|
linter,
|
|
43505
|
-
|
|
43506
|
-
error: error2 instanceof Error ? `Execution failed: ${error2.message}` : "Execution failed: unknown error"
|
|
44120
|
+
error: `No safely resolved ${linter} executable found`
|
|
43507
44121
|
};
|
|
43508
44122
|
}
|
|
44123
|
+
return runResolvedLint(resolved, mode, directory, abortSignal);
|
|
43509
44124
|
}
|
|
43510
|
-
async function runAdditionalLint(linter, mode, cwd) {
|
|
44125
|
+
async function runAdditionalLint(linter, mode, cwd, abortSignal) {
|
|
43511
44126
|
const command = getAdditionalLinterCommand(linter, mode, cwd);
|
|
43512
|
-
|
|
43513
|
-
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
44127
|
+
if (!command) {
|
|
43514
44128
|
return {
|
|
43515
44129
|
success: false,
|
|
43516
44130
|
mode,
|
|
43517
44131
|
linter,
|
|
43518
|
-
command
|
|
43519
|
-
error: "Command exceeds maximum allowed length"
|
|
44132
|
+
error: `No safely executable ${linter} command found`
|
|
43520
44133
|
};
|
|
43521
44134
|
}
|
|
43522
|
-
|
|
43523
|
-
|
|
43524
|
-
|
|
43525
|
-
|
|
43526
|
-
cwd
|
|
43527
|
-
});
|
|
43528
|
-
const [stdout, stderr] = await Promise.all([
|
|
43529
|
-
proc.stdout.text(),
|
|
43530
|
-
proc.stderr.text()
|
|
43531
|
-
]);
|
|
43532
|
-
const exitCode = await proc.exited;
|
|
43533
|
-
let output = stdout;
|
|
43534
|
-
if (stderr) {
|
|
43535
|
-
output += (output ? `
|
|
43536
|
-
` : "") + stderr;
|
|
43537
|
-
}
|
|
43538
|
-
if (output.length > MAX_OUTPUT_BYTES2) {
|
|
43539
|
-
output = `${output.slice(0, MAX_OUTPUT_BYTES2)}
|
|
43540
|
-
... (output truncated)`;
|
|
43541
|
-
}
|
|
43542
|
-
const result = {
|
|
43543
|
-
success: true,
|
|
44135
|
+
const commandStr = command.join(" ");
|
|
44136
|
+
if (commandStr.length > MAX_COMMAND_LENGTH) {
|
|
44137
|
+
return {
|
|
44138
|
+
success: false,
|
|
43544
44139
|
mode,
|
|
43545
44140
|
linter,
|
|
43546
44141
|
command,
|
|
43547
|
-
|
|
43548
|
-
output
|
|
44142
|
+
error: "Command exceeds maximum allowed length"
|
|
43549
44143
|
};
|
|
43550
|
-
|
|
43551
|
-
|
|
43552
|
-
|
|
43553
|
-
result.message = `${linter} fix completed with exit code ${exitCode}. Run check mode to see remaining issues.`;
|
|
43554
|
-
} else {
|
|
43555
|
-
result.message = `${linter} check found issues (exit code ${exitCode}).`;
|
|
43556
|
-
}
|
|
43557
|
-
return result;
|
|
43558
|
-
} catch (error2) {
|
|
44144
|
+
}
|
|
44145
|
+
const [executable, ...args] = command;
|
|
44146
|
+
if (isUnsafeShellWrapperExecutable(executable)) {
|
|
43559
44147
|
return {
|
|
43560
44148
|
success: false,
|
|
43561
44149
|
mode,
|
|
43562
44150
|
linter,
|
|
43563
44151
|
command,
|
|
43564
|
-
error:
|
|
44152
|
+
error: `No safely executable ${linter} command found`
|
|
43565
44153
|
};
|
|
43566
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;
|
|
43567
44185
|
}
|
|
43568
44186
|
var lint = createSwarmTool({
|
|
43569
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.",
|
|
43570
44188
|
args: {
|
|
43571
44189
|
mode: exports_external.enum(["fix", "check"]).describe('Linting mode: "check" for read-only lint check, "fix" to automatically apply fixes')
|
|
43572
44190
|
},
|
|
43573
|
-
async execute(args, directory) {
|
|
44191
|
+
async execute(args, directory, ctx) {
|
|
43574
44192
|
if (!validateArgs(args)) {
|
|
43575
44193
|
const errorResult2 = {
|
|
43576
44194
|
success: false,
|
|
@@ -43589,15 +44207,15 @@ var lint = createSwarmTool({
|
|
|
43589
44207
|
}
|
|
43590
44208
|
const { mode } = args;
|
|
43591
44209
|
const cwd = directory;
|
|
43592
|
-
const
|
|
43593
|
-
if (
|
|
43594
|
-
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);
|
|
43595
44213
|
return JSON.stringify(result, null, 2);
|
|
43596
44214
|
}
|
|
43597
44215
|
const additionalLinter = _internals64.detectAdditionalLinter(cwd);
|
|
43598
44216
|
if (additionalLinter) {
|
|
43599
44217
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
43600
|
-
const result = await _internals64.runAdditionalLint(additionalLinter, mode, cwd);
|
|
44218
|
+
const result = await _internals64.runAdditionalLint(additionalLinter, mode, cwd, ctx?.abort);
|
|
43601
44219
|
return JSON.stringify(result, null, 2);
|
|
43602
44220
|
}
|
|
43603
44221
|
const errorResult = {
|
|
@@ -43612,10 +44230,31 @@ For Rust: rustup component add clippy`
|
|
|
43612
44230
|
}
|
|
43613
44231
|
});
|
|
43614
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,
|
|
43615
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,
|
|
43616
44255
|
runLint,
|
|
43617
|
-
|
|
43618
|
-
|
|
44256
|
+
runResolvedLint,
|
|
44257
|
+
statSync: fs30.statSync
|
|
43619
44258
|
};
|
|
43620
44259
|
|
|
43621
44260
|
// src/tools/secretscan.ts
|
|
@@ -43979,8 +44618,19 @@ function createRedactedContext(line, findings) {
|
|
|
43979
44618
|
return `${result.slice(0, edgeLength)}${truncationMarker}${result.slice(-remaining)}`;
|
|
43980
44619
|
}
|
|
43981
44620
|
var O_NOFOLLOW = process.platform !== "win32" ? fs31.constants.O_NOFOLLOW : undefined;
|
|
43982
|
-
function
|
|
43983
|
-
|
|
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;
|
|
43984
44634
|
try {
|
|
43985
44635
|
const flags = fs31.constants.O_RDONLY | (O_NOFOLLOW !== undefined ? O_NOFOLLOW : 0);
|
|
43986
44636
|
fd = _internals65.openFile(filePath, flags);
|
|
@@ -43988,13 +44638,17 @@ function readBoundedFile(filePath) {
|
|
|
43988
44638
|
return { status: "incomplete", reason: "read_error" };
|
|
43989
44639
|
}
|
|
43990
44640
|
let outcome;
|
|
44641
|
+
let closeFailed = false;
|
|
43991
44642
|
try {
|
|
43992
44643
|
const stat6 = _internals65.fstatFile(fd);
|
|
44644
|
+
const descriptorIdentity = getStableFileIdentity(stat6);
|
|
43993
44645
|
const initialSize = stat6.size;
|
|
43994
44646
|
if (!stat6.isFile()) {
|
|
43995
44647
|
outcome = { status: "incomplete", reason: "non_file" };
|
|
44648
|
+
} else if (descriptorIdentity === null || descriptorIdentity !== expectedIdentity) {
|
|
44649
|
+
outcome = { status: "incomplete", reason: "read_error" };
|
|
43996
44650
|
} else {
|
|
43997
|
-
const bufferLength =
|
|
44651
|
+
const bufferLength = initialSize >= BigInt(MAX_FILE_SIZE_BYTES3) ? MAX_FILE_SIZE_BYTES3 + 1 : Number(initialSize) + 1;
|
|
43998
44652
|
const buffer = Buffer.allocUnsafe(bufferLength);
|
|
43999
44653
|
let bytesRead = 0;
|
|
44000
44654
|
while (bytesRead < buffer.length) {
|
|
@@ -44004,10 +44658,15 @@ function readBoundedFile(filePath) {
|
|
|
44004
44658
|
bytesRead += count;
|
|
44005
44659
|
}
|
|
44006
44660
|
const postStat = _internals65.fstatFile(fd);
|
|
44007
|
-
|
|
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) {
|
|
44008
44667
|
outcome = {
|
|
44009
44668
|
status: "incomplete",
|
|
44010
|
-
reason: postStat.size > MAX_FILE_SIZE_BYTES3 ? "oversized" : "read_error"
|
|
44669
|
+
reason: postStat.size > BigInt(MAX_FILE_SIZE_BYTES3) ? "oversized" : "read_error"
|
|
44011
44670
|
};
|
|
44012
44671
|
} else {
|
|
44013
44672
|
outcome = {
|
|
@@ -44019,25 +44678,30 @@ function readBoundedFile(filePath) {
|
|
|
44019
44678
|
}
|
|
44020
44679
|
} catch {
|
|
44021
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
|
+
}
|
|
44022
44689
|
}
|
|
44023
|
-
|
|
44024
|
-
_internals65.closeFile(fd);
|
|
44025
|
-
} catch {
|
|
44690
|
+
if (closeFailed)
|
|
44026
44691
|
return { status: "incomplete", reason: "read_error" };
|
|
44027
|
-
}
|
|
44028
44692
|
return outcome;
|
|
44029
44693
|
}
|
|
44030
44694
|
function scanFileForSecrets(filePath, mode) {
|
|
44031
44695
|
const findings = [];
|
|
44032
44696
|
try {
|
|
44033
|
-
const lstat3 =
|
|
44697
|
+
const lstat3 = _internals65.lstatFile(filePath);
|
|
44034
44698
|
if (lstat3.isSymbolicLink()) {
|
|
44035
44699
|
return mode === "explicit" ? { status: "incomplete", reason: "symlink" } : { status: "skipped", reason: "symlink" };
|
|
44036
44700
|
}
|
|
44037
44701
|
if (!lstat3.isFile()) {
|
|
44038
44702
|
return { status: "incomplete", reason: "non_file" };
|
|
44039
44703
|
}
|
|
44040
|
-
const readOutcome = readBoundedFile(filePath);
|
|
44704
|
+
const readOutcome = readBoundedFile(filePath, lstat3);
|
|
44041
44705
|
if (readOutcome.status === "incomplete")
|
|
44042
44706
|
return readOutcome;
|
|
44043
44707
|
const { buffer, truncated } = readOutcome;
|
|
@@ -44085,7 +44749,7 @@ function assertNever(value) {
|
|
|
44085
44749
|
throw new Error(`Unhandled secretscan outcome: ${String(value)}`);
|
|
44086
44750
|
}
|
|
44087
44751
|
async function yieldToEventLoop() {
|
|
44088
|
-
await new Promise((
|
|
44752
|
+
await new Promise((resolve25) => setImmediate(resolve25));
|
|
44089
44753
|
}
|
|
44090
44754
|
function serializeSecretscanResult(result) {
|
|
44091
44755
|
let findings = result.findings;
|
|
@@ -44124,14 +44788,14 @@ function isPathWithinScope(realPath, scanDir) {
|
|
|
44124
44788
|
}
|
|
44125
44789
|
var DISCOVERY_YIELD_INTERVAL = 100;
|
|
44126
44790
|
function toSafeRelativePath(rootDir, targetPath) {
|
|
44127
|
-
const
|
|
44128
|
-
if (!
|
|
44791
|
+
const relative11 = path77.relative(rootDir, targetPath).replace(/\\/g, "/");
|
|
44792
|
+
if (!relative11 || relative11 === ".")
|
|
44129
44793
|
return ".";
|
|
44130
|
-
if (
|
|
44131
|
-
const
|
|
44132
|
-
return
|
|
44794
|
+
if (relative11.startsWith("..") || path77.isAbsolute(relative11)) {
|
|
44795
|
+
const basename16 = path77.basename(targetPath).replace(/\\/g, "/");
|
|
44796
|
+
return basename16 || ".";
|
|
44133
44797
|
}
|
|
44134
|
-
return
|
|
44798
|
+
return relative11;
|
|
44135
44799
|
}
|
|
44136
44800
|
function recordIncompletePath(target, rootDir, targetPath, reason) {
|
|
44137
44801
|
if (target.length >= MAX_INCOMPLETE_PATHS) {
|
|
@@ -44713,10 +45377,10 @@ var _internals65 = {
|
|
|
44713
45377
|
now: Date.now,
|
|
44714
45378
|
yieldToEventLoop,
|
|
44715
45379
|
openFile: fs31.openSync,
|
|
44716
|
-
fstatFile: fs31.fstatSync,
|
|
45380
|
+
fstatFile: (fd) => fs31.fstatSync(fd, { bigint: true }),
|
|
44717
45381
|
readFileChunk: fs31.readSync,
|
|
44718
45382
|
closeFile: fs31.closeSync,
|
|
44719
|
-
lstatFile: fs31.lstatSync,
|
|
45383
|
+
lstatFile: (path78) => fs31.lstatSync(path78, { bigint: true }),
|
|
44720
45384
|
closeDirectory: (directory) => directory.closeSync()
|
|
44721
45385
|
};
|
|
44722
45386
|
|
|
@@ -45720,7 +46384,7 @@ var DISPATCH_FRAMEWORK_MAP = {
|
|
|
45720
46384
|
};
|
|
45721
46385
|
async function detectTestFrameworkViaDispatch(cwd) {
|
|
45722
46386
|
try {
|
|
45723
|
-
const { pickBackend } = await import("./dispatch-
|
|
46387
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45724
46388
|
const backend = await pickBackend(cwd);
|
|
45725
46389
|
if (!backend?.selectTestFramework)
|
|
45726
46390
|
return "none";
|
|
@@ -45736,7 +46400,7 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
|
|
|
45736
46400
|
if (framework === "none")
|
|
45737
46401
|
return null;
|
|
45738
46402
|
try {
|
|
45739
|
-
const { pickBackend } = await import("./dispatch-
|
|
46403
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45740
46404
|
const backend = await pickBackend(baseDir);
|
|
45741
46405
|
if (backend?.buildTestCommand) {
|
|
45742
46406
|
const cmd = backend.buildTestCommand(framework, files, baseDir, {
|
|
@@ -45756,7 +46420,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
45756
46420
|
if (framework === "none")
|
|
45757
46421
|
return null;
|
|
45758
46422
|
try {
|
|
45759
|
-
const { pickBackend } = await import("./dispatch-
|
|
46423
|
+
const { pickBackend } = await import("./dispatch-nbv0hezh.js");
|
|
45760
46424
|
const backend = await pickBackend(baseDir);
|
|
45761
46425
|
if (!backend?.parseTestOutput)
|
|
45762
46426
|
return null;
|
|
@@ -45966,21 +46630,21 @@ function hasCompoundTestExtension(filename) {
|
|
|
45966
46630
|
const lower = filename.toLowerCase();
|
|
45967
46631
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
45968
46632
|
}
|
|
45969
|
-
function isLanguageSpecificTestFile(
|
|
45970
|
-
const lower =
|
|
46633
|
+
function isLanguageSpecificTestFile(basename17) {
|
|
46634
|
+
const lower = basename17.toLowerCase();
|
|
45971
46635
|
if (lower.endsWith("_test.go"))
|
|
45972
46636
|
return true;
|
|
45973
46637
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
45974
46638
|
return true;
|
|
45975
46639
|
if (lower.endsWith("_spec.rb"))
|
|
45976
46640
|
return true;
|
|
45977
|
-
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")))
|
|
45978
46642
|
return true;
|
|
45979
46643
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
45980
46644
|
return true;
|
|
45981
|
-
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")))
|
|
45982
46646
|
return true;
|
|
45983
|
-
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")))
|
|
45984
46648
|
return true;
|
|
45985
46649
|
if (lower.endsWith(".tests.ps1"))
|
|
45986
46650
|
return true;
|
|
@@ -45988,23 +46652,23 @@ function isLanguageSpecificTestFile(basename16) {
|
|
|
45988
46652
|
}
|
|
45989
46653
|
function isConventionTestFilePath(filePath) {
|
|
45990
46654
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
45991
|
-
const
|
|
45992
|
-
return hasCompoundTestExtension(
|
|
46655
|
+
const basename17 = path81.basename(filePath);
|
|
46656
|
+
return hasCompoundTestExtension(basename17) || basename17.includes(".spec.") || basename17.includes(".test.") || isLanguageSpecificTestFile(basename17) || isTestDirectoryPath(normalizedPath);
|
|
45993
46657
|
}
|
|
45994
46658
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
45995
46659
|
const testFiles = [];
|
|
45996
46660
|
for (const file of sourceFiles) {
|
|
45997
46661
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
45998
46662
|
const relativeFile = path81.relative(workingDir, absoluteFile);
|
|
45999
|
-
const
|
|
46663
|
+
const basename17 = path81.basename(absoluteFile);
|
|
46000
46664
|
const dirname30 = path81.dirname(absoluteFile);
|
|
46001
46665
|
const preferRelativeOutput = !path81.isAbsolute(file);
|
|
46002
46666
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
46003
46667
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
46004
46668
|
continue;
|
|
46005
46669
|
}
|
|
46006
|
-
const nameWithoutExt =
|
|
46007
|
-
const ext = path81.extname(
|
|
46670
|
+
const nameWithoutExt = basename17.replace(/\.[^.]+$/, "");
|
|
46671
|
+
const ext = path81.extname(basename17);
|
|
46008
46672
|
const genericTestNames = [
|
|
46009
46673
|
`${nameWithoutExt}.spec${ext}`,
|
|
46010
46674
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -46015,7 +46679,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
46015
46679
|
...languageSpecificTestNames
|
|
46016
46680
|
].map((candidateName) => path81.join(dirname30, candidateName));
|
|
46017
46681
|
const testDirectoryNames = [
|
|
46018
|
-
|
|
46682
|
+
basename17,
|
|
46019
46683
|
...genericTestNames,
|
|
46020
46684
|
...languageSpecificTestNames
|
|
46021
46685
|
];
|
|
@@ -46280,13 +46944,13 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
46280
46944
|
'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'
|
|
46281
46945
|
];
|
|
46282
46946
|
case "pest": {
|
|
46283
|
-
const args = [
|
|
46947
|
+
const args = [phpVendorBin("pest")];
|
|
46284
46948
|
if (scope !== "all" && files.length > 0)
|
|
46285
46949
|
args.push(...files);
|
|
46286
46950
|
return args;
|
|
46287
46951
|
}
|
|
46288
46952
|
case "phpunit": {
|
|
46289
|
-
const args = [
|
|
46953
|
+
const args = [phpVendorBin("phpunit")];
|
|
46290
46954
|
if (scope !== "all" && files.length > 0)
|
|
46291
46955
|
args.push(...files);
|
|
46292
46956
|
return args;
|
|
@@ -46301,7 +46965,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
46301
46965
|
return null;
|
|
46302
46966
|
}
|
|
46303
46967
|
}
|
|
46304
|
-
function
|
|
46968
|
+
function phpVendorBin(name) {
|
|
46305
46969
|
return path81.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
|
|
46306
46970
|
}
|
|
46307
46971
|
function mapFrameworkStatusToResult(status) {
|
|
@@ -46740,9 +47404,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
46740
47404
|
stderr: "pipe",
|
|
46741
47405
|
cwd
|
|
46742
47406
|
});
|
|
46743
|
-
const timeoutPromise = new Promise((
|
|
47407
|
+
const timeoutPromise = new Promise((resolve27) => setTimeout(() => {
|
|
46744
47408
|
proc.kill();
|
|
46745
|
-
|
|
47409
|
+
resolve27(-1);
|
|
46746
47410
|
}, timeout_ms));
|
|
46747
47411
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
46748
47412
|
Promise.race([proc.exited, timeoutPromise]),
|
|
@@ -46900,11 +47564,11 @@ function normalizeHistoryTestFile(testFile, workingDir) {
|
|
|
46900
47564
|
const normalized = testFile.replace(/\\/g, "/");
|
|
46901
47565
|
if (!path81.isAbsolute(testFile))
|
|
46902
47566
|
return normalized;
|
|
46903
|
-
const
|
|
46904
|
-
if (
|
|
47567
|
+
const relative12 = path81.relative(workingDir, testFile);
|
|
47568
|
+
if (relative12.startsWith("..") || path81.isAbsolute(relative12)) {
|
|
46905
47569
|
return normalized;
|
|
46906
47570
|
}
|
|
46907
|
-
return
|
|
47571
|
+
return relative12.replace(/\\/g, "/");
|
|
46908
47572
|
}
|
|
46909
47573
|
function combineAggregateResult(current, next) {
|
|
46910
47574
|
if (current === "fail" || next === "fail")
|
|
@@ -48328,13 +48992,13 @@ class CircuitBreaker {
|
|
|
48328
48992
|
if (this.config.callTimeoutMs <= 0) {
|
|
48329
48993
|
return fn();
|
|
48330
48994
|
}
|
|
48331
|
-
return new Promise((
|
|
48995
|
+
return new Promise((resolve28, reject) => {
|
|
48332
48996
|
const timeout = setTimeout(() => {
|
|
48333
48997
|
reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
|
|
48334
48998
|
}, this.config.callTimeoutMs);
|
|
48335
48999
|
fn().then((result) => {
|
|
48336
49000
|
clearTimeout(timeout);
|
|
48337
|
-
|
|
49001
|
+
resolve28(result);
|
|
48338
49002
|
}).catch((error2) => {
|
|
48339
49003
|
clearTimeout(timeout);
|
|
48340
49004
|
reject(error2);
|
|
@@ -48633,7 +49297,7 @@ class AutomationQueue {
|
|
|
48633
49297
|
|
|
48634
49298
|
// src/background/worker.ts
|
|
48635
49299
|
function sleep(ms) {
|
|
48636
|
-
return new Promise((
|
|
49300
|
+
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
48637
49301
|
}
|
|
48638
49302
|
|
|
48639
49303
|
class WorkerManager {
|
|
@@ -50583,7 +51247,7 @@ function resolveReviewFallbackModels(agentName, registry) {
|
|
|
50583
51247
|
init_logger();
|
|
50584
51248
|
|
|
50585
51249
|
// src/hooks/review-receipt-scope.ts
|
|
50586
|
-
import * as
|
|
51250
|
+
import * as child_process6 from "child_process";
|
|
50587
51251
|
import { createHash as createHash14 } from "crypto";
|
|
50588
51252
|
import * as fs42 from "fs";
|
|
50589
51253
|
import * as path89 from "path";
|
|
@@ -50595,7 +51259,7 @@ var HEAD_OUTPUT_BYTES = 256;
|
|
|
50595
51259
|
var HEAD_SHA_PATTERN = /^[0-9a-f]{40,64}$/i;
|
|
50596
51260
|
var REVIEWER_TASK_SCOPE_DESCRIPTION = "reviewer-task-files-v1";
|
|
50597
51261
|
var _internals74 = {
|
|
50598
|
-
spawn:
|
|
51262
|
+
spawn: child_process6.spawn,
|
|
50599
51263
|
realpath: fs42.promises.realpath,
|
|
50600
51264
|
lstatBigInt: (path90) => fs42.promises.lstat(path90, { bigint: true }),
|
|
50601
51265
|
open: fs42.promises.open,
|
|
@@ -50610,8 +51274,8 @@ function hasControlCharacter2(value) {
|
|
|
50610
51274
|
return false;
|
|
50611
51275
|
}
|
|
50612
51276
|
function isContained2(root, candidate) {
|
|
50613
|
-
const
|
|
50614
|
-
return
|
|
51277
|
+
const relative15 = path89.relative(root, candidate);
|
|
51278
|
+
return relative15.length > 0 && relative15 !== ".." && !relative15.startsWith(`..${path89.sep}`) && !path89.isAbsolute(relative15);
|
|
50615
51279
|
}
|
|
50616
51280
|
function canonicalPath(relativePath2) {
|
|
50617
51281
|
return relativePath2.split(path89.sep).join("/");
|
|
@@ -50667,7 +51331,7 @@ async function resolveHeadSha(directory) {
|
|
|
50667
51331
|
timeout: HEAD_TIMEOUT_MS,
|
|
50668
51332
|
windowsHide: true
|
|
50669
51333
|
});
|
|
50670
|
-
return await new Promise((
|
|
51334
|
+
return await new Promise((resolve31) => {
|
|
50671
51335
|
let settled = false;
|
|
50672
51336
|
let stdoutBytes = 0;
|
|
50673
51337
|
const stdoutChunks = [];
|
|
@@ -50677,7 +51341,7 @@ async function resolveHeadSha(directory) {
|
|
|
50677
51341
|
settled = true;
|
|
50678
51342
|
if (timeoutHandle !== undefined)
|
|
50679
51343
|
clearTimeout(timeoutHandle);
|
|
50680
|
-
|
|
51344
|
+
resolve31(value);
|
|
50681
51345
|
};
|
|
50682
51346
|
const killAndFail = () => {
|
|
50683
51347
|
try {
|
|
@@ -51397,8 +52061,8 @@ function normalizedRelativePath(file) {
|
|
|
51397
52061
|
return normalized.replace(/^\.\//, "");
|
|
51398
52062
|
}
|
|
51399
52063
|
function isWithinRoot2(root, candidate) {
|
|
51400
|
-
const
|
|
51401
|
-
return
|
|
52064
|
+
const relative17 = path91.relative(root, candidate);
|
|
52065
|
+
return relative17.length > 0 && relative17 !== ".." && !relative17.startsWith(`..${path91.sep}`) && !path91.isAbsolute(relative17);
|
|
51402
52066
|
}
|
|
51403
52067
|
function rangesOverlap(start, end, ranges) {
|
|
51404
52068
|
return ranges.some((range) => start <= range.end && end >= range.start);
|
|
@@ -51962,8 +52626,8 @@ function formatSelector(selector) {
|
|
|
51962
52626
|
}
|
|
51963
52627
|
}
|
|
51964
52628
|
function isPathInside(parent, candidate) {
|
|
51965
|
-
const
|
|
51966
|
-
return
|
|
52629
|
+
const relative18 = path92.relative(parent, candidate);
|
|
52630
|
+
return relative18.length > 0 && relative18 !== ".." && !relative18.startsWith(`..${path92.sep}`) && !path92.isAbsolute(relative18);
|
|
51967
52631
|
}
|
|
51968
52632
|
function sameFileSnapshot4(left, right) {
|
|
51969
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;
|
|
@@ -53058,14 +53722,14 @@ import * as path96 from "path";
|
|
|
53058
53722
|
// src/services/skill-optimizer/store.ts
|
|
53059
53723
|
import { createHash as createHash15, randomUUID as randomUUID10 } from "crypto";
|
|
53060
53724
|
import {
|
|
53061
|
-
closeSync as
|
|
53725
|
+
closeSync as closeSync13,
|
|
53062
53726
|
existsSync as existsSync53,
|
|
53063
53727
|
fsyncSync as fsyncSync3,
|
|
53064
53728
|
mkdirSync as mkdirSync27,
|
|
53065
|
-
openSync as
|
|
53729
|
+
openSync as openSync13,
|
|
53066
53730
|
readFileSync as readFileSync39,
|
|
53067
53731
|
renameSync as renameSync18,
|
|
53068
|
-
statSync as
|
|
53732
|
+
statSync as statSync16,
|
|
53069
53733
|
unlinkSync as unlinkSync20,
|
|
53070
53734
|
writeFileSync as writeFileSync17,
|
|
53071
53735
|
writeFileSync as writeFileSyncAsync
|
|
@@ -53131,12 +53795,12 @@ function ensureCandidateDir(directory, skillSlug, candidateId2) {
|
|
|
53131
53795
|
return dir;
|
|
53132
53796
|
}
|
|
53133
53797
|
function writeFileFsyncedThenRename(tempPath, targetPath, data) {
|
|
53134
|
-
const fd =
|
|
53798
|
+
const fd = openSync13(tempPath, "w");
|
|
53135
53799
|
try {
|
|
53136
53800
|
writeFileSync17(fd, data, "utf8");
|
|
53137
53801
|
fsyncSync3(fd);
|
|
53138
53802
|
} finally {
|
|
53139
|
-
|
|
53803
|
+
closeSync13(fd);
|
|
53140
53804
|
}
|
|
53141
53805
|
try {
|
|
53142
53806
|
renameSync18(tempPath, targetPath);
|
|
@@ -53155,7 +53819,7 @@ var _internals79 = {
|
|
|
53155
53819
|
renameSync: renameSync18,
|
|
53156
53820
|
unlinkSync: unlinkSync20,
|
|
53157
53821
|
existsSync: existsSync53,
|
|
53158
|
-
statSync:
|
|
53822
|
+
statSync: statSync16
|
|
53159
53823
|
};
|
|
53160
53824
|
async function appendEvent(directory, eventInput) {
|
|
53161
53825
|
if (!isValidSkillSlug(eventInput.skillSlug)) {
|
|
@@ -53973,17 +54637,17 @@ async function deterministicSeed(input) {
|
|
|
53973
54637
|
}
|
|
53974
54638
|
|
|
53975
54639
|
// src/services/skill-optimizer/smoke.ts
|
|
53976
|
-
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";
|
|
53977
54641
|
import * as path98 from "path";
|
|
53978
54642
|
|
|
53979
54643
|
// src/hooks/spawn-helper.ts
|
|
53980
|
-
import * as
|
|
54644
|
+
import * as child_process7 from "child_process";
|
|
53981
54645
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
53982
54646
|
var _internals82 = {
|
|
53983
|
-
spawn:
|
|
54647
|
+
spawn: child_process7.spawn
|
|
53984
54648
|
};
|
|
53985
54649
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
53986
|
-
return new Promise((
|
|
54650
|
+
return new Promise((resolve34) => {
|
|
53987
54651
|
try {
|
|
53988
54652
|
const [rawCmd, ...args] = command;
|
|
53989
54653
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -54030,24 +54694,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
54030
54694
|
try {
|
|
54031
54695
|
proc.kill();
|
|
54032
54696
|
} catch {}
|
|
54033
|
-
|
|
54697
|
+
resolve34(null);
|
|
54034
54698
|
}, timeoutMs);
|
|
54035
54699
|
proc.on("close", (code) => {
|
|
54036
54700
|
if (done)
|
|
54037
54701
|
return;
|
|
54038
54702
|
done = true;
|
|
54039
54703
|
clearTimeout(timer);
|
|
54040
|
-
|
|
54704
|
+
resolve34({ exitCode: code ?? 1, stdout, stderr });
|
|
54041
54705
|
});
|
|
54042
54706
|
proc.on("error", () => {
|
|
54043
54707
|
if (done)
|
|
54044
54708
|
return;
|
|
54045
54709
|
done = true;
|
|
54046
54710
|
clearTimeout(timer);
|
|
54047
|
-
|
|
54711
|
+
resolve34(null);
|
|
54048
54712
|
});
|
|
54049
54713
|
} catch {
|
|
54050
|
-
|
|
54714
|
+
resolve34(null);
|
|
54051
54715
|
}
|
|
54052
54716
|
});
|
|
54053
54717
|
}
|
|
@@ -54066,7 +54730,7 @@ var _internals83 = {
|
|
|
54066
54730
|
const rel = path98.relative(path98.resolve(root), path98.resolve(target));
|
|
54067
54731
|
return rel.startsWith("..") || path98.isAbsolute(rel);
|
|
54068
54732
|
},
|
|
54069
|
-
realpath: (p) =>
|
|
54733
|
+
realpath: (p) => realpathSync11(p),
|
|
54070
54734
|
evaluateSkillChange,
|
|
54071
54735
|
isRejectedSkillContent,
|
|
54072
54736
|
spawnAsync
|
|
@@ -54430,7 +55094,7 @@ async function runValidationWithTransientRetry(input, candidateContent, baseline
|
|
|
54430
55094
|
if (!input.dispatcher) {
|
|
54431
55095
|
throw new Error("no evaluation dispatcher available (cannot run validation)");
|
|
54432
55096
|
}
|
|
54433
|
-
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-
|
|
55097
|
+
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-mzb3e2s6.js");
|
|
54434
55098
|
const executor = createModelEvaluationExecutor2(input.dispatcher, input.sessionId);
|
|
54435
55099
|
const result = await _internals84.evaluateCandidateV1({
|
|
54436
55100
|
projectRoot: input.directory,
|
|
@@ -55303,11 +55967,18 @@ function makeInitialState() {
|
|
|
55303
55967
|
};
|
|
55304
55968
|
}
|
|
55305
55969
|
var sessionStates = new Map;
|
|
55970
|
+
var MAX_TRACKED_COMPACTION_SESSIONS = 500;
|
|
55306
55971
|
function getSessionState(sessionId) {
|
|
55307
55972
|
let state = sessionStates.get(sessionId);
|
|
55308
|
-
if (
|
|
55309
|
-
state
|
|
55310
|
-
|
|
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
|
+
}
|
|
55311
55982
|
}
|
|
55312
55983
|
return state;
|
|
55313
55984
|
}
|
|
@@ -55392,8 +56063,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55392
56063
|
agentCount,
|
|
55393
56064
|
isLegacy: false,
|
|
55394
56065
|
turboMode: hasActiveTurboMode(),
|
|
55395
|
-
contextBudgetPct:
|
|
55396
|
-
contextBudgetTokens:
|
|
56066
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56067
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55397
56068
|
compactionCount: metrics.compactionCount,
|
|
55398
56069
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55399
56070
|
};
|
|
@@ -55409,8 +56080,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55409
56080
|
agentCount: Object.keys(agents).length,
|
|
55410
56081
|
isLegacy: true,
|
|
55411
56082
|
turboMode: hasActiveTurboMode(),
|
|
55412
|
-
contextBudgetPct:
|
|
55413
|
-
contextBudgetTokens:
|
|
56083
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56084
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55414
56085
|
compactionCount: metrics.compactionCount,
|
|
55415
56086
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55416
56087
|
};
|
|
@@ -55429,8 +56100,8 @@ async function getStatusData(directory, agents, sessionId) {
|
|
|
55429
56100
|
agentCount,
|
|
55430
56101
|
isLegacy: true,
|
|
55431
56102
|
turboMode: hasActiveTurboMode(),
|
|
55432
|
-
contextBudgetPct:
|
|
55433
|
-
contextBudgetTokens:
|
|
56103
|
+
contextBudgetPct: getDisplayBudget()?.pct ?? null,
|
|
56104
|
+
contextBudgetTokens: getDisplayBudget()?.tokens ?? null,
|
|
55434
56105
|
compactionCount: metrics.compactionCount,
|
|
55435
56106
|
lastSnapshotAt: metrics.lastSnapshotAt
|
|
55436
56107
|
};
|
|
@@ -56254,7 +56925,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
56254
56925
|
async function handleHelpCommand(ctx) {
|
|
56255
56926
|
const targetCommand = ctx.args.join(" ");
|
|
56256
56927
|
if (!targetCommand) {
|
|
56257
|
-
const { buildHelpText } = await import("./index-
|
|
56928
|
+
const { buildHelpText } = await import("./index-5hyq2mw6.js");
|
|
56258
56929
|
return buildHelpText();
|
|
56259
56930
|
}
|
|
56260
56931
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -56263,7 +56934,7 @@ async function handleHelpCommand(ctx) {
|
|
|
56263
56934
|
return _internals14.buildDetailedHelp(resolved.key, resolved.entry);
|
|
56264
56935
|
}
|
|
56265
56936
|
const similar = _internals14.findSimilarCommands(targetCommand);
|
|
56266
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
56937
|
+
const { buildHelpText: fullHelp } = await import("./index-5hyq2mw6.js");
|
|
56267
56938
|
if (similar.length > 0) {
|
|
56268
56939
|
return `Command '/swarm ${targetCommand}' not found.
|
|
56269
56940
|
|
|
@@ -56440,7 +57111,7 @@ var COMMAND_REGISTRY = {
|
|
|
56440
57111
|
},
|
|
56441
57112
|
"guardrail explain": {
|
|
56442
57113
|
handler: async (ctx) => {
|
|
56443
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
57114
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-y2wg00dp.js");
|
|
56444
57115
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
56445
57116
|
},
|
|
56446
57117
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -56450,7 +57121,7 @@ var COMMAND_REGISTRY = {
|
|
|
56450
57121
|
},
|
|
56451
57122
|
"guardrail-explain": {
|
|
56452
57123
|
handler: async (ctx) => {
|
|
56453
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
57124
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-y2wg00dp.js");
|
|
56454
57125
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
56455
57126
|
},
|
|
56456
57127
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -56460,7 +57131,7 @@ var COMMAND_REGISTRY = {
|
|
|
56460
57131
|
},
|
|
56461
57132
|
"guardrail-log": {
|
|
56462
57133
|
handler: async (ctx) => {
|
|
56463
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
57134
|
+
const { handleGuardrailLog } = await import("./guardrail-log-320grggj.js");
|
|
56464
57135
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
56465
57136
|
},
|
|
56466
57137
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -56914,7 +57585,7 @@ Subcommands:
|
|
|
56914
57585
|
handler: (ctx) => handleApprovePlanCriticCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
56915
57586
|
description: "Record a MANUAL plan-critic approval to unblock the critic_pre_plan execution gate [reason...]",
|
|
56916
57587
|
args: "[reason...]",
|
|
56917
|
-
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.',
|
|
56918
57589
|
category: "utility",
|
|
56919
57590
|
toolPolicy: "restricted"
|
|
56920
57591
|
},
|
|
@@ -59899,14 +60570,6 @@ function getSwarmAgents(swarmId) {
|
|
|
59899
60570
|
const id = swarmId ?? "default";
|
|
59900
60571
|
return _swarmAgentsMap.get(id);
|
|
59901
60572
|
}
|
|
59902
|
-
var KNOWN_VARIANT_VALUES = new Set([
|
|
59903
|
-
"low",
|
|
59904
|
-
"medium",
|
|
59905
|
-
"high",
|
|
59906
|
-
"max",
|
|
59907
|
-
"xhigh",
|
|
59908
|
-
"thinking"
|
|
59909
|
-
]);
|
|
59910
60573
|
|
|
59911
60574
|
// src/hooks/curator-llm-factory.ts
|
|
59912
60575
|
init_schema();
|