opencode-swarm 7.19.0 → 7.19.2
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/dist/cli/index.js +249 -35
- package/dist/config/plan-schema.d.ts +8 -0
- package/dist/hooks/guardrails.d.ts +21 -0
- package/dist/hooks/system-enhancer.d.ts +19 -0
- package/dist/index.js +996 -598
- package/dist/plan/ledger.d.ts +8 -3
- package/dist/plan/manager.d.ts +52 -0
- package/dist/services/status-service.d.ts +8 -0
- package/dist/tools/save-plan.d.ts +19 -0
- package/dist/tools/test-runner.d.ts +1 -0
- package/dist/types/events.d.ts +21 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.19.
|
|
36
|
+
version: "7.19.2",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -17348,6 +17348,17 @@ function applyEventToPlan(plan, event) {
|
|
|
17348
17348
|
return plan;
|
|
17349
17349
|
case "task_added":
|
|
17350
17350
|
return plan;
|
|
17351
|
+
case "task_removed":
|
|
17352
|
+
if (event.task_id) {
|
|
17353
|
+
for (const phase of plan.phases) {
|
|
17354
|
+
const idx = phase.tasks.findIndex((t) => t.id === event.task_id);
|
|
17355
|
+
if (idx !== -1) {
|
|
17356
|
+
phase.tasks.splice(idx, 1);
|
|
17357
|
+
break;
|
|
17358
|
+
}
|
|
17359
|
+
}
|
|
17360
|
+
}
|
|
17361
|
+
return plan;
|
|
17351
17362
|
case "task_updated":
|
|
17352
17363
|
return plan;
|
|
17353
17364
|
case "plan_rebuilt":
|
|
@@ -17455,7 +17466,7 @@ async function loadLastApprovedPlan(directory, expectedPlanId) {
|
|
|
17455
17466
|
}
|
|
17456
17467
|
return null;
|
|
17457
17468
|
}
|
|
17458
|
-
var LEDGER_SCHEMA_VERSION = "1.
|
|
17469
|
+
var LEDGER_SCHEMA_VERSION = "1.1.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
|
|
17459
17470
|
var init_ledger = __esm(() => {
|
|
17460
17471
|
init_plan_schema();
|
|
17461
17472
|
LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
|
|
@@ -17745,7 +17756,13 @@ async function loadPlan(directory) {
|
|
|
17745
17756
|
const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
|
|
17746
17757
|
if (planMdContent2 !== null) {
|
|
17747
17758
|
const migrated = migrateLegacyPlan(planMdContent2);
|
|
17748
|
-
await
|
|
17759
|
+
const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, migrated, "load_plan_migration_from_md", "migrate legacy plan.md to plan.json");
|
|
17760
|
+
if (removedCount > 0) {
|
|
17761
|
+
migrated._midLoadRemovals = {
|
|
17762
|
+
count: removedCount,
|
|
17763
|
+
source: "load_plan_migration_from_md"
|
|
17764
|
+
};
|
|
17765
|
+
}
|
|
17749
17766
|
return migrated;
|
|
17750
17767
|
}
|
|
17751
17768
|
}
|
|
@@ -17774,7 +17791,13 @@ async function loadPlan(directory) {
|
|
|
17774
17791
|
try {
|
|
17775
17792
|
const rebuilt = await replayFromLedger(directory);
|
|
17776
17793
|
if (rebuilt) {
|
|
17777
|
-
await
|
|
17794
|
+
const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, rebuilt, "load_plan_rebuild_from_ledger", "rebuild plan from ledger replay");
|
|
17795
|
+
if (removedCount > 0) {
|
|
17796
|
+
rebuilt._midLoadRemovals = {
|
|
17797
|
+
count: removedCount,
|
|
17798
|
+
source: "load_plan_rebuild_from_ledger"
|
|
17799
|
+
};
|
|
17800
|
+
}
|
|
17778
17801
|
return rebuilt;
|
|
17779
17802
|
}
|
|
17780
17803
|
try {
|
|
@@ -17788,7 +17811,13 @@ async function loadPlan(directory) {
|
|
|
17788
17811
|
if (approved) {
|
|
17789
17812
|
const approvedPhase = approved.approval && typeof approved.approval === "object" && "phase" in approved.approval ? approved.approval.phase : undefined;
|
|
17790
17813
|
warn(`[loadPlan] Ledger replay returned no plan — recovered from critic-approved snapshot seq=${approved.seq} timestamp=${approved.timestamp} (approval phase=${approvedPhase ?? "unknown"}). This may roll the plan back to an earlier phase — verify before continuing.`);
|
|
17791
|
-
await
|
|
17814
|
+
const { removedCount: snapshotRemovedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, approved.plan, "load_plan_recovery_from_approved_snapshot", "restore from critic-approved snapshot");
|
|
17815
|
+
if (snapshotRemovedCount > 0) {
|
|
17816
|
+
approved.plan._midLoadRemovals = {
|
|
17817
|
+
count: snapshotRemovedCount,
|
|
17818
|
+
source: "load_plan_recovery_from_approved_snapshot"
|
|
17819
|
+
};
|
|
17820
|
+
}
|
|
17792
17821
|
try {
|
|
17793
17822
|
await takeSnapshotEvent(directory, approved.plan, {
|
|
17794
17823
|
source: "recovery_from_approved_snapshot",
|
|
@@ -17809,6 +17838,28 @@ async function loadPlan(directory) {
|
|
|
17809
17838
|
}
|
|
17810
17839
|
return null;
|
|
17811
17840
|
}
|
|
17841
|
+
async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
|
|
17842
|
+
const existing = await _internals6.loadPlanJsonOnly(directory);
|
|
17843
|
+
const newIds = new Set;
|
|
17844
|
+
for (const phase of plan.phases) {
|
|
17845
|
+
for (const task of phase.tasks)
|
|
17846
|
+
newIds.add(task.id);
|
|
17847
|
+
}
|
|
17848
|
+
const removedIds = [];
|
|
17849
|
+
if (existing) {
|
|
17850
|
+
for (const phase of existing.phases) {
|
|
17851
|
+
for (const task of phase.tasks) {
|
|
17852
|
+
if (!newIds.has(task.id))
|
|
17853
|
+
removedIds.push(task.id);
|
|
17854
|
+
}
|
|
17855
|
+
}
|
|
17856
|
+
}
|
|
17857
|
+
await savePlan(directory, plan, {
|
|
17858
|
+
...options ?? {},
|
|
17859
|
+
acknowledged_removals: { ids: removedIds, reason, source }
|
|
17860
|
+
});
|
|
17861
|
+
return { removedCount: removedIds.length };
|
|
17862
|
+
}
|
|
17812
17863
|
async function savePlan(directory, plan, options) {
|
|
17813
17864
|
if (directory === null || directory === undefined || typeof directory !== "string" || directory.trim().length === 0) {
|
|
17814
17865
|
throw new Error(`Invalid directory: directory must be a non-empty string`);
|
|
@@ -17945,6 +17996,73 @@ async function savePlan(directory, plan, options) {
|
|
|
17945
17996
|
oldTaskMap.set(task.id, { phase: task.phase, status: task.status });
|
|
17946
17997
|
}
|
|
17947
17998
|
}
|
|
17999
|
+
const newTaskIds = new Set;
|
|
18000
|
+
for (const phase of validated.phases) {
|
|
18001
|
+
for (const task of phase.tasks)
|
|
18002
|
+
newTaskIds.add(task.id);
|
|
18003
|
+
}
|
|
18004
|
+
const missingTasks = [];
|
|
18005
|
+
for (const [id, info2] of oldTaskMap.entries()) {
|
|
18006
|
+
if (!newTaskIds.has(id)) {
|
|
18007
|
+
missingTasks.push({ id, phase: info2.phase, status: info2.status });
|
|
18008
|
+
}
|
|
18009
|
+
}
|
|
18010
|
+
const ack = options?.acknowledged_removals;
|
|
18011
|
+
if (missingTasks.length > 0) {
|
|
18012
|
+
if (!ack) {
|
|
18013
|
+
throw new PlanTaskRemovalNotAcknowledgedError(missingTasks);
|
|
18014
|
+
}
|
|
18015
|
+
if (typeof ack.reason !== "string" || ack.reason.trim().length === 0) {
|
|
18016
|
+
throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.reason must be a non-empty string.");
|
|
18017
|
+
}
|
|
18018
|
+
if (typeof ack.source !== "string" || ack.source.trim().length === 0) {
|
|
18019
|
+
throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.source must be a non-empty string.");
|
|
18020
|
+
}
|
|
18021
|
+
const ackSet = new Set(ack.ids);
|
|
18022
|
+
const missingIdsSet = new Set(missingTasks.map((t) => t.id));
|
|
18023
|
+
const unacked = missingTasks.filter((t) => !ackSet.has(t.id));
|
|
18024
|
+
if (unacked.length > 0) {
|
|
18025
|
+
throw new PlanTaskRemovalNotAcknowledgedError(unacked);
|
|
18026
|
+
}
|
|
18027
|
+
for (const id of ack.ids) {
|
|
18028
|
+
if (!missingIdsSet.has(id)) {
|
|
18029
|
+
throw new Error(`PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals contains "${id}" but that task is not missing from the plan.`);
|
|
18030
|
+
}
|
|
18031
|
+
}
|
|
18032
|
+
try {
|
|
18033
|
+
for (const missing of missingTasks) {
|
|
18034
|
+
const eventInput = {
|
|
18035
|
+
plan_id: derivePlanId(validated),
|
|
18036
|
+
event_type: "task_removed",
|
|
18037
|
+
task_id: missing.id,
|
|
18038
|
+
phase_id: missing.phase,
|
|
18039
|
+
from_status: missing.status,
|
|
18040
|
+
source: ack.source,
|
|
18041
|
+
payload: { reason: ack.reason, source: ack.source }
|
|
18042
|
+
};
|
|
18043
|
+
const capturedTaskId = missing.id;
|
|
18044
|
+
await retryCasWithBackoff(directory, eventInput, {
|
|
18045
|
+
expectedHash: currentHash,
|
|
18046
|
+
planHashAfter: hashAfter,
|
|
18047
|
+
verifyValid: async () => {
|
|
18048
|
+
const onDisk = await _internals6.loadPlanJsonOnly(directory);
|
|
18049
|
+
if (!onDisk)
|
|
18050
|
+
return true;
|
|
18051
|
+
for (const p of onDisk.phases) {
|
|
18052
|
+
if (p.tasks.some((x) => x.id === capturedTaskId))
|
|
18053
|
+
return true;
|
|
18054
|
+
}
|
|
18055
|
+
return false;
|
|
18056
|
+
}
|
|
18057
|
+
});
|
|
18058
|
+
}
|
|
18059
|
+
} catch (error49) {
|
|
18060
|
+
if (error49 instanceof LedgerStaleWriterError) {
|
|
18061
|
+
throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);
|
|
18062
|
+
}
|
|
18063
|
+
throw error49;
|
|
18064
|
+
}
|
|
18065
|
+
}
|
|
17948
18066
|
try {
|
|
17949
18067
|
for (const phase of validated.phases) {
|
|
17950
18068
|
for (const task of phase.tasks) {
|
|
@@ -18411,7 +18529,7 @@ function migrateLegacyPlan(planContent, swarmId) {
|
|
|
18411
18529
|
};
|
|
18412
18530
|
return plan;
|
|
18413
18531
|
}
|
|
18414
|
-
var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals6, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
18532
|
+
var PlanConcurrentModificationError, PlanTaskRemovalNotAcknowledgedError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals6, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
|
|
18415
18533
|
var init_manager = __esm(() => {
|
|
18416
18534
|
init_plan_schema();
|
|
18417
18535
|
init_utils2();
|
|
@@ -18426,6 +18544,15 @@ var init_manager = __esm(() => {
|
|
|
18426
18544
|
this.name = "PlanConcurrentModificationError";
|
|
18427
18545
|
}
|
|
18428
18546
|
};
|
|
18547
|
+
PlanTaskRemovalNotAcknowledgedError = class PlanTaskRemovalNotAcknowledgedError extends Error {
|
|
18548
|
+
missingTasks;
|
|
18549
|
+
constructor(missingTasks) {
|
|
18550
|
+
const idList = missingTasks.map((t) => `${t.id}(${t.status})`).join(", ");
|
|
18551
|
+
super(`PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: the following tasks were present in the prior plan but missing from the new save: ${idList}. Pass acknowledged_removals.ids covering all missing task IDs with a non-empty reason to proceed.`);
|
|
18552
|
+
this.name = "PlanTaskRemovalNotAcknowledgedError";
|
|
18553
|
+
this.missingTasks = missingTasks;
|
|
18554
|
+
}
|
|
18555
|
+
};
|
|
18429
18556
|
startupLedgerCheckedWorkspaces = new Set;
|
|
18430
18557
|
recoveryMutexes = new Map;
|
|
18431
18558
|
_internals6 = {
|
|
@@ -24039,6 +24166,16 @@ var init_normalize_tool_name = __esm(() => {
|
|
|
24039
24166
|
import * as fsSync2 from "node:fs";
|
|
24040
24167
|
import * as fs8 from "node:fs/promises";
|
|
24041
24168
|
import * as path10 from "node:path";
|
|
24169
|
+
function enforceSpecDriftGate(directory, toolName) {
|
|
24170
|
+
if (!directory)
|
|
24171
|
+
return;
|
|
24172
|
+
if (!SPEC_DRIFT_BLOCKED_TOOLS.has(toolName))
|
|
24173
|
+
return;
|
|
24174
|
+
const stalePath = path10.join(directory, ".swarm", "spec-staleness.json");
|
|
24175
|
+
if (fsSync2.existsSync(stalePath)) {
|
|
24176
|
+
throw new Error(`SPEC_DRIFT_BLOCK: tool "${toolName}" is blocked because .swarm/spec-staleness.json exists. ` + "Run /swarm clarify to update the spec, or /swarm acknowledge-spec-drift to dismiss, then retry.");
|
|
24177
|
+
}
|
|
24178
|
+
}
|
|
24042
24179
|
function extractStatusCode(errorMsg) {
|
|
24043
24180
|
const match = errorMsg.match(/\b(408|429|500|502|503|504|529)\b/);
|
|
24044
24181
|
if (match) {
|
|
@@ -25043,6 +25180,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25043
25180
|
await appendShellAuditLog(input.sessionID, input.tool, output.args);
|
|
25044
25181
|
handleInterpreterGating(input.sessionID, input.tool);
|
|
25045
25182
|
checkDestructiveCommand(input.tool, output.args);
|
|
25183
|
+
enforceSpecDriftGate(effectiveDirectory, input.tool);
|
|
25046
25184
|
if (isArchitect(input.sessionID) && isWriteTool(input.tool)) {
|
|
25047
25185
|
handlePlanAndScopeProtection(input.sessionID, input.tool, output.args);
|
|
25048
25186
|
}
|
|
@@ -25891,7 +26029,7 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
|
|
|
25891
26029
|
}
|
|
25892
26030
|
return { allowed: true };
|
|
25893
26031
|
}
|
|
25894
|
-
var import_picomatch, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26032
|
+
var import_picomatch, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
25895
26033
|
var init_guardrails = __esm(() => {
|
|
25896
26034
|
init_quick_lru();
|
|
25897
26035
|
init_agents2();
|
|
@@ -25911,6 +26049,13 @@ var init_guardrails = __esm(() => {
|
|
|
25911
26049
|
init_model_limits();
|
|
25912
26050
|
init_normalize_tool_name();
|
|
25913
26051
|
import_picomatch = __toESM(require_picomatch2(), 1);
|
|
26052
|
+
SPEC_DRIFT_BLOCKED_TOOLS = new Set([
|
|
26053
|
+
"save_plan",
|
|
26054
|
+
"update_task_status",
|
|
26055
|
+
"phase_complete",
|
|
26056
|
+
"lean_turbo_run_phase",
|
|
26057
|
+
"lean_turbo_acquire_locks"
|
|
26058
|
+
]);
|
|
25914
26059
|
storedInputArgs = new Map;
|
|
25915
26060
|
TRANSIENT_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504, 529]);
|
|
25916
26061
|
TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|500|502|503|504|529|timeout|overloaded|model.?not.?found|temporarily.?unavailable|server.?error|connection.?(refused|reset|timeout)|bad.?gateway|gateway.?timeout|internal.?server.?error|service.?unavailable/i;
|
|
@@ -41986,7 +42131,7 @@ var init_event_bus = __esm(() => {
|
|
|
41986
42131
|
});
|
|
41987
42132
|
|
|
41988
42133
|
// src/hooks/knowledge-store.ts
|
|
41989
|
-
import { existsSync as
|
|
42134
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
41990
42135
|
import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
|
|
41991
42136
|
import * as os3 from "node:os";
|
|
41992
42137
|
import * as path15 from "node:path";
|
|
@@ -42014,7 +42159,7 @@ function resolveHiveRejectedPath() {
|
|
|
42014
42159
|
return path15.join(path15.dirname(hivePath), "shared-learnings-rejected.jsonl");
|
|
42015
42160
|
}
|
|
42016
42161
|
async function readKnowledge(filePath) {
|
|
42017
|
-
if (!
|
|
42162
|
+
if (!existsSync10(filePath))
|
|
42018
42163
|
return [];
|
|
42019
42164
|
const content = await readFile5(filePath, "utf-8");
|
|
42020
42165
|
const results = [];
|
|
@@ -42715,7 +42860,7 @@ __export(exports_skill_generator, {
|
|
|
42715
42860
|
activateProposal: () => activateProposal,
|
|
42716
42861
|
_internals: () => _internals12
|
|
42717
42862
|
});
|
|
42718
|
-
import { existsSync as
|
|
42863
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
42719
42864
|
import { mkdir as mkdir5, readFile as readFile6, rename as rename3, writeFile as writeFile5 } from "node:fs/promises";
|
|
42720
42865
|
import * as path17 from "node:path";
|
|
42721
42866
|
function sanitizeSlug(input) {
|
|
@@ -42739,7 +42884,7 @@ function activeRepoRelativePath(slug) {
|
|
|
42739
42884
|
async function selectCandidateEntries(directory, opts) {
|
|
42740
42885
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
42741
42886
|
const hivePath = resolveHiveKnowledgePath();
|
|
42742
|
-
const hive =
|
|
42887
|
+
const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
|
|
42743
42888
|
const all = [...swarm, ...hive];
|
|
42744
42889
|
return all.filter((e) => {
|
|
42745
42890
|
if (e.status === "archived")
|
|
@@ -42904,7 +43049,7 @@ async function generateSkills(req) {
|
|
|
42904
43049
|
const idSet = new Set(req.sourceKnowledgeIds);
|
|
42905
43050
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(req.directory));
|
|
42906
43051
|
const hivePath = resolveHiveKnowledgePath();
|
|
42907
|
-
const hive =
|
|
43052
|
+
const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
|
|
42908
43053
|
pool = [...swarm, ...hive].filter((e) => idSet.has(e.id) && e.status !== "archived");
|
|
42909
43054
|
} else {
|
|
42910
43055
|
pool = candidates;
|
|
@@ -42941,7 +43086,7 @@ async function generateSkills(req) {
|
|
|
42941
43086
|
continue;
|
|
42942
43087
|
}
|
|
42943
43088
|
let preserved = false;
|
|
42944
|
-
if (req.mode === "active" &&
|
|
43089
|
+
if (req.mode === "active" && existsSync11(targetPath) && !req.force) {
|
|
42945
43090
|
const existing = await readFile6(targetPath, "utf-8");
|
|
42946
43091
|
if (!existing.includes("generated by opencode-swarm skill-generator")) {
|
|
42947
43092
|
preserved = true;
|
|
@@ -42986,7 +43131,7 @@ async function stampSourceEntries(directory, slug, ids) {
|
|
|
42986
43131
|
if (touched)
|
|
42987
43132
|
await rewriteKnowledge(swarmPath, swarm);
|
|
42988
43133
|
const hivePath = resolveHiveKnowledgePath();
|
|
42989
|
-
if (!
|
|
43134
|
+
if (!existsSync11(hivePath))
|
|
42990
43135
|
return;
|
|
42991
43136
|
const hive = await readKnowledge(hivePath);
|
|
42992
43137
|
let touchedHive = false;
|
|
@@ -43057,7 +43202,7 @@ async function activateProposal(directory, slug, force = false) {
|
|
|
43057
43202
|
}
|
|
43058
43203
|
const from = proposalPath(directory, cleanSlug);
|
|
43059
43204
|
const to = activePath(directory, cleanSlug);
|
|
43060
|
-
if (!
|
|
43205
|
+
if (!existsSync11(from)) {
|
|
43061
43206
|
return {
|
|
43062
43207
|
activated: false,
|
|
43063
43208
|
from,
|
|
@@ -43065,7 +43210,7 @@ async function activateProposal(directory, slug, force = false) {
|
|
|
43065
43210
|
reason: `proposal not found: ${from}`
|
|
43066
43211
|
};
|
|
43067
43212
|
}
|
|
43068
|
-
if (
|
|
43213
|
+
if (existsSync11(to) && !force) {
|
|
43069
43214
|
const existing = await readFile6(to, "utf-8");
|
|
43070
43215
|
if (!existing.includes("generated by opencode-swarm skill-generator")) {
|
|
43071
43216
|
return {
|
|
@@ -43116,7 +43261,7 @@ async function listSkills(directory) {
|
|
|
43116
43261
|
const proposalsDir = path17.join(directory, ".swarm", "skills", "proposals");
|
|
43117
43262
|
const activeDir = path17.join(directory, ".opencode", "skills", "generated");
|
|
43118
43263
|
const fs12 = await import("node:fs/promises");
|
|
43119
|
-
if (
|
|
43264
|
+
if (existsSync11(proposalsDir)) {
|
|
43120
43265
|
const entries = await fs12.readdir(proposalsDir);
|
|
43121
43266
|
for (const f of entries) {
|
|
43122
43267
|
if (!f.endsWith(".md"))
|
|
@@ -43128,13 +43273,13 @@ async function listSkills(directory) {
|
|
|
43128
43273
|
});
|
|
43129
43274
|
}
|
|
43130
43275
|
}
|
|
43131
|
-
if (
|
|
43276
|
+
if (existsSync11(activeDir)) {
|
|
43132
43277
|
const entries = await fs12.readdir(activeDir, { withFileTypes: true });
|
|
43133
43278
|
for (const e of entries) {
|
|
43134
43279
|
if (!e.isDirectory())
|
|
43135
43280
|
continue;
|
|
43136
43281
|
const skillPath = path17.join(activeDir, e.name, "SKILL.md");
|
|
43137
|
-
if (
|
|
43282
|
+
if (existsSync11(skillPath)) {
|
|
43138
43283
|
result.active.push({
|
|
43139
43284
|
slug: e.name,
|
|
43140
43285
|
path: skillPath
|
|
@@ -43154,7 +43299,7 @@ async function inspectSkill(directory, slug, prefer = "auto") {
|
|
|
43154
43299
|
if (prefer === "proposal" || prefer === "auto")
|
|
43155
43300
|
candidates.push({ p: proposalPath(directory, cleanSlug), m: "draft" });
|
|
43156
43301
|
for (const c of candidates) {
|
|
43157
|
-
if (
|
|
43302
|
+
if (existsSync11(c.p)) {
|
|
43158
43303
|
const content = await readFile6(c.p, "utf-8");
|
|
43159
43304
|
return { found: true, path: c.p, content, mode: c.m };
|
|
43160
43305
|
}
|
|
@@ -44242,7 +44387,7 @@ var init_hive_promoter = __esm(() => {
|
|
|
44242
44387
|
});
|
|
44243
44388
|
|
|
44244
44389
|
// src/hooks/knowledge-reader.ts
|
|
44245
|
-
import { existsSync as
|
|
44390
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
44246
44391
|
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
44247
44392
|
import * as path20 from "node:path";
|
|
44248
44393
|
function inferCategoriesFromPhase(phaseDescription) {
|
|
@@ -44292,7 +44437,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
44292
44437
|
const shownFile = path20.join(directory, ".swarm", ".knowledge-shown.json");
|
|
44293
44438
|
try {
|
|
44294
44439
|
let shownData = {};
|
|
44295
|
-
if (
|
|
44440
|
+
if (existsSync12(shownFile)) {
|
|
44296
44441
|
const content = await readFile7(shownFile, "utf-8");
|
|
44297
44442
|
shownData = JSON.parse(content);
|
|
44298
44443
|
}
|
|
@@ -44400,7 +44545,7 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
44400
44545
|
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
44401
44546
|
const shownFile = path20.join(directory, ".swarm", ".knowledge-shown.json");
|
|
44402
44547
|
try {
|
|
44403
|
-
if (!
|
|
44548
|
+
if (!existsSync12(shownFile)) {
|
|
44404
44549
|
return;
|
|
44405
44550
|
}
|
|
44406
44551
|
const content = await readFile7(shownFile, "utf-8");
|
|
@@ -45017,7 +45162,7 @@ var init_skill_improver_llm_factory = __esm(() => {
|
|
|
45017
45162
|
});
|
|
45018
45163
|
|
|
45019
45164
|
// src/services/skill-improver-quota.ts
|
|
45020
|
-
import { existsSync as
|
|
45165
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
45021
45166
|
import { mkdir as mkdir7, readFile as readFile8, rename as rename4, writeFile as writeFile7 } from "node:fs/promises";
|
|
45022
45167
|
import * as path21 from "node:path";
|
|
45023
45168
|
async function acquireLock(dir) {
|
|
@@ -45049,7 +45194,7 @@ function todayKey(window2, now = new Date) {
|
|
|
45049
45194
|
return `${yr}-${m}-${d}`;
|
|
45050
45195
|
}
|
|
45051
45196
|
async function readState(filePath) {
|
|
45052
|
-
if (!
|
|
45197
|
+
if (!existsSync13(filePath))
|
|
45053
45198
|
return null;
|
|
45054
45199
|
try {
|
|
45055
45200
|
const raw = await readFile8(filePath, "utf-8");
|
|
@@ -45151,7 +45296,7 @@ var init_skill_improver_quota = __esm(() => {
|
|
|
45151
45296
|
});
|
|
45152
45297
|
|
|
45153
45298
|
// src/services/skill-improver.ts
|
|
45154
|
-
import { existsSync as
|
|
45299
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
45155
45300
|
import { mkdir as mkdir8, rename as rename5, writeFile as writeFile8 } from "node:fs/promises";
|
|
45156
45301
|
import * as path22 from "node:path";
|
|
45157
45302
|
function timestampSlug(d) {
|
|
@@ -45166,7 +45311,7 @@ async function atomicWrite4(p, content) {
|
|
|
45166
45311
|
async function gatherInventory(directory) {
|
|
45167
45312
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
45168
45313
|
const hivePath = resolveHiveKnowledgePath();
|
|
45169
|
-
const hive =
|
|
45314
|
+
const hive = existsSync14(hivePath) ? await readKnowledge(hivePath) : [];
|
|
45170
45315
|
const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
|
|
45171
45316
|
const skills = await listSkills(directory);
|
|
45172
45317
|
const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
|
|
@@ -47154,7 +47299,7 @@ function getPluginCachePaths() {
|
|
|
47154
47299
|
var init_cache_paths = () => {};
|
|
47155
47300
|
|
|
47156
47301
|
// src/services/version-check.ts
|
|
47157
|
-
import { existsSync as
|
|
47302
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
47158
47303
|
import { homedir as homedir5 } from "node:os";
|
|
47159
47304
|
import { join as join26 } from "node:path";
|
|
47160
47305
|
function cacheDir() {
|
|
@@ -47168,7 +47313,7 @@ function cacheFile() {
|
|
|
47168
47313
|
function readVersionCache() {
|
|
47169
47314
|
try {
|
|
47170
47315
|
const path28 = cacheFile();
|
|
47171
|
-
if (!
|
|
47316
|
+
if (!existsSync15(path28))
|
|
47172
47317
|
return null;
|
|
47173
47318
|
const raw = readFileSync7(path28, "utf-8");
|
|
47174
47319
|
const parsed = JSON.parse(raw);
|
|
@@ -47267,7 +47412,7 @@ var init_version_check = __esm(() => {
|
|
|
47267
47412
|
|
|
47268
47413
|
// src/services/diagnose-service.ts
|
|
47269
47414
|
import * as child_process4 from "node:child_process";
|
|
47270
|
-
import { existsSync as
|
|
47415
|
+
import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync7 } from "node:fs";
|
|
47271
47416
|
import path28 from "node:path";
|
|
47272
47417
|
import { fileURLToPath } from "node:url";
|
|
47273
47418
|
function validateTaskDag(plan) {
|
|
@@ -47501,7 +47646,7 @@ async function checkConfigBackups(directory) {
|
|
|
47501
47646
|
}
|
|
47502
47647
|
async function checkGitRepository(directory) {
|
|
47503
47648
|
try {
|
|
47504
|
-
if (!
|
|
47649
|
+
if (!existsSync16(directory) || !statSync7(directory).isDirectory()) {
|
|
47505
47650
|
return {
|
|
47506
47651
|
name: "Git Repository",
|
|
47507
47652
|
status: "❌",
|
|
@@ -47566,7 +47711,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
47566
47711
|
}
|
|
47567
47712
|
async function checkConfigParseability(directory) {
|
|
47568
47713
|
const configPath = path28.join(directory, ".opencode/opencode-swarm.json");
|
|
47569
|
-
if (!
|
|
47714
|
+
if (!existsSync16(configPath)) {
|
|
47570
47715
|
return {
|
|
47571
47716
|
name: "Config Parseability",
|
|
47572
47717
|
status: "✅",
|
|
@@ -47621,11 +47766,11 @@ async function checkGrammarWasmFiles() {
|
|
|
47621
47766
|
const thisDir = path28.dirname(fileURLToPath(import.meta.url));
|
|
47622
47767
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
47623
47768
|
const missing = [];
|
|
47624
|
-
if (!
|
|
47769
|
+
if (!existsSync16(path28.join(grammarDir, "tree-sitter.wasm"))) {
|
|
47625
47770
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
47626
47771
|
}
|
|
47627
47772
|
for (const file3 of grammarFiles) {
|
|
47628
|
-
if (!
|
|
47773
|
+
if (!existsSync16(path28.join(grammarDir, file3))) {
|
|
47629
47774
|
missing.push(file3);
|
|
47630
47775
|
}
|
|
47631
47776
|
}
|
|
@@ -47644,7 +47789,7 @@ async function checkGrammarWasmFiles() {
|
|
|
47644
47789
|
}
|
|
47645
47790
|
async function checkCheckpointManifest(directory) {
|
|
47646
47791
|
const manifestPath = path28.join(directory, ".swarm/checkpoints.json");
|
|
47647
|
-
if (!
|
|
47792
|
+
if (!existsSync16(manifestPath)) {
|
|
47648
47793
|
return {
|
|
47649
47794
|
name: "Checkpoint Manifest",
|
|
47650
47795
|
status: "✅",
|
|
@@ -47696,7 +47841,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
47696
47841
|
}
|
|
47697
47842
|
async function checkEventStreamIntegrity(directory) {
|
|
47698
47843
|
const eventsPath = path28.join(directory, ".swarm/events.jsonl");
|
|
47699
|
-
if (!
|
|
47844
|
+
if (!existsSync16(eventsPath)) {
|
|
47700
47845
|
return {
|
|
47701
47846
|
name: "Event Stream",
|
|
47702
47847
|
status: "✅",
|
|
@@ -47737,7 +47882,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
47737
47882
|
}
|
|
47738
47883
|
async function checkSteeringDirectives(directory) {
|
|
47739
47884
|
const eventsPath = path28.join(directory, ".swarm/events.jsonl");
|
|
47740
|
-
if (!
|
|
47885
|
+
if (!existsSync16(eventsPath)) {
|
|
47741
47886
|
return {
|
|
47742
47887
|
name: "Steering Directives",
|
|
47743
47888
|
status: "✅",
|
|
@@ -47793,7 +47938,7 @@ async function checkCurator(directory) {
|
|
|
47793
47938
|
};
|
|
47794
47939
|
}
|
|
47795
47940
|
const summaryPath = path28.join(directory, ".swarm/curator-summary.json");
|
|
47796
|
-
if (!
|
|
47941
|
+
if (!existsSync16(summaryPath)) {
|
|
47797
47942
|
return {
|
|
47798
47943
|
name: "Curator",
|
|
47799
47944
|
status: "✅",
|
|
@@ -47959,7 +48104,7 @@ async function getDiagnoseData(directory) {
|
|
|
47959
48104
|
checks5.push(await checkCurator(directory));
|
|
47960
48105
|
try {
|
|
47961
48106
|
const evidenceDir = path28.join(directory, ".swarm", "evidence");
|
|
47962
|
-
const snapshotFiles =
|
|
48107
|
+
const snapshotFiles = existsSync16(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
47963
48108
|
if (snapshotFiles.length > 0) {
|
|
47964
48109
|
const latest = snapshotFiles.sort().pop();
|
|
47965
48110
|
checks5.push({
|
|
@@ -47992,7 +48137,7 @@ async function getDiagnoseData(directory) {
|
|
|
47992
48137
|
const cacheRows = [];
|
|
47993
48138
|
for (const cachePath of cachePaths) {
|
|
47994
48139
|
try {
|
|
47995
|
-
if (!
|
|
48140
|
+
if (!existsSync16(cachePath)) {
|
|
47996
48141
|
cacheRows.push(`⬜ ${cachePath} — absent`);
|
|
47997
48142
|
continue;
|
|
47998
48143
|
}
|
|
@@ -52310,7 +52455,7 @@ var init_issue = __esm(() => {
|
|
|
52310
52455
|
|
|
52311
52456
|
// src/hooks/knowledge-migrator.ts
|
|
52312
52457
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
52313
|
-
import { existsSync as
|
|
52458
|
+
import { existsSync as existsSync21, readFileSync as readFileSync13 } from "node:fs";
|
|
52314
52459
|
import { mkdir as mkdir9, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
|
|
52315
52460
|
import * as path34 from "node:path";
|
|
52316
52461
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
@@ -52326,7 +52471,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
52326
52471
|
const sentinelPath = path34.join(directory, ".swarm", ".knowledge-migrated");
|
|
52327
52472
|
const contextPath = path34.join(directory, ".swarm", "context.md");
|
|
52328
52473
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
52329
|
-
if (
|
|
52474
|
+
if (existsSync21(sentinelPath)) {
|
|
52330
52475
|
return {
|
|
52331
52476
|
migrated: false,
|
|
52332
52477
|
entriesMigrated: 0,
|
|
@@ -52335,7 +52480,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
52335
52480
|
skippedReason: "sentinel-exists"
|
|
52336
52481
|
};
|
|
52337
52482
|
}
|
|
52338
|
-
if (!
|
|
52483
|
+
if (!existsSync21(contextPath)) {
|
|
52339
52484
|
return {
|
|
52340
52485
|
migrated: false,
|
|
52341
52486
|
entriesMigrated: 0,
|
|
@@ -52521,7 +52666,7 @@ function truncateLesson(text) {
|
|
|
52521
52666
|
}
|
|
52522
52667
|
function inferProjectName(directory) {
|
|
52523
52668
|
const packageJsonPath = path34.join(directory, "package.json");
|
|
52524
|
-
if (
|
|
52669
|
+
if (existsSync21(packageJsonPath)) {
|
|
52525
52670
|
try {
|
|
52526
52671
|
const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
|
|
52527
52672
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -57145,7 +57290,7 @@ function analyzeFailures(workingDir) {
|
|
|
57145
57290
|
} catch {}
|
|
57146
57291
|
return report;
|
|
57147
57292
|
}
|
|
57148
|
-
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
57293
|
+
var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, MAX_SAFE_SOURCE_FILES = 1, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
|
|
57149
57294
|
var init_test_runner = __esm(() => {
|
|
57150
57295
|
init_zod();
|
|
57151
57296
|
init_discovery();
|
|
@@ -57332,8 +57477,8 @@ var init_test_runner = __esm(() => {
|
|
|
57332
57477
|
success: false,
|
|
57333
57478
|
framework: "none",
|
|
57334
57479
|
scope: "all",
|
|
57335
|
-
error: 'scope "all" is
|
|
57336
|
-
message: '
|
|
57480
|
+
error: 'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',
|
|
57481
|
+
message: 'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',
|
|
57337
57482
|
outcome: "error"
|
|
57338
57483
|
};
|
|
57339
57484
|
return JSON.stringify(errorResult, null, 2);
|
|
@@ -57414,6 +57559,17 @@ var init_test_runner = __esm(() => {
|
|
|
57414
57559
|
};
|
|
57415
57560
|
return JSON.stringify(errorResult, null, 2);
|
|
57416
57561
|
}
|
|
57562
|
+
if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
|
|
57563
|
+
const errorResult = {
|
|
57564
|
+
success: false,
|
|
57565
|
+
framework,
|
|
57566
|
+
scope,
|
|
57567
|
+
error: `scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
|
|
57568
|
+
message: `Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,
|
|
57569
|
+
outcome: "scope_exceeded"
|
|
57570
|
+
};
|
|
57571
|
+
return JSON.stringify(errorResult, null, 2);
|
|
57572
|
+
}
|
|
57417
57573
|
testFiles = [
|
|
57418
57574
|
...directTestFiles,
|
|
57419
57575
|
...getTestFilesFromConvention(sourceFiles, workingDir)
|
|
@@ -57437,6 +57593,17 @@ var init_test_runner = __esm(() => {
|
|
|
57437
57593
|
};
|
|
57438
57594
|
return JSON.stringify(errorResult, null, 2);
|
|
57439
57595
|
}
|
|
57596
|
+
if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
|
|
57597
|
+
const errorResult = {
|
|
57598
|
+
success: false,
|
|
57599
|
+
framework,
|
|
57600
|
+
scope,
|
|
57601
|
+
error: `scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
|
|
57602
|
+
message: `Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,
|
|
57603
|
+
outcome: "scope_exceeded"
|
|
57604
|
+
};
|
|
57605
|
+
return JSON.stringify(errorResult, null, 2);
|
|
57606
|
+
}
|
|
57440
57607
|
const graphTestFiles = await getTestFilesFromGraph(sourceFiles, workingDir);
|
|
57441
57608
|
if (graphTestFiles.length > 0) {
|
|
57442
57609
|
testFiles = graphTestFiles;
|
|
@@ -57464,6 +57631,17 @@ var init_test_runner = __esm(() => {
|
|
|
57464
57631
|
};
|
|
57465
57632
|
return JSON.stringify(errorResult, null, 2);
|
|
57466
57633
|
}
|
|
57634
|
+
if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
|
|
57635
|
+
const errorResult = {
|
|
57636
|
+
success: false,
|
|
57637
|
+
framework,
|
|
57638
|
+
scope,
|
|
57639
|
+
error: `scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
|
|
57640
|
+
message: `Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,
|
|
57641
|
+
outcome: "scope_exceeded"
|
|
57642
|
+
};
|
|
57643
|
+
return JSON.stringify(errorResult, null, 2);
|
|
57644
|
+
}
|
|
57467
57645
|
try {
|
|
57468
57646
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
57469
57647
|
if (impactResult.impactedTests.length > 0) {
|
|
@@ -59956,6 +60134,25 @@ var init_context_budget_service = __esm(() => {
|
|
|
59956
60134
|
});
|
|
59957
60135
|
|
|
59958
60136
|
// src/services/status-service.ts
|
|
60137
|
+
import * as fsSync3 from "node:fs";
|
|
60138
|
+
import * as path54 from "node:path";
|
|
60139
|
+
function readSpecStalenessSnapshot(directory) {
|
|
60140
|
+
try {
|
|
60141
|
+
const p = path54.join(directory, ".swarm", "spec-staleness.json");
|
|
60142
|
+
if (!fsSync3.existsSync(p))
|
|
60143
|
+
return { stale: false };
|
|
60144
|
+
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
60145
|
+
const parsed = JSON.parse(raw);
|
|
60146
|
+
return {
|
|
60147
|
+
stale: true,
|
|
60148
|
+
reason: typeof parsed?.reason === "string" ? parsed.reason : undefined,
|
|
60149
|
+
storedHash: typeof parsed?.specHash_plan === "string" ? parsed.specHash_plan : undefined,
|
|
60150
|
+
currentHash: typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null ? parsed.specHash_current : undefined
|
|
60151
|
+
};
|
|
60152
|
+
} catch {
|
|
60153
|
+
return { stale: false };
|
|
60154
|
+
}
|
|
60155
|
+
}
|
|
59959
60156
|
async function getStatusData(directory, agents) {
|
|
59960
60157
|
const plan = await loadPlan(directory);
|
|
59961
60158
|
let status;
|
|
@@ -60021,6 +60218,16 @@ async function getStatusData(directory, agents) {
|
|
|
60021
60218
|
};
|
|
60022
60219
|
}
|
|
60023
60220
|
}
|
|
60221
|
+
const drift = readSpecStalenessSnapshot(directory);
|
|
60222
|
+
if (drift.stale) {
|
|
60223
|
+
status.specStale = true;
|
|
60224
|
+
status.specStaleReason = drift.reason;
|
|
60225
|
+
status.specStaleStoredHash = drift.storedHash;
|
|
60226
|
+
status.specStaleCurrentHash = drift.currentHash;
|
|
60227
|
+
} else if (plan && plan._specStale) {
|
|
60228
|
+
status.specStale = true;
|
|
60229
|
+
status.specStaleReason = plan._specStaleReason;
|
|
60230
|
+
}
|
|
60024
60231
|
return enrichWithLeanTurbo(status, directory);
|
|
60025
60232
|
}
|
|
60026
60233
|
function enrichWithLeanTurbo(status, directory) {
|
|
@@ -60087,6 +60294,12 @@ function formatStatusMarkdown(status) {
|
|
|
60087
60294
|
`**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,
|
|
60088
60295
|
`**Agents**: ${status.agentCount} registered`
|
|
60089
60296
|
];
|
|
60297
|
+
if (status.specStale) {
|
|
60298
|
+
const reason = status.specStaleReason ?? "spec.md changed since plan saved";
|
|
60299
|
+
const stored = status.specStaleStoredHash ?? "unknown";
|
|
60300
|
+
const current = status.specStaleCurrentHash ?? "(spec.md missing)";
|
|
60301
|
+
lines.push("", `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`, "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.");
|
|
60302
|
+
}
|
|
60090
60303
|
if (status.turboStrategy && status.turboStrategy !== "off") {
|
|
60091
60304
|
lines.push("");
|
|
60092
60305
|
if (status.turboStrategy === "lean") {
|
|
@@ -60136,6 +60349,18 @@ function formatStatusMarkdown(status) {
|
|
|
60136
60349
|
async function handleStatusCommand(directory, agents) {
|
|
60137
60350
|
const statusData = await getStatusData(directory, agents);
|
|
60138
60351
|
if (!statusData.hasPlan) {
|
|
60352
|
+
if (statusData.specStale) {
|
|
60353
|
+
const reason = statusData.specStaleReason ?? "spec.md changed since plan saved";
|
|
60354
|
+
const stored = statusData.specStaleStoredHash ?? "unknown";
|
|
60355
|
+
const current = statusData.specStaleCurrentHash ?? "(spec.md missing)";
|
|
60356
|
+
return [
|
|
60357
|
+
"No active swarm plan found.",
|
|
60358
|
+
"",
|
|
60359
|
+
`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,
|
|
60360
|
+
"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."
|
|
60361
|
+
].join(`
|
|
60362
|
+
`);
|
|
60363
|
+
}
|
|
60139
60364
|
return "No active swarm plan found.";
|
|
60140
60365
|
}
|
|
60141
60366
|
return formatStatusMarkdown(statusData);
|
|
@@ -60439,7 +60664,7 @@ var init_write_retro2 = __esm(() => {
|
|
|
60439
60664
|
|
|
60440
60665
|
// src/commands/command-dispatch.ts
|
|
60441
60666
|
import fs36 from "node:fs";
|
|
60442
|
-
import
|
|
60667
|
+
import path55 from "node:path";
|
|
60443
60668
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
60444
60669
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
60445
60670
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -60475,9 +60700,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
60475
60700
|
`);
|
|
60476
60701
|
}
|
|
60477
60702
|
function maybeMarkFirstRun(directory) {
|
|
60478
|
-
const sentinelPath =
|
|
60703
|
+
const sentinelPath = path55.join(directory, ".swarm", ".first-run-complete");
|
|
60479
60704
|
try {
|
|
60480
|
-
const swarmDir =
|
|
60705
|
+
const swarmDir = path55.join(directory, ".swarm");
|
|
60481
60706
|
fs36.mkdirSync(swarmDir, { recursive: true });
|
|
60482
60707
|
fs36.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
60483
60708
|
`, { flag: "wx" });
|
|
@@ -61145,24 +61370,24 @@ function validateAliases() {
|
|
|
61145
61370
|
}
|
|
61146
61371
|
aliasTargets.get(target).push(name2);
|
|
61147
61372
|
const visited = new Set;
|
|
61148
|
-
const
|
|
61373
|
+
const path56 = [];
|
|
61149
61374
|
let current = target;
|
|
61150
61375
|
while (current) {
|
|
61151
61376
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
61152
61377
|
if (!currentEntry)
|
|
61153
61378
|
break;
|
|
61154
61379
|
if (visited.has(current)) {
|
|
61155
|
-
const cycleStart =
|
|
61380
|
+
const cycleStart = path56.indexOf(current);
|
|
61156
61381
|
const fullChain = [
|
|
61157
61382
|
name2,
|
|
61158
|
-
...
|
|
61383
|
+
...path56.slice(0, cycleStart > 0 ? cycleStart : path56.length),
|
|
61159
61384
|
current
|
|
61160
61385
|
].join(" → ");
|
|
61161
61386
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
61162
61387
|
break;
|
|
61163
61388
|
}
|
|
61164
61389
|
visited.add(current);
|
|
61165
|
-
|
|
61390
|
+
path56.push(current);
|
|
61166
61391
|
current = currentEntry.aliasOf || "";
|
|
61167
61392
|
}
|
|
61168
61393
|
}
|
|
@@ -63375,6 +63600,18 @@ If resuming a project with an existing approved plan, CRITIC-GATE is already sat
|
|
|
63375
63600
|
- Run /swarm clarify to update the spec and align it with the plan, OR
|
|
63376
63601
|
- Run /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings
|
|
63377
63602
|
- Do NOT proceed with implementation until spec staleness is resolved.
|
|
63603
|
+
- When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task
|
|
63604
|
+
present in the prior plan but absent from the new args.phases be enumerated
|
|
63605
|
+
in removed_task_ids with a removal_reason. save_plan will reject the call
|
|
63606
|
+
otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished
|
|
63607
|
+
(status: pending, in_progress, blocked) MUST NOT be removed without explicit
|
|
63608
|
+
user confirmation — surface the list to the user and ask before populating
|
|
63609
|
+
removed_task_ids.
|
|
63610
|
+
- While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the
|
|
63611
|
+
following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,
|
|
63612
|
+
phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call
|
|
63613
|
+
returns SPEC_DRIFT_BLOCK, do NOT retry; instead present the drift to the
|
|
63614
|
+
user and run /swarm clarify or /swarm acknowledge-spec-drift first.
|
|
63378
63615
|
|
|
63379
63616
|
### MODE: EXECUTE
|
|
63380
63617
|
For each task (respecting dependencies):
|
|
@@ -65785,7 +66022,7 @@ COVERAGE REPORTING:
|
|
|
65785
66022
|
|
|
65786
66023
|
// src/agents/index.ts
|
|
65787
66024
|
import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
|
|
65788
|
-
import * as
|
|
66025
|
+
import * as path56 from "node:path";
|
|
65789
66026
|
function stripSwarmPrefix(agentName, swarmPrefix) {
|
|
65790
66027
|
if (!swarmPrefix || !agentName)
|
|
65791
66028
|
return agentName;
|
|
@@ -66181,14 +66418,14 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
|
|
|
66181
66418
|
}));
|
|
66182
66419
|
if (directory) {
|
|
66183
66420
|
const sid = sessionId ?? `init-${Date.now()}`;
|
|
66184
|
-
const evidenceDir =
|
|
66421
|
+
const evidenceDir = path56.join(directory, ".swarm", "evidence");
|
|
66185
66422
|
const filename = `agent-tools-${sid}.json`;
|
|
66186
66423
|
const snapshotData = JSON.stringify({
|
|
66187
66424
|
sessionId: sid,
|
|
66188
66425
|
generatedAt: new Date().toISOString(),
|
|
66189
66426
|
agents: agentToolSnapshot
|
|
66190
66427
|
}, null, 2);
|
|
66191
|
-
mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(
|
|
66428
|
+
mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path56.join(evidenceDir, filename), snapshotData)).catch(() => {});
|
|
66192
66429
|
}
|
|
66193
66430
|
return result;
|
|
66194
66431
|
}
|
|
@@ -66225,14 +66462,14 @@ __export(exports_evidence_summary_integration, {
|
|
|
66225
66462
|
createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
|
|
66226
66463
|
EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
|
|
66227
66464
|
});
|
|
66228
|
-
import { existsSync as
|
|
66229
|
-
import * as
|
|
66465
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
|
|
66466
|
+
import * as path57 from "node:path";
|
|
66230
66467
|
function persistSummary(projectDir, artifact, filename) {
|
|
66231
|
-
const swarmPath =
|
|
66232
|
-
if (!
|
|
66468
|
+
const swarmPath = path57.join(projectDir, ".swarm");
|
|
66469
|
+
if (!existsSync32(swarmPath)) {
|
|
66233
66470
|
mkdirSync16(swarmPath, { recursive: true });
|
|
66234
66471
|
}
|
|
66235
|
-
const artifactPath =
|
|
66472
|
+
const artifactPath = path57.join(swarmPath, filename);
|
|
66236
66473
|
const content = JSON.stringify(artifact, null, 2);
|
|
66237
66474
|
writeFileSync8(artifactPath, content, "utf-8");
|
|
66238
66475
|
log("[EvidenceSummaryIntegration] Summary persisted", {
|
|
@@ -66351,7 +66588,7 @@ __export(exports_status_artifact, {
|
|
|
66351
66588
|
AutomationStatusArtifact: () => AutomationStatusArtifact
|
|
66352
66589
|
});
|
|
66353
66590
|
import * as fs38 from "node:fs";
|
|
66354
|
-
import * as
|
|
66591
|
+
import * as path59 from "node:path";
|
|
66355
66592
|
function createEmptySnapshot(mode, capabilities) {
|
|
66356
66593
|
return {
|
|
66357
66594
|
timestamp: Date.now(),
|
|
@@ -66410,7 +66647,7 @@ class AutomationStatusArtifact {
|
|
|
66410
66647
|
});
|
|
66411
66648
|
}
|
|
66412
66649
|
getFilePath() {
|
|
66413
|
-
return
|
|
66650
|
+
return path59.join(this.swarmDir, this.filename);
|
|
66414
66651
|
}
|
|
66415
66652
|
load() {
|
|
66416
66653
|
const filePath = this.getFilePath();
|
|
@@ -66823,12 +67060,12 @@ __export(exports_review_receipt, {
|
|
|
66823
67060
|
});
|
|
66824
67061
|
import * as crypto5 from "node:crypto";
|
|
66825
67062
|
import * as fs44 from "node:fs";
|
|
66826
|
-
import * as
|
|
67063
|
+
import * as path62 from "node:path";
|
|
66827
67064
|
function resolveReceiptsDir(directory) {
|
|
66828
|
-
return
|
|
67065
|
+
return path62.join(directory, ".swarm", "review-receipts");
|
|
66829
67066
|
}
|
|
66830
67067
|
function resolveReceiptIndexPath(directory) {
|
|
66831
|
-
return
|
|
67068
|
+
return path62.join(resolveReceiptsDir(directory), "index.json");
|
|
66832
67069
|
}
|
|
66833
67070
|
function buildReceiptFilename(id, date9) {
|
|
66834
67071
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -66867,7 +67104,7 @@ async function readReceiptIndex(directory) {
|
|
|
66867
67104
|
}
|
|
66868
67105
|
async function writeReceiptIndex(directory, index) {
|
|
66869
67106
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
66870
|
-
const dir =
|
|
67107
|
+
const dir = path62.dirname(indexPath);
|
|
66871
67108
|
await fs44.promises.mkdir(dir, { recursive: true });
|
|
66872
67109
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
66873
67110
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
@@ -66878,7 +67115,7 @@ async function persistReviewReceipt(directory, receipt) {
|
|
|
66878
67115
|
await fs44.promises.mkdir(receiptsDir, { recursive: true });
|
|
66879
67116
|
const now = new Date(receipt.reviewed_at);
|
|
66880
67117
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
66881
|
-
const receiptPath =
|
|
67118
|
+
const receiptPath = path62.join(receiptsDir, filename);
|
|
66882
67119
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
66883
67120
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
66884
67121
|
fs44.renameSync(tmpPath, receiptPath);
|
|
@@ -66900,7 +67137,7 @@ async function readReceiptById(directory, receiptId) {
|
|
|
66900
67137
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
66901
67138
|
if (!entry)
|
|
66902
67139
|
return null;
|
|
66903
|
-
const receiptPath =
|
|
67140
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66904
67141
|
try {
|
|
66905
67142
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66906
67143
|
return JSON.parse(content);
|
|
@@ -66913,7 +67150,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
66913
67150
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
66914
67151
|
const receipts = [];
|
|
66915
67152
|
for (const entry of matching) {
|
|
66916
|
-
const receiptPath =
|
|
67153
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66917
67154
|
try {
|
|
66918
67155
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66919
67156
|
receipts.push(JSON.parse(content));
|
|
@@ -66926,7 +67163,7 @@ async function readAllReceipts(directory) {
|
|
|
66926
67163
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
66927
67164
|
const receipts = [];
|
|
66928
67165
|
for (const entry of sorted) {
|
|
66929
|
-
const receiptPath =
|
|
67166
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66930
67167
|
try {
|
|
66931
67168
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66932
67169
|
receipts.push(JSON.parse(content));
|
|
@@ -68514,11 +68751,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
68514
68751
|
throw toThrow;
|
|
68515
68752
|
}, "quit_");
|
|
68516
68753
|
var scriptDirectory = "";
|
|
68517
|
-
function locateFile(
|
|
68754
|
+
function locateFile(path77) {
|
|
68518
68755
|
if (Module["locateFile"]) {
|
|
68519
|
-
return Module["locateFile"](
|
|
68756
|
+
return Module["locateFile"](path77, scriptDirectory);
|
|
68520
68757
|
}
|
|
68521
|
-
return scriptDirectory +
|
|
68758
|
+
return scriptDirectory + path77;
|
|
68522
68759
|
}
|
|
68523
68760
|
__name(locateFile, "locateFile");
|
|
68524
68761
|
var readAsync, readBinary;
|
|
@@ -70268,12 +70505,12 @@ __export(exports_runtime, {
|
|
|
70268
70505
|
clearParserCache: () => clearParserCache,
|
|
70269
70506
|
_internals: () => _internals35
|
|
70270
70507
|
});
|
|
70271
|
-
import * as
|
|
70508
|
+
import * as path77 from "node:path";
|
|
70272
70509
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
70273
70510
|
async function initTreeSitter() {
|
|
70274
70511
|
if (!treeSitterInitPromise) {
|
|
70275
70512
|
treeSitterInitPromise = (async () => {
|
|
70276
|
-
const thisDir =
|
|
70513
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
70277
70514
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
70278
70515
|
if (isSource) {
|
|
70279
70516
|
await _internals35.parserInit();
|
|
@@ -70281,7 +70518,7 @@ async function initTreeSitter() {
|
|
|
70281
70518
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
70282
70519
|
await _internals35.parserInit({
|
|
70283
70520
|
locateFile(scriptName) {
|
|
70284
|
-
return
|
|
70521
|
+
return path77.join(grammarsDir, scriptName);
|
|
70285
70522
|
}
|
|
70286
70523
|
});
|
|
70287
70524
|
}
|
|
@@ -70307,11 +70544,11 @@ function getWasmFileName(languageId) {
|
|
|
70307
70544
|
return `tree-sitter-${sanitized}.wasm`;
|
|
70308
70545
|
}
|
|
70309
70546
|
function getGrammarsDirAbsolute() {
|
|
70310
|
-
const thisDir =
|
|
70547
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
70311
70548
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
70312
70549
|
const isSource = normalized.endsWith("/src/lang");
|
|
70313
70550
|
const isCliBundle = normalized.endsWith("/cli");
|
|
70314
|
-
return isSource ?
|
|
70551
|
+
return isSource ? path77.join(thisDir, "grammars") : isCliBundle ? path77.join(thisDir, "..", "lang", "grammars") : path77.join(thisDir, "lang", "grammars");
|
|
70315
70552
|
}
|
|
70316
70553
|
async function loadGrammar(languageId) {
|
|
70317
70554
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -70327,9 +70564,9 @@ async function loadGrammar(languageId) {
|
|
|
70327
70564
|
await initTreeSitter();
|
|
70328
70565
|
const parser = new Parser;
|
|
70329
70566
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
70330
|
-
const wasmPath =
|
|
70331
|
-
const { existsSync:
|
|
70332
|
-
if (!
|
|
70567
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
70568
|
+
const { existsSync: existsSync42 } = await import("node:fs");
|
|
70569
|
+
if (!existsSync42(wasmPath)) {
|
|
70333
70570
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
70334
70571
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
70335
70572
|
}
|
|
@@ -70362,7 +70599,7 @@ async function isGrammarAvailable(languageId) {
|
|
|
70362
70599
|
}
|
|
70363
70600
|
try {
|
|
70364
70601
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
70365
|
-
const wasmPath =
|
|
70602
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
70366
70603
|
const { statSync: statSync20 } = await import("node:fs");
|
|
70367
70604
|
statSync20(wasmPath);
|
|
70368
70605
|
return true;
|
|
@@ -70431,13 +70668,13 @@ import {
|
|
|
70431
70668
|
stat as stat6,
|
|
70432
70669
|
writeFile as writeFile12
|
|
70433
70670
|
} from "node:fs/promises";
|
|
70434
|
-
import * as
|
|
70671
|
+
import * as path79 from "node:path";
|
|
70435
70672
|
function normalizeSeparators(filePath) {
|
|
70436
70673
|
return filePath.replace(/\\/g, "/");
|
|
70437
70674
|
}
|
|
70438
70675
|
function matchesDocPattern(filePath, patterns) {
|
|
70439
70676
|
const normalizedPath = normalizeSeparators(filePath);
|
|
70440
|
-
const basename10 =
|
|
70677
|
+
const basename10 = path79.basename(filePath);
|
|
70441
70678
|
for (const pattern of patterns) {
|
|
70442
70679
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
70443
70680
|
if (basename10 === pattern) {
|
|
@@ -70493,7 +70730,7 @@ function stripMarkdown(text) {
|
|
|
70493
70730
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
70494
70731
|
}
|
|
70495
70732
|
async function scanDocIndex(directory) {
|
|
70496
|
-
const manifestPath =
|
|
70733
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70497
70734
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
70498
70735
|
const extraPatterns = [
|
|
70499
70736
|
"ARCHITECTURE.md",
|
|
@@ -70510,7 +70747,7 @@ async function scanDocIndex(directory) {
|
|
|
70510
70747
|
let cacheValid = true;
|
|
70511
70748
|
for (const file3 of existingManifest.files) {
|
|
70512
70749
|
try {
|
|
70513
|
-
const fullPath =
|
|
70750
|
+
const fullPath = path79.join(directory, file3.path);
|
|
70514
70751
|
const stat7 = fs53.statSync(fullPath);
|
|
70515
70752
|
if (stat7.mtimeMs > file3.mtime) {
|
|
70516
70753
|
cacheValid = false;
|
|
@@ -70545,10 +70782,10 @@ async function scanDocIndex(directory) {
|
|
|
70545
70782
|
let isFile = entry.isFile();
|
|
70546
70783
|
if (entry.isSymbolicLink()) {
|
|
70547
70784
|
try {
|
|
70548
|
-
const symlinkPath =
|
|
70785
|
+
const symlinkPath = path79.join(dir, entry.name);
|
|
70549
70786
|
const resolved = await realpath2(symlinkPath);
|
|
70550
|
-
const rel =
|
|
70551
|
-
if (rel.startsWith("..") ||
|
|
70787
|
+
const rel = path79.relative(resolvedDirectory, resolved);
|
|
70788
|
+
if (rel.startsWith("..") || path79.isAbsolute(rel))
|
|
70552
70789
|
continue;
|
|
70553
70790
|
const targetStat = await stat6(symlinkPath);
|
|
70554
70791
|
isFile = targetStat.isFile();
|
|
@@ -70558,14 +70795,14 @@ async function scanDocIndex(directory) {
|
|
|
70558
70795
|
}
|
|
70559
70796
|
if (isDir) {
|
|
70560
70797
|
if (!SKIP_DIRECTORIES3.has(entry.name)) {
|
|
70561
|
-
await walkDir(
|
|
70798
|
+
await walkDir(path79.join(dir, entry.name));
|
|
70562
70799
|
}
|
|
70563
70800
|
continue;
|
|
70564
70801
|
}
|
|
70565
70802
|
if (!isFile)
|
|
70566
70803
|
continue;
|
|
70567
|
-
const fullPath =
|
|
70568
|
-
const relPath = normalizeSeparators(
|
|
70804
|
+
const fullPath = path79.join(dir, entry.name);
|
|
70805
|
+
const relPath = normalizeSeparators(path79.relative(directory, fullPath));
|
|
70569
70806
|
let skipThisFile = false;
|
|
70570
70807
|
for (const pattern of SKIP_PATTERNS) {
|
|
70571
70808
|
if (pattern.test(relPath)) {
|
|
@@ -70589,7 +70826,7 @@ async function scanDocIndex(directory) {
|
|
|
70589
70826
|
} catch {
|
|
70590
70827
|
continue;
|
|
70591
70828
|
}
|
|
70592
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
70829
|
+
const { title, summary } = extractTitleAndSummary(content, path79.basename(relPath));
|
|
70593
70830
|
discoveredFiles.push({
|
|
70594
70831
|
path: relPath,
|
|
70595
70832
|
title,
|
|
@@ -70626,7 +70863,7 @@ async function scanDocIndex(directory) {
|
|
|
70626
70863
|
files: discoveredFiles
|
|
70627
70864
|
};
|
|
70628
70865
|
try {
|
|
70629
|
-
await mkdir13(
|
|
70866
|
+
await mkdir13(path79.dirname(manifestPath), { recursive: true });
|
|
70630
70867
|
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
70631
70868
|
} catch {}
|
|
70632
70869
|
return { manifest, cached: false };
|
|
@@ -70665,7 +70902,7 @@ function extractConstraintsFromContent(content) {
|
|
|
70665
70902
|
return constraints;
|
|
70666
70903
|
}
|
|
70667
70904
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
70668
|
-
const manifestPath =
|
|
70905
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70669
70906
|
let manifest;
|
|
70670
70907
|
try {
|
|
70671
70908
|
const content = await readFile12(manifestPath, "utf-8");
|
|
@@ -70691,7 +70928,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
70691
70928
|
}
|
|
70692
70929
|
let fullContent;
|
|
70693
70930
|
try {
|
|
70694
|
-
fullContent = await readFile12(
|
|
70931
|
+
fullContent = await readFile12(path79.join(directory, docFile.path), "utf-8");
|
|
70695
70932
|
} catch {
|
|
70696
70933
|
skippedCount++;
|
|
70697
70934
|
continue;
|
|
@@ -70714,7 +70951,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
70714
70951
|
tier: "swarm",
|
|
70715
70952
|
lesson: constraint,
|
|
70716
70953
|
category: "architecture",
|
|
70717
|
-
tags: ["doc-scan",
|
|
70954
|
+
tags: ["doc-scan", path79.basename(docFile.path)],
|
|
70718
70955
|
scope: "global",
|
|
70719
70956
|
confidence: 0.5,
|
|
70720
70957
|
status: "candidate",
|
|
@@ -70793,7 +71030,7 @@ var init_doc_scan = __esm(() => {
|
|
|
70793
71030
|
}
|
|
70794
71031
|
} catch {}
|
|
70795
71032
|
if (force) {
|
|
70796
|
-
const manifestPath =
|
|
71033
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70797
71034
|
try {
|
|
70798
71035
|
fs53.unlinkSync(manifestPath);
|
|
70799
71036
|
} catch {}
|
|
@@ -70989,9 +71226,9 @@ __export(exports_curator_drift, {
|
|
|
70989
71226
|
_internals: () => _internals38
|
|
70990
71227
|
});
|
|
70991
71228
|
import * as fs60 from "node:fs";
|
|
70992
|
-
import * as
|
|
71229
|
+
import * as path85 from "node:path";
|
|
70993
71230
|
async function readPriorDriftReports(directory) {
|
|
70994
|
-
const swarmDir =
|
|
71231
|
+
const swarmDir = path85.join(directory, ".swarm");
|
|
70995
71232
|
const entries = await fs60.promises.readdir(swarmDir).catch(() => null);
|
|
70996
71233
|
if (entries === null)
|
|
70997
71234
|
return [];
|
|
@@ -71018,7 +71255,7 @@ async function readPriorDriftReports(directory) {
|
|
|
71018
71255
|
async function writeDriftReport(directory, report) {
|
|
71019
71256
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
71020
71257
|
const filePath = validateSwarmPath(directory, filename);
|
|
71021
|
-
const swarmDir =
|
|
71258
|
+
const swarmDir = path85.dirname(filePath);
|
|
71022
71259
|
await fs60.promises.mkdir(swarmDir, { recursive: true });
|
|
71023
71260
|
try {
|
|
71024
71261
|
await fs60.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -71164,7 +71401,7 @@ __export(exports_project_context, {
|
|
|
71164
71401
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
71165
71402
|
});
|
|
71166
71403
|
import * as fs110 from "node:fs";
|
|
71167
|
-
import * as
|
|
71404
|
+
import * as path139 from "node:path";
|
|
71168
71405
|
function detectFileExists2(directory, pattern) {
|
|
71169
71406
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
71170
71407
|
try {
|
|
@@ -71176,7 +71413,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71176
71413
|
}
|
|
71177
71414
|
}
|
|
71178
71415
|
try {
|
|
71179
|
-
fs110.accessSync(
|
|
71416
|
+
fs110.accessSync(path139.join(directory, pattern));
|
|
71180
71417
|
return true;
|
|
71181
71418
|
} catch {
|
|
71182
71419
|
return false;
|
|
@@ -71185,7 +71422,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71185
71422
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
71186
71423
|
let pkgRaw;
|
|
71187
71424
|
try {
|
|
71188
|
-
pkgRaw = fs110.readFileSync(
|
|
71425
|
+
pkgRaw = fs110.readFileSync(path139.join(directory, "package.json"), "utf-8");
|
|
71189
71426
|
} catch {
|
|
71190
71427
|
return null;
|
|
71191
71428
|
}
|
|
@@ -71294,7 +71531,7 @@ var init_project_context = __esm(() => {
|
|
|
71294
71531
|
init_package();
|
|
71295
71532
|
init_agents2();
|
|
71296
71533
|
init_critic();
|
|
71297
|
-
import * as
|
|
71534
|
+
import * as path140 from "node:path";
|
|
71298
71535
|
|
|
71299
71536
|
// src/background/index.ts
|
|
71300
71537
|
init_event_bus();
|
|
@@ -71305,7 +71542,7 @@ init_manager3();
|
|
|
71305
71542
|
init_manager();
|
|
71306
71543
|
init_utils();
|
|
71307
71544
|
import * as fs37 from "node:fs";
|
|
71308
|
-
import * as
|
|
71545
|
+
import * as path58 from "node:path";
|
|
71309
71546
|
|
|
71310
71547
|
class PlanSyncWorker {
|
|
71311
71548
|
directory;
|
|
@@ -71329,10 +71566,10 @@ class PlanSyncWorker {
|
|
|
71329
71566
|
this.onSyncComplete = options.onSyncComplete;
|
|
71330
71567
|
}
|
|
71331
71568
|
getSwarmDir() {
|
|
71332
|
-
return
|
|
71569
|
+
return path58.resolve(this.directory, ".swarm");
|
|
71333
71570
|
}
|
|
71334
71571
|
getPlanJsonPath() {
|
|
71335
|
-
return
|
|
71572
|
+
return path58.join(this.getSwarmDir(), "plan.json");
|
|
71336
71573
|
}
|
|
71337
71574
|
start() {
|
|
71338
71575
|
if (this.disposed) {
|
|
@@ -71551,8 +71788,8 @@ class PlanSyncWorker {
|
|
|
71551
71788
|
checkForUnauthorizedWrite() {
|
|
71552
71789
|
try {
|
|
71553
71790
|
const swarmDir = this.getSwarmDir();
|
|
71554
|
-
const planJsonPath =
|
|
71555
|
-
const markerPath =
|
|
71791
|
+
const planJsonPath = path58.join(swarmDir, "plan.json");
|
|
71792
|
+
const markerPath = path58.join(swarmDir, ".plan-write-marker");
|
|
71556
71793
|
const planStats = fs37.statSync(planJsonPath);
|
|
71557
71794
|
const planMtimeMs = Math.floor(planStats.mtimeMs);
|
|
71558
71795
|
const markerContent = fs37.readFileSync(markerPath, "utf8");
|
|
@@ -71593,13 +71830,13 @@ init_constants();
|
|
|
71593
71830
|
// src/config/project-init.ts
|
|
71594
71831
|
init_constants();
|
|
71595
71832
|
import * as fs39 from "node:fs";
|
|
71596
|
-
import * as
|
|
71833
|
+
import * as path60 from "node:path";
|
|
71597
71834
|
var STARTER_CONTENT = `{}
|
|
71598
71835
|
`;
|
|
71599
71836
|
function writeProjectConfigIfNew(directory, quiet = false) {
|
|
71600
71837
|
try {
|
|
71601
|
-
const opencodeDir =
|
|
71602
|
-
const dest =
|
|
71838
|
+
const opencodeDir = path60.join(directory, ".opencode");
|
|
71839
|
+
const dest = path60.join(opencodeDir, "opencode-swarm.json");
|
|
71603
71840
|
try {
|
|
71604
71841
|
const stat4 = fs39.lstatSync(opencodeDir);
|
|
71605
71842
|
if (stat4.isSymbolicLink())
|
|
@@ -71624,8 +71861,8 @@ function writeProjectConfigIfNew(directory, quiet = false) {
|
|
|
71624
71861
|
}
|
|
71625
71862
|
function writeSwarmConfigExampleIfNew(projectDirectory) {
|
|
71626
71863
|
try {
|
|
71627
|
-
const swarmDir =
|
|
71628
|
-
const dest =
|
|
71864
|
+
const swarmDir = path60.join(projectDirectory, ".swarm");
|
|
71865
|
+
const dest = path60.join(swarmDir, "config.example.json");
|
|
71629
71866
|
if (fs39.existsSync(dest))
|
|
71630
71867
|
return;
|
|
71631
71868
|
if (!fs39.existsSync(swarmDir)) {
|
|
@@ -71662,7 +71899,7 @@ init_state();
|
|
|
71662
71899
|
init_logger();
|
|
71663
71900
|
init_state2();
|
|
71664
71901
|
import * as fs40 from "node:fs";
|
|
71665
|
-
import * as
|
|
71902
|
+
import * as path61 from "node:path";
|
|
71666
71903
|
var oversightSequenceCounter = 0;
|
|
71667
71904
|
var VALID_VERDICTS = [
|
|
71668
71905
|
"APPROVED",
|
|
@@ -71836,10 +72073,10 @@ async function writeFullAutoOversightEvidence(directory, phase, event) {
|
|
|
71836
72073
|
if (phase === undefined)
|
|
71837
72074
|
return;
|
|
71838
72075
|
try {
|
|
71839
|
-
const evidenceDir = validateSwarmPath(directory,
|
|
72076
|
+
const evidenceDir = validateSwarmPath(directory, path61.posix.join("evidence", String(phase)));
|
|
71840
72077
|
fs40.mkdirSync(evidenceDir, { recursive: true });
|
|
71841
72078
|
const fileName = `full-auto-${event.oversight_sequence}.json`;
|
|
71842
|
-
const filePath = validateSwarmPath(directory,
|
|
72079
|
+
const filePath = validateSwarmPath(directory, path61.posix.join("evidence", String(phase), fileName));
|
|
71843
72080
|
fs40.writeFileSync(filePath, `${JSON.stringify(event, null, 2)}
|
|
71844
72081
|
`, "utf-8");
|
|
71845
72082
|
return filePath;
|
|
@@ -72248,11 +72485,11 @@ async function doFlush(directory) {
|
|
|
72248
72485
|
const activitySection = renderActivitySection();
|
|
72249
72486
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
72250
72487
|
const flushedCount = swarmState.pendingEvents;
|
|
72251
|
-
const
|
|
72252
|
-
const tempPath = `${
|
|
72488
|
+
const path62 = nodePath2.join(directory, ".swarm", "context.md");
|
|
72489
|
+
const tempPath = `${path62}.tmp`;
|
|
72253
72490
|
try {
|
|
72254
72491
|
await bunWrite(tempPath, updated);
|
|
72255
|
-
renameSync13(tempPath,
|
|
72492
|
+
renameSync13(tempPath, path62);
|
|
72256
72493
|
} catch (writeError) {
|
|
72257
72494
|
try {
|
|
72258
72495
|
unlinkSync10(tempPath);
|
|
@@ -72495,7 +72732,7 @@ init_state();
|
|
|
72495
72732
|
init_extractors();
|
|
72496
72733
|
init_utils2();
|
|
72497
72734
|
import * as fs41 from "node:fs";
|
|
72498
|
-
import { join as
|
|
72735
|
+
import { join as join55 } from "node:path";
|
|
72499
72736
|
function createCompactionCustomizerHook(config3, directory) {
|
|
72500
72737
|
const enabled = config3.hooks?.compaction !== false;
|
|
72501
72738
|
if (!enabled) {
|
|
@@ -72540,7 +72777,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
72540
72777
|
}
|
|
72541
72778
|
}
|
|
72542
72779
|
try {
|
|
72543
|
-
const summariesDir =
|
|
72780
|
+
const summariesDir = join55(directory, ".swarm", "summaries");
|
|
72544
72781
|
const files = await fs41.promises.readdir(summariesDir);
|
|
72545
72782
|
if (files.length > 0) {
|
|
72546
72783
|
const count = files.length;
|
|
@@ -73920,7 +74157,7 @@ init_schema();
|
|
|
73920
74157
|
init_manager();
|
|
73921
74158
|
init_curator();
|
|
73922
74159
|
init_utils2();
|
|
73923
|
-
import * as
|
|
74160
|
+
import * as path63 from "node:path";
|
|
73924
74161
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
73925
74162
|
let lastKnownPhase = null;
|
|
73926
74163
|
const handler = async (input, _output) => {
|
|
@@ -73940,9 +74177,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
73940
74177
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
73941
74178
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
73942
74179
|
if (initResult.briefing) {
|
|
73943
|
-
const briefingPath =
|
|
74180
|
+
const briefingPath = path63.join(directory, ".swarm", "curator-briefing.md");
|
|
73944
74181
|
const { mkdir: mkdir11, writeFile: writeFile11 } = await import("node:fs/promises");
|
|
73945
|
-
await mkdir11(
|
|
74182
|
+
await mkdir11(path63.dirname(briefingPath), { recursive: true });
|
|
73946
74183
|
await writeFile11(briefingPath, initResult.briefing, "utf-8");
|
|
73947
74184
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
73948
74185
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -74069,16 +74306,16 @@ ${originalText}`;
|
|
|
74069
74306
|
// src/hooks/repo-graph-builder.ts
|
|
74070
74307
|
init_constants();
|
|
74071
74308
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
74072
|
-
import * as
|
|
74309
|
+
import * as path70 from "node:path";
|
|
74073
74310
|
|
|
74074
74311
|
// src/tools/repo-graph/builder.ts
|
|
74075
74312
|
init_logger();
|
|
74076
74313
|
init_path_security();
|
|
74077
|
-
import * as
|
|
74078
|
-
import { existsSync as
|
|
74314
|
+
import * as fsSync4 from "node:fs";
|
|
74315
|
+
import { existsSync as existsSync38, realpathSync as realpathSync6 } from "node:fs";
|
|
74079
74316
|
import * as fsPromises5 from "node:fs/promises";
|
|
74080
74317
|
import * as os7 from "node:os";
|
|
74081
|
-
import * as
|
|
74318
|
+
import * as path66 from "node:path";
|
|
74082
74319
|
|
|
74083
74320
|
// src/utils/timeout.ts
|
|
74084
74321
|
async function withTimeout(promise3, ms, timeoutError) {
|
|
@@ -74110,7 +74347,7 @@ init_zod();
|
|
|
74110
74347
|
init_create_tool();
|
|
74111
74348
|
init_path_security();
|
|
74112
74349
|
import * as fs45 from "node:fs";
|
|
74113
|
-
import * as
|
|
74350
|
+
import * as path64 from "node:path";
|
|
74114
74351
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
74115
74352
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
74116
74353
|
function containsWindowsAttacks(str) {
|
|
@@ -74127,11 +74364,11 @@ function containsWindowsAttacks(str) {
|
|
|
74127
74364
|
}
|
|
74128
74365
|
function isPathInWorkspace(filePath, workspace) {
|
|
74129
74366
|
try {
|
|
74130
|
-
const resolvedPath =
|
|
74367
|
+
const resolvedPath = path64.resolve(workspace, filePath);
|
|
74131
74368
|
const realWorkspace = fs45.realpathSync(workspace);
|
|
74132
74369
|
const realResolvedPath = fs45.realpathSync(resolvedPath);
|
|
74133
|
-
const relativePath =
|
|
74134
|
-
if (relativePath.startsWith("..") ||
|
|
74370
|
+
const relativePath = path64.relative(realWorkspace, realResolvedPath);
|
|
74371
|
+
if (relativePath.startsWith("..") || path64.isAbsolute(relativePath)) {
|
|
74135
74372
|
return false;
|
|
74136
74373
|
}
|
|
74137
74374
|
return true;
|
|
@@ -74143,7 +74380,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
74143
74380
|
return isPathInWorkspace(filePath, workspace);
|
|
74144
74381
|
}
|
|
74145
74382
|
function extractTSSymbols(filePath, cwd) {
|
|
74146
|
-
const fullPath =
|
|
74383
|
+
const fullPath = path64.join(cwd, filePath);
|
|
74147
74384
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
74148
74385
|
return [];
|
|
74149
74386
|
}
|
|
@@ -74295,7 +74532,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
74295
74532
|
});
|
|
74296
74533
|
}
|
|
74297
74534
|
function extractPythonSymbols(filePath, cwd) {
|
|
74298
|
-
const fullPath =
|
|
74535
|
+
const fullPath = path64.join(cwd, filePath);
|
|
74299
74536
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
74300
74537
|
return [];
|
|
74301
74538
|
}
|
|
@@ -74378,7 +74615,7 @@ var symbols = createSwarmTool({
|
|
|
74378
74615
|
}, null, 2);
|
|
74379
74616
|
}
|
|
74380
74617
|
const cwd = directory;
|
|
74381
|
-
const ext =
|
|
74618
|
+
const ext = path64.extname(file3);
|
|
74382
74619
|
if (containsControlChars(file3)) {
|
|
74383
74620
|
return JSON.stringify({
|
|
74384
74621
|
file: file3,
|
|
@@ -74439,16 +74676,16 @@ var symbols = createSwarmTool({
|
|
|
74439
74676
|
});
|
|
74440
74677
|
|
|
74441
74678
|
// src/tools/repo-graph/types.ts
|
|
74442
|
-
import * as
|
|
74679
|
+
import * as path65 from "node:path";
|
|
74443
74680
|
var REPO_GRAPH_FILENAME = "repo-graph.json";
|
|
74444
74681
|
var GRAPH_SCHEMA_VERSION = "1.0.0";
|
|
74445
74682
|
function normalizeGraphPath(filePath) {
|
|
74446
|
-
return
|
|
74683
|
+
return path65.normalize(filePath).replace(/\\/g, "/");
|
|
74447
74684
|
}
|
|
74448
74685
|
function createEmptyGraph(workspaceRoot) {
|
|
74449
74686
|
return {
|
|
74450
74687
|
schema_version: GRAPH_SCHEMA_VERSION,
|
|
74451
|
-
workspaceRoot:
|
|
74688
|
+
workspaceRoot: path65.normalize(workspaceRoot),
|
|
74452
74689
|
nodes: {},
|
|
74453
74690
|
edges: [],
|
|
74454
74691
|
metadata: {
|
|
@@ -74623,8 +74860,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74623
74860
|
}
|
|
74624
74861
|
try {
|
|
74625
74862
|
if (specifier.startsWith(".")) {
|
|
74626
|
-
const sourceDir =
|
|
74627
|
-
let resolved =
|
|
74863
|
+
const sourceDir = path66.dirname(sourceFile);
|
|
74864
|
+
let resolved = path66.resolve(sourceDir, specifier);
|
|
74628
74865
|
let realResolved;
|
|
74629
74866
|
try {
|
|
74630
74867
|
realResolved = realpathSync6(resolved);
|
|
@@ -74635,9 +74872,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74635
74872
|
try {
|
|
74636
74873
|
realRoot = realpathSync6(workspaceRoot);
|
|
74637
74874
|
} catch {
|
|
74638
|
-
realRoot =
|
|
74875
|
+
realRoot = path66.normalize(workspaceRoot);
|
|
74639
74876
|
}
|
|
74640
|
-
if (!
|
|
74877
|
+
if (!existsSync38(resolved)) {
|
|
74641
74878
|
const EXTENSIONS = [
|
|
74642
74879
|
".ts",
|
|
74643
74880
|
".tsx",
|
|
@@ -74651,7 +74888,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74651
74888
|
let found = null;
|
|
74652
74889
|
for (const ext of EXTENSIONS) {
|
|
74653
74890
|
const candidate = resolved + ext;
|
|
74654
|
-
if (
|
|
74891
|
+
if (existsSync38(candidate)) {
|
|
74655
74892
|
found = candidate;
|
|
74656
74893
|
break;
|
|
74657
74894
|
}
|
|
@@ -74667,9 +74904,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74667
74904
|
return null;
|
|
74668
74905
|
}
|
|
74669
74906
|
}
|
|
74670
|
-
const normalizedResolved =
|
|
74671
|
-
const normalizedRoot =
|
|
74672
|
-
if (!normalizedResolved.startsWith(normalizedRoot +
|
|
74907
|
+
const normalizedResolved = path66.normalize(realResolved);
|
|
74908
|
+
const normalizedRoot = path66.normalize(realRoot);
|
|
74909
|
+
if (!normalizedResolved.startsWith(normalizedRoot + path66.sep) && normalizedResolved !== normalizedRoot) {
|
|
74673
74910
|
return null;
|
|
74674
74911
|
}
|
|
74675
74912
|
return resolved;
|
|
@@ -74684,12 +74921,12 @@ function isRefusedWorkspaceRoot(target) {
|
|
|
74684
74921
|
try {
|
|
74685
74922
|
resolved = realpathSync6(target);
|
|
74686
74923
|
} catch {
|
|
74687
|
-
resolved =
|
|
74924
|
+
resolved = path66.resolve(target);
|
|
74688
74925
|
}
|
|
74689
74926
|
const refused = new Set;
|
|
74690
74927
|
const add = (p) => {
|
|
74691
74928
|
if (typeof p === "string" && p.length > 0) {
|
|
74692
|
-
refused.add(
|
|
74929
|
+
refused.add(path66.resolve(p));
|
|
74693
74930
|
}
|
|
74694
74931
|
};
|
|
74695
74932
|
add(os7.homedir());
|
|
@@ -74799,7 +75036,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74799
75036
|
ctx.stats.skippedDirs++;
|
|
74800
75037
|
continue;
|
|
74801
75038
|
}
|
|
74802
|
-
const fullPath =
|
|
75039
|
+
const fullPath = path66.join(current, entry.name);
|
|
74803
75040
|
if (entry.isSymbolicLink() && !ctx.followSymlinks) {
|
|
74804
75041
|
ctx.stats.skippedDirs++;
|
|
74805
75042
|
continue;
|
|
@@ -74807,7 +75044,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74807
75044
|
if (entry.isDirectory()) {
|
|
74808
75045
|
queue.push(fullPath);
|
|
74809
75046
|
} else if (entry.isFile()) {
|
|
74810
|
-
const ext =
|
|
75047
|
+
const ext = path66.extname(fullPath).toLowerCase();
|
|
74811
75048
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
74812
75049
|
files.push(fullPath);
|
|
74813
75050
|
}
|
|
@@ -74824,11 +75061,11 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74824
75061
|
return files;
|
|
74825
75062
|
}
|
|
74826
75063
|
function toModuleName(filePath, workspaceRoot) {
|
|
74827
|
-
const relative11 =
|
|
74828
|
-
return relative11.split(
|
|
75064
|
+
const relative11 = path66.relative(workspaceRoot, filePath);
|
|
75065
|
+
return relative11.split(path66.sep).join("/");
|
|
74829
75066
|
}
|
|
74830
75067
|
function getLanguage(filePath) {
|
|
74831
|
-
const ext =
|
|
75068
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
74832
75069
|
return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
|
|
74833
75070
|
}
|
|
74834
75071
|
function isBinaryContent(content) {
|
|
@@ -74841,26 +75078,26 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
|
|
|
74841
75078
|
let content;
|
|
74842
75079
|
let fileStats;
|
|
74843
75080
|
try {
|
|
74844
|
-
fileStats =
|
|
75081
|
+
fileStats = fsSync4.statSync(filePath);
|
|
74845
75082
|
if (fileStats.size > maxFileSize) {
|
|
74846
75083
|
return { node: null, edges: [] };
|
|
74847
75084
|
}
|
|
74848
|
-
content =
|
|
75085
|
+
content = fsSync4.readFileSync(filePath, "utf-8");
|
|
74849
75086
|
} catch {
|
|
74850
75087
|
return { node: null, edges: [] };
|
|
74851
75088
|
}
|
|
74852
75089
|
if (isBinaryContent(content)) {
|
|
74853
75090
|
return { node: null, edges: [] };
|
|
74854
75091
|
}
|
|
74855
|
-
const ext =
|
|
75092
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
74856
75093
|
let exports = [];
|
|
74857
75094
|
try {
|
|
74858
75095
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
74859
|
-
const relativePath =
|
|
75096
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
74860
75097
|
const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
|
|
74861
75098
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
74862
75099
|
} else if (ext === ".py") {
|
|
74863
|
-
const relativePath =
|
|
75100
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
74864
75101
|
const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
|
|
74865
75102
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
74866
75103
|
}
|
|
@@ -74897,8 +75134,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
74897
75134
|
const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
|
|
74898
75135
|
const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
|
|
74899
75136
|
const followSymlinks = options?.followSymlinks ?? false;
|
|
74900
|
-
const absoluteRoot =
|
|
74901
|
-
if (!
|
|
75137
|
+
const absoluteRoot = path66.resolve(workspaceRoot);
|
|
75138
|
+
if (!existsSync38(absoluteRoot)) {
|
|
74902
75139
|
throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
|
|
74903
75140
|
}
|
|
74904
75141
|
if (isRefusedWorkspaceRoot(absoluteRoot)) {
|
|
@@ -74953,15 +75190,15 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
74953
75190
|
return graph;
|
|
74954
75191
|
}
|
|
74955
75192
|
// src/tools/repo-graph/cache.ts
|
|
74956
|
-
import * as
|
|
75193
|
+
import * as path67 from "node:path";
|
|
74957
75194
|
var graphCache = new Map;
|
|
74958
75195
|
var dirtyFlags = new Map;
|
|
74959
75196
|
var mtimeCache = new Map;
|
|
74960
75197
|
function getCachedGraph(workspace) {
|
|
74961
|
-
return graphCache.get(
|
|
75198
|
+
return graphCache.get(path67.normalize(workspace));
|
|
74962
75199
|
}
|
|
74963
75200
|
function setCachedGraph(workspace, graph, mtime) {
|
|
74964
|
-
const normalized =
|
|
75201
|
+
const normalized = path67.normalize(workspace);
|
|
74965
75202
|
graphCache.set(normalized, graph);
|
|
74966
75203
|
dirtyFlags.set(normalized, false);
|
|
74967
75204
|
if (mtime !== undefined) {
|
|
@@ -74969,30 +75206,30 @@ function setCachedGraph(workspace, graph, mtime) {
|
|
|
74969
75206
|
}
|
|
74970
75207
|
}
|
|
74971
75208
|
function isDirty(workspace) {
|
|
74972
|
-
return dirtyFlags.get(
|
|
75209
|
+
return dirtyFlags.get(path67.normalize(workspace)) ?? false;
|
|
74973
75210
|
}
|
|
74974
75211
|
function clearCache(workspace) {
|
|
74975
|
-
const normalized =
|
|
75212
|
+
const normalized = path67.normalize(workspace);
|
|
74976
75213
|
graphCache.delete(normalized);
|
|
74977
75214
|
dirtyFlags.delete(normalized);
|
|
74978
75215
|
mtimeCache.delete(normalized);
|
|
74979
75216
|
}
|
|
74980
75217
|
function getCachedMtime(workspace) {
|
|
74981
|
-
return mtimeCache.get(
|
|
75218
|
+
return mtimeCache.get(path67.normalize(workspace));
|
|
74982
75219
|
}
|
|
74983
75220
|
// src/tools/repo-graph/incremental.ts
|
|
74984
75221
|
init_logger();
|
|
74985
|
-
import { existsSync as
|
|
75222
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
74986
75223
|
import * as fsPromises7 from "node:fs/promises";
|
|
74987
|
-
import * as
|
|
75224
|
+
import * as path69 from "node:path";
|
|
74988
75225
|
|
|
74989
75226
|
// src/tools/repo-graph/storage.ts
|
|
74990
75227
|
init_utils2();
|
|
74991
75228
|
init_logger();
|
|
74992
75229
|
init_path_security();
|
|
74993
|
-
import { constants as constants4, existsSync as
|
|
75230
|
+
import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
|
|
74994
75231
|
import * as fsPromises6 from "node:fs/promises";
|
|
74995
|
-
import * as
|
|
75232
|
+
import * as path68 from "node:path";
|
|
74996
75233
|
var WINDOWS_RENAME_MAX_RETRIES2 = 3;
|
|
74997
75234
|
var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
|
|
74998
75235
|
function getGraphPath(workspace) {
|
|
@@ -75003,12 +75240,12 @@ function getGraphPath(workspace) {
|
|
|
75003
75240
|
}
|
|
75004
75241
|
async function loadGraph(workspace) {
|
|
75005
75242
|
validateWorkspace(workspace);
|
|
75006
|
-
const normalized =
|
|
75243
|
+
const normalized = path68.normalize(workspace);
|
|
75007
75244
|
const cached3 = getCachedGraph(normalized);
|
|
75008
75245
|
if (cached3 && !isDirty(normalized)) {
|
|
75009
75246
|
try {
|
|
75010
75247
|
const graphPath = getGraphPath(workspace);
|
|
75011
|
-
if (
|
|
75248
|
+
if (existsSync39(graphPath)) {
|
|
75012
75249
|
const stats = await fsPromises6.stat(graphPath);
|
|
75013
75250
|
const cachedMtime = getCachedMtime(normalized);
|
|
75014
75251
|
if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
|
|
@@ -75025,7 +75262,7 @@ async function loadGraph(workspace) {
|
|
|
75025
75262
|
}
|
|
75026
75263
|
try {
|
|
75027
75264
|
const graphPath = getGraphPath(workspace);
|
|
75028
|
-
if (!
|
|
75265
|
+
if (!existsSync39(graphPath)) {
|
|
75029
75266
|
return null;
|
|
75030
75267
|
}
|
|
75031
75268
|
const stats = await fsPromises6.stat(graphPath);
|
|
@@ -75097,28 +75334,28 @@ async function saveGraph(workspace, graph, options) {
|
|
|
75097
75334
|
if (!Array.isArray(graph.edges)) {
|
|
75098
75335
|
throw new Error("Graph must have edges array");
|
|
75099
75336
|
}
|
|
75100
|
-
const normalizedWorkspace =
|
|
75337
|
+
const normalizedWorkspace = path68.normalize(workspace);
|
|
75101
75338
|
let realWorkspace;
|
|
75102
75339
|
try {
|
|
75103
75340
|
realWorkspace = realpathSync7(workspace);
|
|
75104
75341
|
} catch {
|
|
75105
75342
|
realWorkspace = normalizedWorkspace;
|
|
75106
75343
|
}
|
|
75107
|
-
const normalizedGraphRoot =
|
|
75344
|
+
const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
|
|
75108
75345
|
let realGraphRoot;
|
|
75109
75346
|
try {
|
|
75110
75347
|
realGraphRoot = realpathSync7(graph.workspaceRoot);
|
|
75111
75348
|
} catch {
|
|
75112
75349
|
realGraphRoot = normalizedGraphRoot;
|
|
75113
75350
|
}
|
|
75114
|
-
if (
|
|
75351
|
+
if (path68.normalize(realWorkspace) !== path68.normalize(realGraphRoot)) {
|
|
75115
75352
|
throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
|
|
75116
75353
|
}
|
|
75117
75354
|
const normalized = normalizedWorkspace;
|
|
75118
75355
|
const graphPath = getGraphPath(workspace);
|
|
75119
75356
|
updateGraphMetadata(graph);
|
|
75120
75357
|
const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
75121
|
-
await fsPromises6.mkdir(
|
|
75358
|
+
await fsPromises6.mkdir(path68.dirname(tempPath), { recursive: true });
|
|
75122
75359
|
let lastError = null;
|
|
75123
75360
|
try {
|
|
75124
75361
|
if (options?.createAtomic) {
|
|
@@ -75186,12 +75423,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
75186
75423
|
return graph2;
|
|
75187
75424
|
}
|
|
75188
75425
|
const graph = existingGraph;
|
|
75189
|
-
const absoluteRoot =
|
|
75426
|
+
const absoluteRoot = path69.resolve(workspaceRoot);
|
|
75190
75427
|
const maxFileSize = 1024 * 1024;
|
|
75191
75428
|
const updatedPaths = new Set;
|
|
75192
75429
|
for (const rawFilePath of filePaths) {
|
|
75193
75430
|
const normalizedPath = normalizeGraphPath(rawFilePath);
|
|
75194
|
-
const fileExists =
|
|
75431
|
+
const fileExists = existsSync40(rawFilePath);
|
|
75195
75432
|
if (fileExists) {
|
|
75196
75433
|
graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
|
|
75197
75434
|
const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
|
|
@@ -75226,12 +75463,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
75226
75463
|
await saveGraph(workspaceRoot, rebuiltGraph);
|
|
75227
75464
|
return rebuiltGraph;
|
|
75228
75465
|
}
|
|
75229
|
-
const normalizedWorkspace =
|
|
75466
|
+
const normalizedWorkspace = path69.normalize(workspaceRoot);
|
|
75230
75467
|
const loadedMtime = getCachedMtime(normalizedWorkspace);
|
|
75231
75468
|
if (loadedMtime !== undefined) {
|
|
75232
75469
|
try {
|
|
75233
75470
|
const graphPath = getGraphPath(workspaceRoot);
|
|
75234
|
-
if (
|
|
75471
|
+
if (existsSync40(graphPath)) {
|
|
75235
75472
|
const currentStats = await fsPromises7.stat(graphPath);
|
|
75236
75473
|
if (currentStats.mtimeMs !== loadedMtime) {
|
|
75237
75474
|
warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
|
|
@@ -75324,7 +75561,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
75324
75561
|
return;
|
|
75325
75562
|
if (!isSupportedSourceFile(filePath))
|
|
75326
75563
|
return;
|
|
75327
|
-
const absoluteFilePath =
|
|
75564
|
+
const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
|
|
75328
75565
|
let realFilePath;
|
|
75329
75566
|
try {
|
|
75330
75567
|
realFilePath = realpathSync8(absoluteFilePath);
|
|
@@ -75351,7 +75588,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
75351
75588
|
try {
|
|
75352
75589
|
await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
|
|
75353
75590
|
consecutiveFailures = 0;
|
|
75354
|
-
log(`[repo-graph] Incremental update for ${
|
|
75591
|
+
log(`[repo-graph] Incremental update for ${path70.basename(filePath)}`);
|
|
75355
75592
|
} catch (error93) {
|
|
75356
75593
|
const message = error93 instanceof Error ? error93.message : String(error93);
|
|
75357
75594
|
consecutiveFailures++;
|
|
@@ -75374,14 +75611,14 @@ init_manager2();
|
|
|
75374
75611
|
init_detector();
|
|
75375
75612
|
init_manager();
|
|
75376
75613
|
import * as fs54 from "node:fs";
|
|
75377
|
-
import * as
|
|
75614
|
+
import * as path80 from "node:path";
|
|
75378
75615
|
|
|
75379
75616
|
// src/services/decision-drift-analyzer.ts
|
|
75380
75617
|
init_utils2();
|
|
75381
75618
|
init_manager();
|
|
75382
75619
|
init_utils();
|
|
75383
75620
|
import * as fs46 from "node:fs";
|
|
75384
|
-
import * as
|
|
75621
|
+
import * as path71 from "node:path";
|
|
75385
75622
|
var DEFAULT_DRIFT_CONFIG = {
|
|
75386
75623
|
staleThresholdPhases: 1,
|
|
75387
75624
|
detectContradictions: true,
|
|
@@ -75535,7 +75772,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
75535
75772
|
currentPhase = legacyPhase;
|
|
75536
75773
|
}
|
|
75537
75774
|
}
|
|
75538
|
-
const contextPath =
|
|
75775
|
+
const contextPath = path71.join(directory, ".swarm", "context.md");
|
|
75539
75776
|
let contextContent = "";
|
|
75540
75777
|
try {
|
|
75541
75778
|
if (fs46.existsSync(contextPath)) {
|
|
@@ -75674,7 +75911,7 @@ init_utils();
|
|
|
75674
75911
|
init_constants();
|
|
75675
75912
|
init_schema();
|
|
75676
75913
|
import * as fs47 from "node:fs/promises";
|
|
75677
|
-
import * as
|
|
75914
|
+
import * as path72 from "node:path";
|
|
75678
75915
|
function safeGet(obj, key) {
|
|
75679
75916
|
if (!obj || !Object.hasOwn(obj, key))
|
|
75680
75917
|
return;
|
|
@@ -75906,9 +76143,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
75906
76143
|
let eventLogged = false;
|
|
75907
76144
|
let checkpointCreated = false;
|
|
75908
76145
|
try {
|
|
75909
|
-
const swarmDir =
|
|
76146
|
+
const swarmDir = path72.join(directory, ".swarm");
|
|
75910
76147
|
await fs47.mkdir(swarmDir, { recursive: true });
|
|
75911
|
-
const eventsPath =
|
|
76148
|
+
const eventsPath = path72.join(swarmDir, "events.jsonl");
|
|
75912
76149
|
await fs47.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
75913
76150
|
`);
|
|
75914
76151
|
eventLogged = true;
|
|
@@ -76044,7 +76281,7 @@ import * as fs51 from "node:fs";
|
|
|
76044
76281
|
|
|
76045
76282
|
// src/graph/graph-builder.ts
|
|
76046
76283
|
import * as fs49 from "node:fs";
|
|
76047
|
-
import * as
|
|
76284
|
+
import * as path75 from "node:path";
|
|
76048
76285
|
|
|
76049
76286
|
// node_modules/yocto-queue/index.js
|
|
76050
76287
|
class Node {
|
|
@@ -76205,7 +76442,7 @@ function validateConcurrency(concurrency) {
|
|
|
76205
76442
|
// src/graph/import-extractor.ts
|
|
76206
76443
|
init_path_security();
|
|
76207
76444
|
import * as fs48 from "node:fs";
|
|
76208
|
-
import * as
|
|
76445
|
+
import * as path73 from "node:path";
|
|
76209
76446
|
var SOURCE_EXTENSIONS2 = [
|
|
76210
76447
|
".ts",
|
|
76211
76448
|
".tsx",
|
|
@@ -76250,14 +76487,14 @@ function getLanguageFromExtension(ext) {
|
|
|
76250
76487
|
return null;
|
|
76251
76488
|
}
|
|
76252
76489
|
function toRelForwardSlash(absPath, root) {
|
|
76253
|
-
return
|
|
76490
|
+
return path73.relative(root, absPath).replace(/\\/g, "/");
|
|
76254
76491
|
}
|
|
76255
76492
|
function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
76256
76493
|
if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
|
|
76257
76494
|
return null;
|
|
76258
76495
|
}
|
|
76259
|
-
const sourceDir =
|
|
76260
|
-
const baseAbs =
|
|
76496
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
76497
|
+
const baseAbs = path73.resolve(sourceDir, rawModule);
|
|
76261
76498
|
const probe = (basePath) => {
|
|
76262
76499
|
for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
|
|
76263
76500
|
const test = basePath + ext;
|
|
@@ -76268,7 +76505,7 @@ function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
|
76268
76505
|
} catch {}
|
|
76269
76506
|
}
|
|
76270
76507
|
for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
|
|
76271
|
-
const test =
|
|
76508
|
+
const test = path73.join(basePath, indexFile);
|
|
76272
76509
|
try {
|
|
76273
76510
|
const stat6 = fs48.statSync(test);
|
|
76274
76511
|
if (stat6.isFile())
|
|
@@ -76298,13 +76535,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
76298
76535
|
}
|
|
76299
76536
|
const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
|
|
76300
76537
|
const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
|
|
76301
|
-
const sourceDir =
|
|
76302
|
-
const baseAbs =
|
|
76538
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
76539
|
+
const baseAbs = path73.resolve(sourceDir, upDirs + remainder);
|
|
76303
76540
|
const accept = (test) => {
|
|
76304
76541
|
try {
|
|
76305
76542
|
const stat6 = fs48.statSync(test);
|
|
76306
76543
|
if (stat6.isFile()) {
|
|
76307
|
-
const rel =
|
|
76544
|
+
const rel = path73.relative(workspaceRoot, test).replace(/\\/g, "/");
|
|
76308
76545
|
if (rel.startsWith(".."))
|
|
76309
76546
|
return null;
|
|
76310
76547
|
return test;
|
|
@@ -76318,7 +76555,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
76318
76555
|
return hit;
|
|
76319
76556
|
}
|
|
76320
76557
|
for (const indexFile of PY_INDEX_CANDIDATES) {
|
|
76321
|
-
const hit = accept(
|
|
76558
|
+
const hit = accept(path73.join(baseAbs, indexFile));
|
|
76322
76559
|
if (hit)
|
|
76323
76560
|
return hit;
|
|
76324
76561
|
}
|
|
@@ -76689,7 +76926,7 @@ function parseRustUses(content) {
|
|
|
76689
76926
|
}
|
|
76690
76927
|
function extractImports5(opts) {
|
|
76691
76928
|
const { absoluteFilePath, workspaceRoot } = opts;
|
|
76692
|
-
const ext =
|
|
76929
|
+
const ext = path73.extname(absoluteFilePath).toLowerCase();
|
|
76693
76930
|
const language = getLanguageFromExtension(ext);
|
|
76694
76931
|
if (!language)
|
|
76695
76932
|
return [];
|
|
@@ -76740,9 +76977,9 @@ function extractImports5(opts) {
|
|
|
76740
76977
|
}
|
|
76741
76978
|
|
|
76742
76979
|
// src/graph/symbol-extractor.ts
|
|
76743
|
-
import * as
|
|
76980
|
+
import * as path74 from "node:path";
|
|
76744
76981
|
function extractExportedSymbols(relativeFilePath, workspaceRoot) {
|
|
76745
|
-
const ext =
|
|
76982
|
+
const ext = path74.extname(relativeFilePath).toLowerCase();
|
|
76746
76983
|
const language = getLanguageFromExtension(ext);
|
|
76747
76984
|
if (!language)
|
|
76748
76985
|
return [];
|
|
@@ -76831,15 +77068,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
|
76831
77068
|
if (entry.isDirectory()) {
|
|
76832
77069
|
if (skipDirs.has(entry.name))
|
|
76833
77070
|
continue;
|
|
76834
|
-
stack.push(
|
|
77071
|
+
stack.push(path75.join(dir, entry.name));
|
|
76835
77072
|
continue;
|
|
76836
77073
|
}
|
|
76837
77074
|
if (!entry.isFile())
|
|
76838
77075
|
continue;
|
|
76839
|
-
const ext =
|
|
77076
|
+
const ext = path75.extname(entry.name).toLowerCase();
|
|
76840
77077
|
if (!SOURCE_EXT_SET.has(ext))
|
|
76841
77078
|
continue;
|
|
76842
|
-
out2.push(
|
|
77079
|
+
out2.push(path75.join(dir, entry.name));
|
|
76843
77080
|
}
|
|
76844
77081
|
}
|
|
76845
77082
|
return out2;
|
|
@@ -76867,7 +77104,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
|
|
|
76867
77104
|
};
|
|
76868
77105
|
}
|
|
76869
77106
|
async function processFile(absoluteFilePath, workspaceRoot) {
|
|
76870
|
-
const ext =
|
|
77107
|
+
const ext = path75.extname(absoluteFilePath).toLowerCase();
|
|
76871
77108
|
const language = getLanguageFromExtension(ext);
|
|
76872
77109
|
if (!language)
|
|
76873
77110
|
return null;
|
|
@@ -76887,7 +77124,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
|
|
|
76887
77124
|
} catch {
|
|
76888
77125
|
return null;
|
|
76889
77126
|
}
|
|
76890
|
-
const relPath =
|
|
77127
|
+
const relPath = path75.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
|
|
76891
77128
|
const imports = extractImports5({
|
|
76892
77129
|
absoluteFilePath,
|
|
76893
77130
|
workspaceRoot,
|
|
@@ -77129,10 +77366,10 @@ function formatSummary(opts) {
|
|
|
77129
77366
|
// src/graph/graph-store.ts
|
|
77130
77367
|
import * as crypto6 from "node:crypto";
|
|
77131
77368
|
import * as fs50 from "node:fs";
|
|
77132
|
-
import * as
|
|
77369
|
+
import * as path76 from "node:path";
|
|
77133
77370
|
var SWARM_DIR = ".swarm";
|
|
77134
77371
|
function getGraphPath2(workspaceRoot) {
|
|
77135
|
-
return
|
|
77372
|
+
return path76.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
|
|
77136
77373
|
}
|
|
77137
77374
|
function loadGraph2(workspaceRoot) {
|
|
77138
77375
|
const file3 = getGraphPath2(workspaceRoot);
|
|
@@ -77154,7 +77391,7 @@ function loadGraph2(workspaceRoot) {
|
|
|
77154
77391
|
}
|
|
77155
77392
|
function saveGraph2(workspaceRoot, graph) {
|
|
77156
77393
|
const file3 = getGraphPath2(workspaceRoot);
|
|
77157
|
-
const dir =
|
|
77394
|
+
const dir = path76.dirname(file3);
|
|
77158
77395
|
try {
|
|
77159
77396
|
const stat6 = fs50.lstatSync(dir);
|
|
77160
77397
|
if (stat6.isSymbolicLink()) {
|
|
@@ -77260,7 +77497,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
|
|
|
77260
77497
|
// src/hooks/semantic-diff-injection.ts
|
|
77261
77498
|
import * as child_process5 from "node:child_process";
|
|
77262
77499
|
import * as fs52 from "node:fs";
|
|
77263
|
-
import * as
|
|
77500
|
+
import * as path78 from "node:path";
|
|
77264
77501
|
|
|
77265
77502
|
// src/diff/ast-diff.ts
|
|
77266
77503
|
init_tree_sitter();
|
|
@@ -78007,17 +78244,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
78007
78244
|
const fileConsumers = {};
|
|
78008
78245
|
if (graph) {
|
|
78009
78246
|
for (const f of filesToProcess) {
|
|
78010
|
-
const relativePath =
|
|
78247
|
+
const relativePath = path78.isAbsolute(f) ? path78.relative(directory, f) : f;
|
|
78011
78248
|
const normalized = normalizeGraphPath2(relativePath);
|
|
78012
78249
|
fileConsumers[normalized] = getImporters(graph, normalized).length;
|
|
78013
78250
|
fileConsumers[f] = fileConsumers[normalized];
|
|
78014
78251
|
}
|
|
78015
78252
|
}
|
|
78016
78253
|
for (const filePath of filesToProcess) {
|
|
78017
|
-
const normalizedPath =
|
|
78018
|
-
const resolvedPath =
|
|
78019
|
-
const relativeToDir =
|
|
78020
|
-
if (relativeToDir.startsWith("..") ||
|
|
78254
|
+
const normalizedPath = path78.normalize(filePath);
|
|
78255
|
+
const resolvedPath = path78.resolve(directory, normalizedPath);
|
|
78256
|
+
const relativeToDir = path78.relative(directory, resolvedPath);
|
|
78257
|
+
if (relativeToDir.startsWith("..") || path78.isAbsolute(relativeToDir)) {
|
|
78021
78258
|
continue;
|
|
78022
78259
|
}
|
|
78023
78260
|
try {
|
|
@@ -78044,7 +78281,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
78044
78281
|
stdio: "pipe",
|
|
78045
78282
|
maxBuffer: 5 * 1024 * 1024
|
|
78046
78283
|
}) : "";
|
|
78047
|
-
const newContent = fs52.readFileSync(
|
|
78284
|
+
const newContent = fs52.readFileSync(path78.join(directory, filePath), "utf-8");
|
|
78048
78285
|
const astResult = await computeASTDiff(filePath, oldContent, newContent);
|
|
78049
78286
|
if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
|
|
78050
78287
|
astDiffs.push(astResult);
|
|
@@ -78071,6 +78308,49 @@ ${markdown}`;
|
|
|
78071
78308
|
|
|
78072
78309
|
// src/hooks/system-enhancer.ts
|
|
78073
78310
|
init_utils2();
|
|
78311
|
+
function buildSpecDriftAdvisory(args2) {
|
|
78312
|
+
const lines = [
|
|
78313
|
+
"[spec-drift]",
|
|
78314
|
+
`Reason: ${args2.reason}`,
|
|
78315
|
+
`Stored spec hash: ${args2.storedHash}`,
|
|
78316
|
+
`Current spec hash: ${args2.currentHash ?? "(spec.md missing)"}`,
|
|
78317
|
+
"Action: surface this warning to the user at your next user-facing reply. " + "Do NOT proceed with destructive plan operations (save_plan with removals, " + "update_task_status, phase_complete, lean_turbo_run_phase, " + "lean_turbo_acquire_locks) until the user runs /swarm clarify or " + "/swarm acknowledge-spec-drift."
|
|
78318
|
+
];
|
|
78319
|
+
if (args2.midLoadRemovals) {
|
|
78320
|
+
lines.push(`Auto-removed during recovery: ${args2.midLoadRemovals.count} task(s) ` + `(source: ${args2.midLoadRemovals.source}). See ` + ".swarm/plan-ledger.jsonl for IDs.");
|
|
78321
|
+
}
|
|
78322
|
+
return lines.join(`
|
|
78323
|
+
`);
|
|
78324
|
+
}
|
|
78325
|
+
function readSpecStalenessSnapshot2(directory) {
|
|
78326
|
+
try {
|
|
78327
|
+
const p = path80.join(directory, ".swarm", "spec-staleness.json");
|
|
78328
|
+
if (!fs54.existsSync(p))
|
|
78329
|
+
return null;
|
|
78330
|
+
const raw = fs54.readFileSync(p, "utf-8");
|
|
78331
|
+
const parsed = JSON.parse(raw);
|
|
78332
|
+
if (typeof parsed?.specHash_plan === "string" && (typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null)) {
|
|
78333
|
+
return {
|
|
78334
|
+
specHash_plan: parsed.specHash_plan,
|
|
78335
|
+
specHash_current: parsed.specHash_current
|
|
78336
|
+
};
|
|
78337
|
+
}
|
|
78338
|
+
} catch {}
|
|
78339
|
+
return null;
|
|
78340
|
+
}
|
|
78341
|
+
function maybeAppendSpecDriftAdvisory(output, directory, plan) {
|
|
78342
|
+
if (!plan?._specStale)
|
|
78343
|
+
return;
|
|
78344
|
+
const snap = readSpecStalenessSnapshot2(directory);
|
|
78345
|
+
const storedHash = snap?.specHash_plan ?? plan.specHash ?? "(unknown — plan missing specHash)";
|
|
78346
|
+
const currentHash = snap?.specHash_current ?? null;
|
|
78347
|
+
output.system.push(buildSpecDriftAdvisory({
|
|
78348
|
+
reason: plan._specStaleReason ?? "spec.md changed since plan was saved",
|
|
78349
|
+
currentHash,
|
|
78350
|
+
storedHash,
|
|
78351
|
+
midLoadRemovals: plan._midLoadRemovals
|
|
78352
|
+
}));
|
|
78353
|
+
}
|
|
78074
78354
|
function extractAgentPrefix(fullAgentName) {
|
|
78075
78355
|
if (!fullAgentName)
|
|
78076
78356
|
return "";
|
|
@@ -78392,7 +78672,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
78392
78672
|
await fs54.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
78393
78673
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
78394
78674
|
try {
|
|
78395
|
-
const projectName =
|
|
78675
|
+
const projectName = path80.basename(path80.resolve(directory));
|
|
78396
78676
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
78397
78677
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
78398
78678
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -78433,6 +78713,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
78433
78713
|
} catch (error93) {
|
|
78434
78714
|
warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
78435
78715
|
}
|
|
78716
|
+
maybeAppendSpecDriftAdvisory(output, directory, plan2);
|
|
78436
78717
|
const mode = await detectArchitectMode(directory);
|
|
78437
78718
|
let planContent = null;
|
|
78438
78719
|
let phaseHeader = "";
|
|
@@ -78591,7 +78872,7 @@ ${lines.join(`
|
|
|
78591
78872
|
try {
|
|
78592
78873
|
const taskId_ccp = ccpSession?.currentTaskId;
|
|
78593
78874
|
if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
|
|
78594
|
-
const evidencePath =
|
|
78875
|
+
const evidencePath = path80.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
|
|
78595
78876
|
if (fs54.existsSync(evidencePath)) {
|
|
78596
78877
|
const evidenceContent = fs54.readFileSync(evidencePath, "utf-8");
|
|
78597
78878
|
const evidenceData = JSON.parse(evidenceContent);
|
|
@@ -78806,6 +79087,7 @@ ${budgetWarning}`);
|
|
|
78806
79087
|
} catch (error93) {
|
|
78807
79088
|
warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
78808
79089
|
}
|
|
79090
|
+
maybeAppendSpecDriftAdvisory(output, directory, plan);
|
|
78809
79091
|
let currentPhase = null;
|
|
78810
79092
|
let currentTask = null;
|
|
78811
79093
|
if (plan && plan.migration_status !== "migration_failed") {
|
|
@@ -79754,7 +80036,7 @@ import * as fs56 from "node:fs";
|
|
|
79754
80036
|
// src/full-auto/policy.ts
|
|
79755
80037
|
init_constants();
|
|
79756
80038
|
import * as fs55 from "node:fs";
|
|
79757
|
-
import * as
|
|
80039
|
+
import * as path81 from "node:path";
|
|
79758
80040
|
var READ_ONLY_TOOLS = new Set([
|
|
79759
80041
|
"check_gate_status",
|
|
79760
80042
|
"completion_verify",
|
|
@@ -79949,11 +80231,11 @@ function normalizePath3(p) {
|
|
|
79949
80231
|
function isWithinDirectory(target, root) {
|
|
79950
80232
|
if (!target || !root)
|
|
79951
80233
|
return false;
|
|
79952
|
-
const resolvedTarget =
|
|
79953
|
-
const resolvedRoot =
|
|
80234
|
+
const resolvedTarget = path81.resolve(target);
|
|
80235
|
+
const resolvedRoot = path81.resolve(root);
|
|
79954
80236
|
if (resolvedTarget === resolvedRoot)
|
|
79955
80237
|
return true;
|
|
79956
|
-
const withSep = resolvedRoot.endsWith(
|
|
80238
|
+
const withSep = resolvedRoot.endsWith(path81.sep) ? resolvedRoot : resolvedRoot + path81.sep;
|
|
79957
80239
|
if (process.platform === "win32") {
|
|
79958
80240
|
return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());
|
|
79959
80241
|
}
|
|
@@ -80012,7 +80294,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80012
80294
|
highRiskBuild: false
|
|
80013
80295
|
};
|
|
80014
80296
|
}
|
|
80015
|
-
const absolute =
|
|
80297
|
+
const absolute = path81.isAbsolute(filePath) ? filePath : path81.resolve(context.directory, filePath);
|
|
80016
80298
|
const resolvedAbsolute = (() => {
|
|
80017
80299
|
try {
|
|
80018
80300
|
let candidate = absolute;
|
|
@@ -80028,7 +80310,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80028
80310
|
}
|
|
80029
80311
|
return absolute;
|
|
80030
80312
|
}
|
|
80031
|
-
const parent =
|
|
80313
|
+
const parent = path81.dirname(candidate);
|
|
80032
80314
|
if (parent === candidate)
|
|
80033
80315
|
break;
|
|
80034
80316
|
candidate = parent;
|
|
@@ -80040,7 +80322,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80040
80322
|
}
|
|
80041
80323
|
})();
|
|
80042
80324
|
const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
|
|
80043
|
-
const relative17 =
|
|
80325
|
+
const relative17 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
|
|
80044
80326
|
let withinDeclaredScope = null;
|
|
80045
80327
|
if (Array.isArray(context.declaredScope)) {
|
|
80046
80328
|
withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
|
|
@@ -80350,7 +80632,7 @@ function classifyFullAutoToolAction(input) {
|
|
|
80350
80632
|
recoverable: true
|
|
80351
80633
|
};
|
|
80352
80634
|
}
|
|
80353
|
-
if (isProtectedPath(
|
|
80635
|
+
if (isProtectedPath(path81.relative(input.directory, path81.resolve(input.directory, p)), config3)) {
|
|
80354
80636
|
return {
|
|
80355
80637
|
action: "escalate_critic",
|
|
80356
80638
|
reason: `write to protected path requires critic approval: ${p}`,
|
|
@@ -81124,7 +81406,7 @@ init_hive_promoter();
|
|
|
81124
81406
|
|
|
81125
81407
|
// src/hooks/incremental-verify.ts
|
|
81126
81408
|
import * as fs58 from "node:fs";
|
|
81127
|
-
import * as
|
|
81409
|
+
import * as path82 from "node:path";
|
|
81128
81410
|
|
|
81129
81411
|
// src/hooks/spawn-helper.ts
|
|
81130
81412
|
import * as child_process6 from "node:child_process";
|
|
@@ -81202,18 +81484,18 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
81202
81484
|
// src/hooks/incremental-verify.ts
|
|
81203
81485
|
var emittedSkipAdvisories = new Set;
|
|
81204
81486
|
function detectPackageManager(projectDir) {
|
|
81205
|
-
if (fs58.existsSync(
|
|
81487
|
+
if (fs58.existsSync(path82.join(projectDir, "bun.lockb")))
|
|
81206
81488
|
return "bun";
|
|
81207
|
-
if (fs58.existsSync(
|
|
81489
|
+
if (fs58.existsSync(path82.join(projectDir, "pnpm-lock.yaml")))
|
|
81208
81490
|
return "pnpm";
|
|
81209
|
-
if (fs58.existsSync(
|
|
81491
|
+
if (fs58.existsSync(path82.join(projectDir, "yarn.lock")))
|
|
81210
81492
|
return "yarn";
|
|
81211
|
-
if (fs58.existsSync(
|
|
81493
|
+
if (fs58.existsSync(path82.join(projectDir, "package-lock.json")))
|
|
81212
81494
|
return "npm";
|
|
81213
81495
|
return "bun";
|
|
81214
81496
|
}
|
|
81215
81497
|
function detectTypecheckCommand(projectDir) {
|
|
81216
|
-
const pkgPath =
|
|
81498
|
+
const pkgPath = path82.join(projectDir, "package.json");
|
|
81217
81499
|
if (fs58.existsSync(pkgPath)) {
|
|
81218
81500
|
try {
|
|
81219
81501
|
const pkg = JSON.parse(fs58.readFileSync(pkgPath, "utf8"));
|
|
@@ -81230,8 +81512,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
81230
81512
|
...pkg.dependencies,
|
|
81231
81513
|
...pkg.devDependencies
|
|
81232
81514
|
};
|
|
81233
|
-
if (!deps?.typescript && !fs58.existsSync(
|
|
81234
|
-
const hasTSMarkers = deps?.typescript || fs58.existsSync(
|
|
81515
|
+
if (!deps?.typescript && !fs58.existsSync(path82.join(projectDir, "tsconfig.json"))) {}
|
|
81516
|
+
const hasTSMarkers = deps?.typescript || fs58.existsSync(path82.join(projectDir, "tsconfig.json"));
|
|
81235
81517
|
if (hasTSMarkers) {
|
|
81236
81518
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
81237
81519
|
}
|
|
@@ -81239,13 +81521,13 @@ function detectTypecheckCommand(projectDir) {
|
|
|
81239
81521
|
return null;
|
|
81240
81522
|
}
|
|
81241
81523
|
}
|
|
81242
|
-
if (fs58.existsSync(
|
|
81524
|
+
if (fs58.existsSync(path82.join(projectDir, "go.mod"))) {
|
|
81243
81525
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
81244
81526
|
}
|
|
81245
|
-
if (fs58.existsSync(
|
|
81527
|
+
if (fs58.existsSync(path82.join(projectDir, "Cargo.toml"))) {
|
|
81246
81528
|
return { command: ["cargo", "check"], language: "rust" };
|
|
81247
81529
|
}
|
|
81248
|
-
if (fs58.existsSync(
|
|
81530
|
+
if (fs58.existsSync(path82.join(projectDir, "pyproject.toml")) || fs58.existsSync(path82.join(projectDir, "requirements.txt")) || fs58.existsSync(path82.join(projectDir, "setup.py"))) {
|
|
81249
81531
|
return { command: null, language: "python" };
|
|
81250
81532
|
}
|
|
81251
81533
|
try {
|
|
@@ -81322,17 +81604,17 @@ init_schema();
|
|
|
81322
81604
|
init_state();
|
|
81323
81605
|
init_logger();
|
|
81324
81606
|
import { appendFile as appendFile7, mkdir as mkdir15 } from "node:fs/promises";
|
|
81325
|
-
import * as
|
|
81607
|
+
import * as path84 from "node:path";
|
|
81326
81608
|
|
|
81327
81609
|
// src/hooks/knowledge-application.ts
|
|
81328
81610
|
init_logger();
|
|
81329
81611
|
init_knowledge_store();
|
|
81330
81612
|
var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
|
|
81331
|
-
import { existsSync as
|
|
81613
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
81332
81614
|
import { appendFile as appendFile6, mkdir as mkdir14, readFile as readFile13 } from "node:fs/promises";
|
|
81333
|
-
import * as
|
|
81615
|
+
import * as path83 from "node:path";
|
|
81334
81616
|
function resolveApplicationLogPath(directory) {
|
|
81335
|
-
return
|
|
81617
|
+
return path83.join(directory, ".swarm", "knowledge-application.jsonl");
|
|
81336
81618
|
}
|
|
81337
81619
|
var ACK_PATTERN = /KNOWLEDGE_(APPLIED|IGNORED|VIOLATED)\s*:\s*([0-9a-fA-F-]{8,64})(?:\s+reason\s*=\s*([^\n\r]+?))?(?=$|[\n\r]|\s+KNOWLEDGE_)/g;
|
|
81338
81620
|
function parseAcknowledgments(text) {
|
|
@@ -81350,7 +81632,7 @@ function parseAcknowledgments(text) {
|
|
|
81350
81632
|
}
|
|
81351
81633
|
async function appendAudit(directory, record3) {
|
|
81352
81634
|
const filePath = resolveApplicationLogPath(directory);
|
|
81353
|
-
await mkdir14(
|
|
81635
|
+
await mkdir14(path83.dirname(filePath), { recursive: true });
|
|
81354
81636
|
await appendFile6(filePath, `${JSON.stringify(record3)}
|
|
81355
81637
|
`, "utf-8");
|
|
81356
81638
|
}
|
|
@@ -81394,7 +81676,7 @@ async function bumpCountersBatch(directory, bumps) {
|
|
|
81394
81676
|
if (applyOne(swarm))
|
|
81395
81677
|
await rewriteKnowledge(swarmPath, swarm);
|
|
81396
81678
|
const hivePath = resolveHiveKnowledgePath();
|
|
81397
|
-
if (
|
|
81679
|
+
if (existsSync45(hivePath)) {
|
|
81398
81680
|
const hive = await readKnowledge(hivePath);
|
|
81399
81681
|
if (applyOne(hive))
|
|
81400
81682
|
await rewriteKnowledge(hivePath, hive);
|
|
@@ -81516,8 +81798,8 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
|
|
|
81516
81798
|
}).catch(() => {});
|
|
81517
81799
|
}
|
|
81518
81800
|
async function writeWarnEvent(directory, record3) {
|
|
81519
|
-
const filePath =
|
|
81520
|
-
await mkdir15(
|
|
81801
|
+
const filePath = path84.join(directory, ".swarm", "events.jsonl");
|
|
81802
|
+
await mkdir15(path84.dirname(filePath), { recursive: true });
|
|
81521
81803
|
await appendFile7(filePath, `${JSON.stringify(record3)}
|
|
81522
81804
|
`, "utf-8");
|
|
81523
81805
|
}
|
|
@@ -82018,7 +82300,7 @@ init_scope_persistence();
|
|
|
82018
82300
|
init_state();
|
|
82019
82301
|
init_delegation_gate();
|
|
82020
82302
|
init_normalize_tool_name();
|
|
82021
|
-
import * as
|
|
82303
|
+
import * as path86 from "node:path";
|
|
82022
82304
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
82023
82305
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
82024
82306
|
const enabled = config3.enabled ?? true;
|
|
@@ -82076,13 +82358,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
82076
82358
|
}
|
|
82077
82359
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
82078
82360
|
const dir = directory ?? process.cwd();
|
|
82079
|
-
const resolvedFile =
|
|
82361
|
+
const resolvedFile = path86.resolve(dir, filePath);
|
|
82080
82362
|
return scopeEntries.some((scope) => {
|
|
82081
|
-
const resolvedScope =
|
|
82363
|
+
const resolvedScope = path86.resolve(dir, scope);
|
|
82082
82364
|
if (resolvedFile === resolvedScope)
|
|
82083
82365
|
return true;
|
|
82084
|
-
const rel =
|
|
82085
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
82366
|
+
const rel = path86.relative(resolvedScope, resolvedFile);
|
|
82367
|
+
return rel.length > 0 && !rel.startsWith("..") && !path86.isAbsolute(rel);
|
|
82086
82368
|
});
|
|
82087
82369
|
}
|
|
82088
82370
|
|
|
@@ -82134,7 +82416,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
82134
82416
|
|
|
82135
82417
|
// src/hooks/slop-detector.ts
|
|
82136
82418
|
import * as fs61 from "node:fs";
|
|
82137
|
-
import * as
|
|
82419
|
+
import * as path87 from "node:path";
|
|
82138
82420
|
var WRITE_EDIT_TOOLS = new Set([
|
|
82139
82421
|
"write",
|
|
82140
82422
|
"edit",
|
|
@@ -82184,7 +82466,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
82184
82466
|
break;
|
|
82185
82467
|
if (entry.isSymbolicLink())
|
|
82186
82468
|
continue;
|
|
82187
|
-
const full =
|
|
82469
|
+
const full = path87.join(dir, entry.name);
|
|
82188
82470
|
if (entry.isDirectory()) {
|
|
82189
82471
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
82190
82472
|
continue;
|
|
@@ -82199,7 +82481,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
82199
82481
|
return results;
|
|
82200
82482
|
}
|
|
82201
82483
|
function checkDeadExports(content, projectDir, startTime) {
|
|
82202
|
-
const hasPackageJson = fs61.existsSync(
|
|
82484
|
+
const hasPackageJson = fs61.existsSync(path87.join(projectDir, "package.json"));
|
|
82203
82485
|
if (!hasPackageJson)
|
|
82204
82486
|
return null;
|
|
82205
82487
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -82313,14 +82595,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
|
|
|
82313
82595
|
for (const utilDir of utilityDirs) {
|
|
82314
82596
|
if (Date.now() > deadline)
|
|
82315
82597
|
break;
|
|
82316
|
-
const utilPath =
|
|
82598
|
+
const utilPath = path87.join(projectDir, utilDir);
|
|
82317
82599
|
if (!fs61.existsSync(utilPath))
|
|
82318
82600
|
continue;
|
|
82319
82601
|
const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
|
|
82320
82602
|
for (const file3 of files) {
|
|
82321
82603
|
if (Date.now() > deadline)
|
|
82322
82604
|
break;
|
|
82323
|
-
if (targetFile &&
|
|
82605
|
+
if (targetFile && path87.resolve(file3) === path87.resolve(targetFile))
|
|
82324
82606
|
continue;
|
|
82325
82607
|
try {
|
|
82326
82608
|
const text = fs61.readFileSync(file3, "utf-8");
|
|
@@ -82458,14 +82740,14 @@ function createSteeringConsumedHook(directory) {
|
|
|
82458
82740
|
// src/hooks/trajectory-logger.ts
|
|
82459
82741
|
init_manager2();
|
|
82460
82742
|
import * as fs64 from "node:fs/promises";
|
|
82461
|
-
import * as
|
|
82743
|
+
import * as path89 from "node:path";
|
|
82462
82744
|
|
|
82463
82745
|
// src/prm/trajectory-store.ts
|
|
82464
82746
|
init_utils2();
|
|
82465
82747
|
import * as fs63 from "node:fs/promises";
|
|
82466
|
-
import * as
|
|
82748
|
+
import * as path88 from "node:path";
|
|
82467
82749
|
function getTrajectoryPath(sessionId, directory) {
|
|
82468
|
-
const relativePath =
|
|
82750
|
+
const relativePath = path88.join("trajectories", `${sessionId}.jsonl`);
|
|
82469
82751
|
return validateSwarmPath(directory, relativePath);
|
|
82470
82752
|
}
|
|
82471
82753
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -82484,7 +82766,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
|
|
|
82484
82766
|
_inMemoryTrajectoryCache.set(sessionId, cached3);
|
|
82485
82767
|
}
|
|
82486
82768
|
const trajectoryPath = getTrajectoryPath(sessionId, directory);
|
|
82487
|
-
await fs63.mkdir(
|
|
82769
|
+
await fs63.mkdir(path88.dirname(trajectoryPath), { recursive: true });
|
|
82488
82770
|
const line = `${JSON.stringify(entry)}
|
|
82489
82771
|
`;
|
|
82490
82772
|
await fs63.appendFile(trajectoryPath, line, "utf-8");
|
|
@@ -82523,7 +82805,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
82523
82805
|
for (const entry of entries) {
|
|
82524
82806
|
if (!entry.isFile())
|
|
82525
82807
|
continue;
|
|
82526
|
-
const filePath =
|
|
82808
|
+
const filePath = path88.join(dirPath, entry.name);
|
|
82527
82809
|
try {
|
|
82528
82810
|
const stat8 = await fs63.stat(filePath);
|
|
82529
82811
|
if (now - stat8.mtimeMs > cutoffMs) {
|
|
@@ -82715,10 +82997,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
|
|
|
82715
82997
|
elapsed_ms
|
|
82716
82998
|
};
|
|
82717
82999
|
const sanitized = sanitizeTaskId2(taskId);
|
|
82718
|
-
const relativePath =
|
|
83000
|
+
const relativePath = path89.join("evidence", sanitized, "trajectory.jsonl");
|
|
82719
83001
|
const trajectoryPath = validateSwarmPath(_directory, relativePath);
|
|
82720
83002
|
try {
|
|
82721
|
-
await fs64.mkdir(
|
|
83003
|
+
await fs64.mkdir(path89.dirname(trajectoryPath), { recursive: true });
|
|
82722
83004
|
const line = `${JSON.stringify(entry)}
|
|
82723
83005
|
`;
|
|
82724
83006
|
await fs64.appendFile(trajectoryPath, line, "utf-8");
|
|
@@ -83269,16 +83551,16 @@ init_telemetry();
|
|
|
83269
83551
|
|
|
83270
83552
|
// src/prm/replay.ts
|
|
83271
83553
|
import { promises as fs65 } from "node:fs";
|
|
83272
|
-
import
|
|
83554
|
+
import path90 from "node:path";
|
|
83273
83555
|
function isPathSafe2(targetPath, basePath) {
|
|
83274
|
-
const resolvedTarget =
|
|
83275
|
-
const resolvedBase =
|
|
83276
|
-
const rel =
|
|
83277
|
-
return !rel.startsWith("..") && !
|
|
83556
|
+
const resolvedTarget = path90.resolve(targetPath);
|
|
83557
|
+
const resolvedBase = path90.resolve(basePath);
|
|
83558
|
+
const rel = path90.relative(resolvedBase, resolvedTarget);
|
|
83559
|
+
return !rel.startsWith("..") && !path90.isAbsolute(rel);
|
|
83278
83560
|
}
|
|
83279
83561
|
function isWithinReplaysDir(targetPath) {
|
|
83280
|
-
const resolved =
|
|
83281
|
-
const parts2 = resolved.split(
|
|
83562
|
+
const resolved = path90.resolve(targetPath);
|
|
83563
|
+
const parts2 = resolved.split(path90.sep);
|
|
83282
83564
|
for (let i2 = 0;i2 < parts2.length - 1; i2++) {
|
|
83283
83565
|
if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
|
|
83284
83566
|
return true;
|
|
@@ -83291,10 +83573,10 @@ function sanitizeFilename(input) {
|
|
|
83291
83573
|
}
|
|
83292
83574
|
async function startReplayRecording(sessionID, directory) {
|
|
83293
83575
|
try {
|
|
83294
|
-
const replayDir =
|
|
83576
|
+
const replayDir = path90.join(directory, ".swarm", "replays");
|
|
83295
83577
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
83296
83578
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
83297
|
-
const filepath =
|
|
83579
|
+
const filepath = path90.join(replayDir, filename);
|
|
83298
83580
|
if (!isPathSafe2(filepath, replayDir)) {
|
|
83299
83581
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
83300
83582
|
return null;
|
|
@@ -83668,7 +83950,7 @@ init_telemetry();
|
|
|
83668
83950
|
init_dist();
|
|
83669
83951
|
init_create_tool();
|
|
83670
83952
|
import * as fs66 from "node:fs";
|
|
83671
|
-
import * as
|
|
83953
|
+
import * as path91 from "node:path";
|
|
83672
83954
|
init_path_security();
|
|
83673
83955
|
var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
83674
83956
|
function containsWindowsAttacks2(str) {
|
|
@@ -83685,14 +83967,14 @@ function containsWindowsAttacks2(str) {
|
|
|
83685
83967
|
}
|
|
83686
83968
|
function isPathInWorkspace2(filePath, workspace) {
|
|
83687
83969
|
try {
|
|
83688
|
-
const resolvedPath =
|
|
83970
|
+
const resolvedPath = path91.resolve(workspace, filePath);
|
|
83689
83971
|
if (!fs66.existsSync(resolvedPath)) {
|
|
83690
83972
|
return true;
|
|
83691
83973
|
}
|
|
83692
83974
|
const realWorkspace = fs66.realpathSync(workspace);
|
|
83693
83975
|
const realResolvedPath = fs66.realpathSync(resolvedPath);
|
|
83694
|
-
const relativePath =
|
|
83695
|
-
if (relativePath.startsWith("..") ||
|
|
83976
|
+
const relativePath = path91.relative(realWorkspace, realResolvedPath);
|
|
83977
|
+
if (relativePath.startsWith("..") || path91.isAbsolute(relativePath)) {
|
|
83696
83978
|
return false;
|
|
83697
83979
|
}
|
|
83698
83980
|
return true;
|
|
@@ -83701,7 +83983,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
83701
83983
|
}
|
|
83702
83984
|
}
|
|
83703
83985
|
function processFile2(file3, cwd, exportedOnly) {
|
|
83704
|
-
const ext =
|
|
83986
|
+
const ext = path91.extname(file3);
|
|
83705
83987
|
if (containsControlChars(file3)) {
|
|
83706
83988
|
return {
|
|
83707
83989
|
file: file3,
|
|
@@ -83734,7 +84016,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
83734
84016
|
errorType: "path-outside-workspace"
|
|
83735
84017
|
};
|
|
83736
84018
|
}
|
|
83737
|
-
const fullPath =
|
|
84019
|
+
const fullPath = path91.join(cwd, file3);
|
|
83738
84020
|
if (!fs66.existsSync(fullPath)) {
|
|
83739
84021
|
return {
|
|
83740
84022
|
file: file3,
|
|
@@ -84026,15 +84308,15 @@ init_task_id();
|
|
|
84026
84308
|
init_create_tool();
|
|
84027
84309
|
init_resolve_working_directory();
|
|
84028
84310
|
import * as fs67 from "node:fs";
|
|
84029
|
-
import * as
|
|
84311
|
+
import * as path92 from "node:path";
|
|
84030
84312
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
84031
84313
|
function isValidTaskId3(taskId) {
|
|
84032
84314
|
return isStrictTaskId(taskId);
|
|
84033
84315
|
}
|
|
84034
84316
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
84035
|
-
const normalizedWorkspace =
|
|
84036
|
-
const swarmPath =
|
|
84037
|
-
const normalizedPath =
|
|
84317
|
+
const normalizedWorkspace = path92.resolve(workspaceRoot);
|
|
84318
|
+
const swarmPath = path92.join(normalizedWorkspace, ".swarm", "evidence");
|
|
84319
|
+
const normalizedPath = path92.resolve(filePath);
|
|
84038
84320
|
return normalizedPath.startsWith(swarmPath);
|
|
84039
84321
|
}
|
|
84040
84322
|
function readEvidenceFile(evidencePath) {
|
|
@@ -84115,7 +84397,7 @@ var check_gate_status = createSwarmTool({
|
|
|
84115
84397
|
};
|
|
84116
84398
|
return JSON.stringify(errorResult, null, 2);
|
|
84117
84399
|
}
|
|
84118
|
-
const evidencePath =
|
|
84400
|
+
const evidencePath = path92.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
84119
84401
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
84120
84402
|
const errorResult = {
|
|
84121
84403
|
taskId: taskIdInput,
|
|
@@ -84212,7 +84494,7 @@ init_state();
|
|
|
84212
84494
|
init_create_tool();
|
|
84213
84495
|
init_resolve_working_directory();
|
|
84214
84496
|
import * as fs68 from "node:fs";
|
|
84215
|
-
import * as
|
|
84497
|
+
import * as path93 from "node:path";
|
|
84216
84498
|
function extractMatches(regex, text) {
|
|
84217
84499
|
return Array.from(text.matchAll(regex));
|
|
84218
84500
|
}
|
|
@@ -84364,10 +84646,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84364
84646
|
let hasFileReadFailure = false;
|
|
84365
84647
|
for (const filePath of fileTargets) {
|
|
84366
84648
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
84367
|
-
const resolvedPath =
|
|
84368
|
-
const projectRoot =
|
|
84369
|
-
const relative20 =
|
|
84370
|
-
const withinProject = relative20 === "" || !relative20.startsWith("..") && !
|
|
84649
|
+
const resolvedPath = path93.resolve(directory, normalizedPath);
|
|
84650
|
+
const projectRoot = path93.resolve(directory);
|
|
84651
|
+
const relative20 = path93.relative(projectRoot, resolvedPath);
|
|
84652
|
+
const withinProject = relative20 === "" || !relative20.startsWith("..") && !path93.isAbsolute(relative20);
|
|
84371
84653
|
if (!withinProject) {
|
|
84372
84654
|
blockedTasks.push({
|
|
84373
84655
|
task_id: task.id,
|
|
@@ -84422,8 +84704,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84422
84704
|
blockedTasks
|
|
84423
84705
|
};
|
|
84424
84706
|
try {
|
|
84425
|
-
const evidenceDir =
|
|
84426
|
-
const evidencePath =
|
|
84707
|
+
const evidenceDir = path93.join(directory, ".swarm", "evidence", `${phase}`);
|
|
84708
|
+
const evidencePath = path93.join(evidenceDir, "completion-verify.json");
|
|
84427
84709
|
fs68.mkdirSync(evidenceDir, { recursive: true });
|
|
84428
84710
|
const evidenceBundle = {
|
|
84429
84711
|
schema_version: "1.0.0",
|
|
@@ -84500,11 +84782,11 @@ var completion_verify = createSwarmTool({
|
|
|
84500
84782
|
// src/tools/complexity-hotspots.ts
|
|
84501
84783
|
init_zod();
|
|
84502
84784
|
import * as fs70 from "node:fs";
|
|
84503
|
-
import * as
|
|
84785
|
+
import * as path95 from "node:path";
|
|
84504
84786
|
|
|
84505
84787
|
// src/quality/metrics.ts
|
|
84506
84788
|
import * as fs69 from "node:fs";
|
|
84507
|
-
import * as
|
|
84789
|
+
import * as path94 from "node:path";
|
|
84508
84790
|
var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
|
|
84509
84791
|
var MIN_DUPLICATION_LINES = 10;
|
|
84510
84792
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -84556,7 +84838,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
84556
84838
|
let totalComplexity = 0;
|
|
84557
84839
|
const analyzedFiles = [];
|
|
84558
84840
|
for (const file3 of files) {
|
|
84559
|
-
const fullPath =
|
|
84841
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84560
84842
|
if (!fs69.existsSync(fullPath)) {
|
|
84561
84843
|
continue;
|
|
84562
84844
|
}
|
|
@@ -84679,7 +84961,7 @@ function countGoExports(content) {
|
|
|
84679
84961
|
function getExportCountForFile(filePath) {
|
|
84680
84962
|
try {
|
|
84681
84963
|
const content = fs69.readFileSync(filePath, "utf-8");
|
|
84682
|
-
const ext =
|
|
84964
|
+
const ext = path94.extname(filePath).toLowerCase();
|
|
84683
84965
|
switch (ext) {
|
|
84684
84966
|
case ".ts":
|
|
84685
84967
|
case ".tsx":
|
|
@@ -84705,7 +84987,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
84705
84987
|
let totalExports = 0;
|
|
84706
84988
|
const analyzedFiles = [];
|
|
84707
84989
|
for (const file3 of files) {
|
|
84708
|
-
const fullPath =
|
|
84990
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84709
84991
|
if (!fs69.existsSync(fullPath)) {
|
|
84710
84992
|
continue;
|
|
84711
84993
|
}
|
|
@@ -84739,7 +85021,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
84739
85021
|
let duplicateLines = 0;
|
|
84740
85022
|
const analyzedFiles = [];
|
|
84741
85023
|
for (const file3 of files) {
|
|
84742
|
-
const fullPath =
|
|
85024
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84743
85025
|
if (!fs69.existsSync(fullPath)) {
|
|
84744
85026
|
continue;
|
|
84745
85027
|
}
|
|
@@ -84772,8 +85054,8 @@ function countCodeLines(content) {
|
|
|
84772
85054
|
return lines.length;
|
|
84773
85055
|
}
|
|
84774
85056
|
function isTestFile(filePath) {
|
|
84775
|
-
const basename12 =
|
|
84776
|
-
const _ext =
|
|
85057
|
+
const basename12 = path94.basename(filePath);
|
|
85058
|
+
const _ext = path94.extname(filePath).toLowerCase();
|
|
84777
85059
|
const testPatterns = [
|
|
84778
85060
|
".test.",
|
|
84779
85061
|
".spec.",
|
|
@@ -84854,8 +85136,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
84854
85136
|
}
|
|
84855
85137
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
84856
85138
|
}
|
|
84857
|
-
function matchesGlobSegment(
|
|
84858
|
-
const normalizedPath =
|
|
85139
|
+
function matchesGlobSegment(path95, glob) {
|
|
85140
|
+
const normalizedPath = path95.replace(/\\/g, "/");
|
|
84859
85141
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
84860
85142
|
if (normalizedPath.includes("//")) {
|
|
84861
85143
|
return false;
|
|
@@ -84886,8 +85168,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
84886
85168
|
function hasGlobstar(glob) {
|
|
84887
85169
|
return glob.includes("**");
|
|
84888
85170
|
}
|
|
84889
|
-
function globMatches(
|
|
84890
|
-
const normalizedPath =
|
|
85171
|
+
function globMatches(path95, glob) {
|
|
85172
|
+
const normalizedPath = path95.replace(/\\/g, "/");
|
|
84891
85173
|
if (!glob || glob === "") {
|
|
84892
85174
|
if (normalizedPath.includes("//")) {
|
|
84893
85175
|
return false;
|
|
@@ -84923,7 +85205,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
84923
85205
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
84924
85206
|
let testLines = 0;
|
|
84925
85207
|
let codeLines = 0;
|
|
84926
|
-
const srcDir =
|
|
85208
|
+
const srcDir = path94.join(workingDir, "src");
|
|
84927
85209
|
if (fs69.existsSync(srcDir)) {
|
|
84928
85210
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
84929
85211
|
codeLines += lines;
|
|
@@ -84931,14 +85213,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
84931
85213
|
}
|
|
84932
85214
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
84933
85215
|
for (const dir of possibleSrcDirs) {
|
|
84934
|
-
const dirPath =
|
|
85216
|
+
const dirPath = path94.join(workingDir, dir);
|
|
84935
85217
|
if (fs69.existsSync(dirPath)) {
|
|
84936
85218
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
84937
85219
|
codeLines += lines;
|
|
84938
85220
|
});
|
|
84939
85221
|
}
|
|
84940
85222
|
}
|
|
84941
|
-
const testsDir =
|
|
85223
|
+
const testsDir = path94.join(workingDir, "tests");
|
|
84942
85224
|
if (fs69.existsSync(testsDir)) {
|
|
84943
85225
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
84944
85226
|
testLines += lines;
|
|
@@ -84946,7 +85228,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
84946
85228
|
}
|
|
84947
85229
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
84948
85230
|
for (const dir of possibleTestDirs) {
|
|
84949
|
-
const dirPath =
|
|
85231
|
+
const dirPath = path94.join(workingDir, dir);
|
|
84950
85232
|
if (fs69.existsSync(dirPath) && dirPath !== testsDir) {
|
|
84951
85233
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
84952
85234
|
testLines += lines;
|
|
@@ -84961,7 +85243,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
84961
85243
|
try {
|
|
84962
85244
|
const entries = fs69.readdirSync(dirPath, { withFileTypes: true });
|
|
84963
85245
|
for (const entry of entries) {
|
|
84964
|
-
const fullPath =
|
|
85246
|
+
const fullPath = path94.join(dirPath, entry.name);
|
|
84965
85247
|
if (entry.isDirectory()) {
|
|
84966
85248
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
84967
85249
|
continue;
|
|
@@ -84969,7 +85251,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
84969
85251
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
84970
85252
|
} else if (entry.isFile()) {
|
|
84971
85253
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
84972
|
-
const ext =
|
|
85254
|
+
const ext = path94.extname(entry.name).toLowerCase();
|
|
84973
85255
|
const validExts = [
|
|
84974
85256
|
".ts",
|
|
84975
85257
|
".tsx",
|
|
@@ -85220,7 +85502,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85220
85502
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
85221
85503
|
const filteredChurn = new Map;
|
|
85222
85504
|
for (const [file3, count] of churnMap) {
|
|
85223
|
-
const ext =
|
|
85505
|
+
const ext = path95.extname(file3).toLowerCase();
|
|
85224
85506
|
if (extSet.has(ext)) {
|
|
85225
85507
|
filteredChurn.set(file3, count);
|
|
85226
85508
|
}
|
|
@@ -85231,7 +85513,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85231
85513
|
for (const [file3, churnCount] of filteredChurn) {
|
|
85232
85514
|
let fullPath = file3;
|
|
85233
85515
|
if (!fs70.existsSync(fullPath)) {
|
|
85234
|
-
fullPath =
|
|
85516
|
+
fullPath = path95.join(cwd, file3);
|
|
85235
85517
|
}
|
|
85236
85518
|
const complexity = getComplexityForFile2(fullPath);
|
|
85237
85519
|
if (complexity !== null) {
|
|
@@ -85400,12 +85682,12 @@ ${body2}`);
|
|
|
85400
85682
|
// src/council/council-evidence-writer.ts
|
|
85401
85683
|
import {
|
|
85402
85684
|
appendFileSync as appendFileSync9,
|
|
85403
|
-
existsSync as
|
|
85685
|
+
existsSync as existsSync51,
|
|
85404
85686
|
mkdirSync as mkdirSync22,
|
|
85405
|
-
readFileSync as
|
|
85687
|
+
readFileSync as readFileSync42,
|
|
85406
85688
|
writeFileSync as writeFileSync15
|
|
85407
85689
|
} from "node:fs";
|
|
85408
|
-
import { join as
|
|
85690
|
+
import { join as join81 } from "node:path";
|
|
85409
85691
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
85410
85692
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
85411
85693
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -85439,13 +85721,13 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85439
85721
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
85440
85722
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
85441
85723
|
}
|
|
85442
|
-
const dir =
|
|
85724
|
+
const dir = join81(workingDir, EVIDENCE_DIR2);
|
|
85443
85725
|
mkdirSync22(dir, { recursive: true });
|
|
85444
|
-
const filePath =
|
|
85726
|
+
const filePath = join81(dir, `${synthesis.taskId}.json`);
|
|
85445
85727
|
const existingRoot = Object.create(null);
|
|
85446
|
-
if (
|
|
85728
|
+
if (existsSync51(filePath)) {
|
|
85447
85729
|
try {
|
|
85448
|
-
const parsed = JSON.parse(
|
|
85730
|
+
const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
|
|
85449
85731
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
85450
85732
|
safeAssignOwnProps(existingRoot, parsed);
|
|
85451
85733
|
}
|
|
@@ -85475,7 +85757,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85475
85757
|
updated.required_gates = [];
|
|
85476
85758
|
writeFileSync15(filePath, JSON.stringify(updated, null, 2));
|
|
85477
85759
|
try {
|
|
85478
|
-
const councilDir =
|
|
85760
|
+
const councilDir = join81(workingDir, ".swarm", "council");
|
|
85479
85761
|
mkdirSync22(councilDir, { recursive: true });
|
|
85480
85762
|
const auditLine = JSON.stringify({
|
|
85481
85763
|
round: synthesis.roundNumber,
|
|
@@ -85483,7 +85765,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85483
85765
|
timestamp: synthesis.timestamp,
|
|
85484
85766
|
vetoedBy: synthesis.vetoedBy
|
|
85485
85767
|
});
|
|
85486
|
-
appendFileSync9(
|
|
85768
|
+
appendFileSync9(join81(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
85487
85769
|
`);
|
|
85488
85770
|
} catch (auditError) {
|
|
85489
85771
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -85805,25 +86087,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
85805
86087
|
}
|
|
85806
86088
|
|
|
85807
86089
|
// src/council/criteria-store.ts
|
|
85808
|
-
import { existsSync as
|
|
85809
|
-
import { join as
|
|
86090
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync23, readFileSync as readFileSync43, writeFileSync as writeFileSync16 } from "node:fs";
|
|
86091
|
+
import { join as join82 } from "node:path";
|
|
85810
86092
|
var COUNCIL_DIR = ".swarm/council";
|
|
85811
86093
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
85812
|
-
const dir =
|
|
86094
|
+
const dir = join82(workingDir, COUNCIL_DIR);
|
|
85813
86095
|
mkdirSync23(dir, { recursive: true });
|
|
85814
86096
|
const payload = {
|
|
85815
86097
|
taskId,
|
|
85816
86098
|
criteria,
|
|
85817
86099
|
declaredAt: new Date().toISOString()
|
|
85818
86100
|
};
|
|
85819
|
-
writeFileSync16(
|
|
86101
|
+
writeFileSync16(join82(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
85820
86102
|
}
|
|
85821
86103
|
function readCriteria(workingDir, taskId) {
|
|
85822
|
-
const filePath =
|
|
85823
|
-
if (!
|
|
86104
|
+
const filePath = join82(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
86105
|
+
if (!existsSync52(filePath))
|
|
85824
86106
|
return null;
|
|
85825
86107
|
try {
|
|
85826
|
-
const parsed = JSON.parse(
|
|
86108
|
+
const parsed = JSON.parse(readFileSync43(filePath, "utf-8"));
|
|
85827
86109
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
85828
86110
|
return parsed;
|
|
85829
86111
|
}
|
|
@@ -85972,7 +86254,7 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
85972
86254
|
init_zod();
|
|
85973
86255
|
init_loader();
|
|
85974
86256
|
import * as fs71 from "node:fs";
|
|
85975
|
-
import * as
|
|
86257
|
+
import * as path96 from "node:path";
|
|
85976
86258
|
|
|
85977
86259
|
// src/council/general-council-advisory.ts
|
|
85978
86260
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -86400,10 +86682,10 @@ var convene_general_council = createSwarmTool({
|
|
|
86400
86682
|
const round1 = input.round1Responses;
|
|
86401
86683
|
const round2 = input.round2Responses ?? [];
|
|
86402
86684
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
86403
|
-
const evidenceDir =
|
|
86685
|
+
const evidenceDir = path96.join(workingDir, ".swarm", "council", "general");
|
|
86404
86686
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
86405
86687
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
86406
|
-
const evidencePath =
|
|
86688
|
+
const evidencePath = path96.join(evidenceDir, evidenceFile);
|
|
86407
86689
|
try {
|
|
86408
86690
|
await fs71.promises.mkdir(evidenceDir, { recursive: true });
|
|
86409
86691
|
await fs71.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
@@ -86648,7 +86930,7 @@ init_state();
|
|
|
86648
86930
|
init_task_id();
|
|
86649
86931
|
init_create_tool();
|
|
86650
86932
|
import * as fs72 from "node:fs";
|
|
86651
|
-
import * as
|
|
86933
|
+
import * as path97 from "node:path";
|
|
86652
86934
|
function validateTaskIdFormat2(taskId) {
|
|
86653
86935
|
return validateTaskIdFormat(taskId);
|
|
86654
86936
|
}
|
|
@@ -86722,8 +87004,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86722
87004
|
};
|
|
86723
87005
|
}
|
|
86724
87006
|
}
|
|
86725
|
-
normalizedDir =
|
|
86726
|
-
const pathParts = normalizedDir.split(
|
|
87007
|
+
normalizedDir = path97.normalize(args2.working_directory);
|
|
87008
|
+
const pathParts = normalizedDir.split(path97.sep);
|
|
86727
87009
|
if (pathParts.includes("..")) {
|
|
86728
87010
|
return {
|
|
86729
87011
|
success: false,
|
|
@@ -86733,10 +87015,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86733
87015
|
]
|
|
86734
87016
|
};
|
|
86735
87017
|
}
|
|
86736
|
-
const resolvedDir =
|
|
87018
|
+
const resolvedDir = path97.resolve(normalizedDir);
|
|
86737
87019
|
try {
|
|
86738
87020
|
const realPath = fs72.realpathSync(resolvedDir);
|
|
86739
|
-
const planPath2 =
|
|
87021
|
+
const planPath2 = path97.join(realPath, ".swarm", "plan.json");
|
|
86740
87022
|
if (!fs72.existsSync(planPath2)) {
|
|
86741
87023
|
return {
|
|
86742
87024
|
success: false,
|
|
@@ -86760,7 +87042,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86760
87042
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
86761
87043
|
}
|
|
86762
87044
|
const directory = normalizedDir || fallbackDir;
|
|
86763
|
-
const planPath =
|
|
87045
|
+
const planPath = path97.resolve(directory, ".swarm", "plan.json");
|
|
86764
87046
|
if (!fs72.existsSync(planPath)) {
|
|
86765
87047
|
return {
|
|
86766
87048
|
success: false,
|
|
@@ -86800,8 +87082,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86800
87082
|
const normalizeErrors = [];
|
|
86801
87083
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
86802
87084
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
86803
|
-
if (
|
|
86804
|
-
const relativePath =
|
|
87085
|
+
if (path97.isAbsolute(file3)) {
|
|
87086
|
+
const relativePath = path97.relative(dir, file3).replace(/\\/g, "/");
|
|
86805
87087
|
if (relativePath.startsWith("..")) {
|
|
86806
87088
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
86807
87089
|
return file3;
|
|
@@ -86862,7 +87144,7 @@ var declare_scope = createSwarmTool({
|
|
|
86862
87144
|
init_zod();
|
|
86863
87145
|
import * as child_process7 from "node:child_process";
|
|
86864
87146
|
import * as fs73 from "node:fs";
|
|
86865
|
-
import * as
|
|
87147
|
+
import * as path98 from "node:path";
|
|
86866
87148
|
init_create_tool();
|
|
86867
87149
|
var MAX_DIFF_LINES = 500;
|
|
86868
87150
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -86891,20 +87173,20 @@ function validateBase(base) {
|
|
|
86891
87173
|
function validatePaths(paths) {
|
|
86892
87174
|
if (!paths)
|
|
86893
87175
|
return null;
|
|
86894
|
-
for (const
|
|
86895
|
-
if (!
|
|
87176
|
+
for (const path99 of paths) {
|
|
87177
|
+
if (!path99 || path99.length === 0) {
|
|
86896
87178
|
return "empty path not allowed";
|
|
86897
87179
|
}
|
|
86898
|
-
if (
|
|
87180
|
+
if (path99.length > MAX_PATH_LENGTH) {
|
|
86899
87181
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
86900
87182
|
}
|
|
86901
|
-
if (SHELL_METACHARACTERS2.test(
|
|
87183
|
+
if (SHELL_METACHARACTERS2.test(path99)) {
|
|
86902
87184
|
return "path contains shell metacharacters";
|
|
86903
87185
|
}
|
|
86904
|
-
if (
|
|
87186
|
+
if (path99.startsWith("-")) {
|
|
86905
87187
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
86906
87188
|
}
|
|
86907
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
87189
|
+
if (CONTROL_CHAR_PATTERN2.test(path99)) {
|
|
86908
87190
|
return "path contains control characters";
|
|
86909
87191
|
}
|
|
86910
87192
|
}
|
|
@@ -87012,8 +87294,8 @@ var diff = createSwarmTool({
|
|
|
87012
87294
|
if (parts2.length >= 3) {
|
|
87013
87295
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
87014
87296
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
87015
|
-
const
|
|
87016
|
-
files.push({ path:
|
|
87297
|
+
const path99 = parts2[2];
|
|
87298
|
+
files.push({ path: path99, additions, deletions });
|
|
87017
87299
|
}
|
|
87018
87300
|
}
|
|
87019
87301
|
const contractChanges = [];
|
|
@@ -87053,7 +87335,7 @@ var diff = createSwarmTool({
|
|
|
87053
87335
|
} else if (base === "unstaged") {
|
|
87054
87336
|
const oldRef = `:${file3.path}`;
|
|
87055
87337
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
87056
|
-
newContent = fs73.readFileSync(
|
|
87338
|
+
newContent = fs73.readFileSync(path98.join(directory, file3.path), "utf-8");
|
|
87057
87339
|
} else {
|
|
87058
87340
|
const oldRef = `${base}:${file3.path}`;
|
|
87059
87341
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -87128,7 +87410,7 @@ var diff = createSwarmTool({
|
|
|
87128
87410
|
init_zod();
|
|
87129
87411
|
import * as child_process8 from "node:child_process";
|
|
87130
87412
|
import * as fs74 from "node:fs";
|
|
87131
|
-
import * as
|
|
87413
|
+
import * as path99 from "node:path";
|
|
87132
87414
|
init_create_tool();
|
|
87133
87415
|
var diff_summary = createSwarmTool({
|
|
87134
87416
|
description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
|
|
@@ -87176,7 +87458,7 @@ var diff_summary = createSwarmTool({
|
|
|
87176
87458
|
}
|
|
87177
87459
|
try {
|
|
87178
87460
|
let oldContent;
|
|
87179
|
-
const newContent = fs74.readFileSync(
|
|
87461
|
+
const newContent = fs74.readFileSync(path99.join(workingDir, filePath), "utf-8");
|
|
87180
87462
|
if (fileExistsInHead) {
|
|
87181
87463
|
oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
87182
87464
|
encoding: "utf-8",
|
|
@@ -87405,7 +87687,7 @@ init_zod();
|
|
|
87405
87687
|
init_create_tool();
|
|
87406
87688
|
init_path_security();
|
|
87407
87689
|
import * as fs75 from "node:fs";
|
|
87408
|
-
import * as
|
|
87690
|
+
import * as path100 from "node:path";
|
|
87409
87691
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
87410
87692
|
var MAX_EVIDENCE_FILES = 1000;
|
|
87411
87693
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -87432,9 +87714,9 @@ function validateRequiredTypes(input) {
|
|
|
87432
87714
|
return null;
|
|
87433
87715
|
}
|
|
87434
87716
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
87435
|
-
const normalizedCwd =
|
|
87436
|
-
const swarmPath =
|
|
87437
|
-
const normalizedPath =
|
|
87717
|
+
const normalizedCwd = path100.resolve(cwd);
|
|
87718
|
+
const swarmPath = path100.join(normalizedCwd, ".swarm");
|
|
87719
|
+
const normalizedPath = path100.resolve(filePath);
|
|
87438
87720
|
return normalizedPath.startsWith(swarmPath);
|
|
87439
87721
|
}
|
|
87440
87722
|
function parseCompletedTasks(planContent) {
|
|
@@ -87464,10 +87746,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
87464
87746
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
87465
87747
|
continue;
|
|
87466
87748
|
}
|
|
87467
|
-
const filePath =
|
|
87749
|
+
const filePath = path100.join(evidenceDir, filename);
|
|
87468
87750
|
try {
|
|
87469
|
-
const resolvedPath =
|
|
87470
|
-
const evidenceDirResolved =
|
|
87751
|
+
const resolvedPath = path100.resolve(filePath);
|
|
87752
|
+
const evidenceDirResolved = path100.resolve(evidenceDir);
|
|
87471
87753
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
87472
87754
|
continue;
|
|
87473
87755
|
}
|
|
@@ -87585,7 +87867,7 @@ var evidence_check = createSwarmTool({
|
|
|
87585
87867
|
return JSON.stringify(errorResult, null, 2);
|
|
87586
87868
|
}
|
|
87587
87869
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
87588
|
-
const planPath =
|
|
87870
|
+
const planPath = path100.join(cwd, PLAN_FILE);
|
|
87589
87871
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
87590
87872
|
const errorResult = {
|
|
87591
87873
|
error: "plan file path validation failed",
|
|
@@ -87617,7 +87899,7 @@ var evidence_check = createSwarmTool({
|
|
|
87617
87899
|
};
|
|
87618
87900
|
return JSON.stringify(result2, null, 2);
|
|
87619
87901
|
}
|
|
87620
|
-
const evidenceDir =
|
|
87902
|
+
const evidenceDir = path100.join(cwd, EVIDENCE_DIR3);
|
|
87621
87903
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
87622
87904
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
87623
87905
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -87635,7 +87917,7 @@ var evidence_check = createSwarmTool({
|
|
|
87635
87917
|
init_zod();
|
|
87636
87918
|
init_create_tool();
|
|
87637
87919
|
import * as fs76 from "node:fs";
|
|
87638
|
-
import * as
|
|
87920
|
+
import * as path101 from "node:path";
|
|
87639
87921
|
var EXT_MAP = {
|
|
87640
87922
|
python: ".py",
|
|
87641
87923
|
py: ".py",
|
|
@@ -87716,12 +87998,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
87716
87998
|
if (prefix) {
|
|
87717
87999
|
filename = `${prefix}_${filename}`;
|
|
87718
88000
|
}
|
|
87719
|
-
let filepath =
|
|
87720
|
-
const base =
|
|
87721
|
-
const ext =
|
|
88001
|
+
let filepath = path101.join(targetDir, filename);
|
|
88002
|
+
const base = path101.basename(filepath, path101.extname(filepath));
|
|
88003
|
+
const ext = path101.extname(filepath);
|
|
87722
88004
|
let counter = 1;
|
|
87723
88005
|
while (fs76.existsSync(filepath)) {
|
|
87724
|
-
filepath =
|
|
88006
|
+
filepath = path101.join(targetDir, `${base}_${counter}${ext}`);
|
|
87725
88007
|
counter++;
|
|
87726
88008
|
}
|
|
87727
88009
|
try {
|
|
@@ -87979,7 +88261,7 @@ init_zod();
|
|
|
87979
88261
|
init_create_tool();
|
|
87980
88262
|
init_path_security();
|
|
87981
88263
|
import * as fs77 from "node:fs";
|
|
87982
|
-
import * as
|
|
88264
|
+
import * as path102 from "node:path";
|
|
87983
88265
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
87984
88266
|
var MAX_SYMBOL_LENGTH = 256;
|
|
87985
88267
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -88027,7 +88309,7 @@ function validateSymbolInput(symbol3) {
|
|
|
88027
88309
|
return null;
|
|
88028
88310
|
}
|
|
88029
88311
|
function isBinaryFile2(filePath, buffer) {
|
|
88030
|
-
const ext =
|
|
88312
|
+
const ext = path102.extname(filePath).toLowerCase();
|
|
88031
88313
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
88032
88314
|
return false;
|
|
88033
88315
|
}
|
|
@@ -88051,15 +88333,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88051
88333
|
const imports = [];
|
|
88052
88334
|
let _resolvedTarget;
|
|
88053
88335
|
try {
|
|
88054
|
-
_resolvedTarget =
|
|
88336
|
+
_resolvedTarget = path102.resolve(targetFile);
|
|
88055
88337
|
} catch {
|
|
88056
88338
|
_resolvedTarget = targetFile;
|
|
88057
88339
|
}
|
|
88058
|
-
const targetBasename =
|
|
88340
|
+
const targetBasename = path102.basename(targetFile, path102.extname(targetFile));
|
|
88059
88341
|
const targetWithExt = targetFile;
|
|
88060
88342
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
88061
|
-
const normalizedTargetWithExt =
|
|
88062
|
-
const normalizedTargetWithoutExt =
|
|
88343
|
+
const normalizedTargetWithExt = path102.normalize(targetWithExt).replace(/\\/g, "/");
|
|
88344
|
+
const normalizedTargetWithoutExt = path102.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
88063
88345
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
88064
88346
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
88065
88347
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -88082,9 +88364,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88082
88364
|
}
|
|
88083
88365
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
88084
88366
|
let isMatch = false;
|
|
88085
|
-
const _targetDir =
|
|
88086
|
-
const targetExt =
|
|
88087
|
-
const targetBasenameNoExt =
|
|
88367
|
+
const _targetDir = path102.dirname(targetFile);
|
|
88368
|
+
const targetExt = path102.extname(targetFile);
|
|
88369
|
+
const targetBasenameNoExt = path102.basename(targetFile, targetExt);
|
|
88088
88370
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
88089
88371
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
88090
88372
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -88152,10 +88434,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88152
88434
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
88153
88435
|
for (const entry of entries) {
|
|
88154
88436
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
88155
|
-
stats.skippedDirs.push(
|
|
88437
|
+
stats.skippedDirs.push(path102.join(dir, entry));
|
|
88156
88438
|
continue;
|
|
88157
88439
|
}
|
|
88158
|
-
const fullPath =
|
|
88440
|
+
const fullPath = path102.join(dir, entry);
|
|
88159
88441
|
let stat8;
|
|
88160
88442
|
try {
|
|
88161
88443
|
stat8 = fs77.statSync(fullPath);
|
|
@@ -88169,7 +88451,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88169
88451
|
if (stat8.isDirectory()) {
|
|
88170
88452
|
findSourceFiles2(fullPath, files, stats);
|
|
88171
88453
|
} else if (stat8.isFile()) {
|
|
88172
|
-
const ext =
|
|
88454
|
+
const ext = path102.extname(fullPath).toLowerCase();
|
|
88173
88455
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
88174
88456
|
files.push(fullPath);
|
|
88175
88457
|
}
|
|
@@ -88226,7 +88508,7 @@ var imports = createSwarmTool({
|
|
|
88226
88508
|
return JSON.stringify(errorResult, null, 2);
|
|
88227
88509
|
}
|
|
88228
88510
|
try {
|
|
88229
|
-
const targetFile =
|
|
88511
|
+
const targetFile = path102.resolve(file3);
|
|
88230
88512
|
if (!fs77.existsSync(targetFile)) {
|
|
88231
88513
|
const errorResult = {
|
|
88232
88514
|
error: `target file not found: ${file3}`,
|
|
@@ -88248,7 +88530,7 @@ var imports = createSwarmTool({
|
|
|
88248
88530
|
};
|
|
88249
88531
|
return JSON.stringify(errorResult, null, 2);
|
|
88250
88532
|
}
|
|
88251
|
-
const baseDir =
|
|
88533
|
+
const baseDir = path102.dirname(targetFile);
|
|
88252
88534
|
const scanStats = {
|
|
88253
88535
|
skippedDirs: [],
|
|
88254
88536
|
skippedFiles: 0,
|
|
@@ -88539,7 +88821,7 @@ init_zod();
|
|
|
88539
88821
|
init_config();
|
|
88540
88822
|
init_knowledge_store();
|
|
88541
88823
|
init_create_tool();
|
|
88542
|
-
import { existsSync as
|
|
88824
|
+
import { existsSync as existsSync57 } from "node:fs";
|
|
88543
88825
|
var DEFAULT_LIMIT = 10;
|
|
88544
88826
|
var MAX_LESSON_LENGTH = 200;
|
|
88545
88827
|
var VALID_CATEGORIES3 = [
|
|
@@ -88609,14 +88891,14 @@ function validateLimit(limit) {
|
|
|
88609
88891
|
}
|
|
88610
88892
|
async function readSwarmKnowledge(directory) {
|
|
88611
88893
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
88612
|
-
if (!
|
|
88894
|
+
if (!existsSync57(swarmPath)) {
|
|
88613
88895
|
return [];
|
|
88614
88896
|
}
|
|
88615
88897
|
return readKnowledge(swarmPath);
|
|
88616
88898
|
}
|
|
88617
88899
|
async function readHiveKnowledge() {
|
|
88618
88900
|
const hivePath = resolveHiveKnowledgePath();
|
|
88619
|
-
if (!
|
|
88901
|
+
if (!existsSync57(hivePath)) {
|
|
88620
88902
|
return [];
|
|
88621
88903
|
}
|
|
88622
88904
|
return readKnowledge(hivePath);
|
|
@@ -88851,22 +89133,22 @@ init_schema();
|
|
|
88851
89133
|
init_qa_gate_profile();
|
|
88852
89134
|
init_manager2();
|
|
88853
89135
|
import * as fs82 from "node:fs";
|
|
88854
|
-
import * as
|
|
89136
|
+
import * as path107 from "node:path";
|
|
88855
89137
|
|
|
88856
89138
|
// src/full-auto/phase-approval.ts
|
|
88857
89139
|
init_utils2();
|
|
88858
89140
|
init_logger();
|
|
88859
89141
|
init_state2();
|
|
88860
89142
|
import * as fs78 from "node:fs";
|
|
88861
|
-
import * as
|
|
89143
|
+
import * as path103 from "node:path";
|
|
88862
89144
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
88863
89145
|
function readEvidenceDir(directory, phase) {
|
|
88864
89146
|
try {
|
|
88865
|
-
const dirPath = validateSwarmPath(directory,
|
|
89147
|
+
const dirPath = validateSwarmPath(directory, path103.posix.join("evidence", String(phase)));
|
|
88866
89148
|
if (!fs78.existsSync(dirPath))
|
|
88867
89149
|
return [];
|
|
88868
89150
|
const entries = fs78.readdirSync(dirPath);
|
|
88869
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
89151
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path103.join(dirPath, e));
|
|
88870
89152
|
} catch {
|
|
88871
89153
|
return [];
|
|
88872
89154
|
}
|
|
@@ -89005,16 +89287,16 @@ init_plan_schema();
|
|
|
89005
89287
|
init_ledger();
|
|
89006
89288
|
init_manager();
|
|
89007
89289
|
import * as fs79 from "node:fs";
|
|
89008
|
-
import * as
|
|
89290
|
+
import * as path104 from "node:path";
|
|
89009
89291
|
async function writeCheckpoint(directory) {
|
|
89010
89292
|
try {
|
|
89011
89293
|
const plan = await loadPlan(directory);
|
|
89012
89294
|
if (!plan)
|
|
89013
89295
|
return;
|
|
89014
|
-
const swarmDir =
|
|
89296
|
+
const swarmDir = path104.join(directory, ".swarm");
|
|
89015
89297
|
fs79.mkdirSync(swarmDir, { recursive: true });
|
|
89016
|
-
const jsonPath =
|
|
89017
|
-
const mdPath =
|
|
89298
|
+
const jsonPath = path104.join(swarmDir, "SWARM_PLAN.json");
|
|
89299
|
+
const mdPath = path104.join(swarmDir, "SWARM_PLAN.md");
|
|
89018
89300
|
fs79.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
89019
89301
|
const md = derivePlanMarkdown(plan);
|
|
89020
89302
|
fs79.writeFileSync(mdPath, md, "utf8");
|
|
@@ -89033,15 +89315,15 @@ init_telemetry();
|
|
|
89033
89315
|
// src/turbo/lean/phase-ready.ts
|
|
89034
89316
|
init_file_locks();
|
|
89035
89317
|
import * as fs81 from "node:fs";
|
|
89036
|
-
import * as
|
|
89318
|
+
import * as path106 from "node:path";
|
|
89037
89319
|
|
|
89038
89320
|
// src/turbo/lean/evidence.ts
|
|
89039
89321
|
init_bun_compat();
|
|
89040
89322
|
import { rmSync as rmSync5 } from "node:fs";
|
|
89041
89323
|
import * as fs80 from "node:fs/promises";
|
|
89042
|
-
import * as
|
|
89324
|
+
import * as path105 from "node:path";
|
|
89043
89325
|
function leanTurboEvidenceDir(directory, phase) {
|
|
89044
|
-
return
|
|
89326
|
+
return path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89045
89327
|
}
|
|
89046
89328
|
function validateLaneId(laneId) {
|
|
89047
89329
|
if (laneId.length === 0) {
|
|
@@ -89063,16 +89345,16 @@ function validateLaneId(laneId) {
|
|
|
89063
89345
|
function laneEvidencePath(directory, phase, laneId) {
|
|
89064
89346
|
validateLaneId(laneId);
|
|
89065
89347
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
89066
|
-
const resolvedPath =
|
|
89067
|
-
const resolvedDir =
|
|
89068
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
89348
|
+
const resolvedPath = path105.resolve(path105.join(expectedDir, `${laneId}.json`));
|
|
89349
|
+
const resolvedDir = path105.resolve(expectedDir);
|
|
89350
|
+
if (!resolvedPath.startsWith(resolvedDir + path105.sep) && resolvedPath !== resolvedDir) {
|
|
89069
89351
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
89070
89352
|
}
|
|
89071
89353
|
return resolvedPath;
|
|
89072
89354
|
}
|
|
89073
89355
|
async function atomicWriteJson(filePath, data) {
|
|
89074
89356
|
const content = JSON.stringify(data, null, 2);
|
|
89075
|
-
const dir =
|
|
89357
|
+
const dir = path105.dirname(filePath);
|
|
89076
89358
|
await fs80.mkdir(dir, { recursive: true });
|
|
89077
89359
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
89078
89360
|
try {
|
|
@@ -89086,7 +89368,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
89086
89368
|
}
|
|
89087
89369
|
}
|
|
89088
89370
|
function phaseEvidencePath(directory, phase) {
|
|
89089
|
-
return
|
|
89371
|
+
return path105.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
89090
89372
|
}
|
|
89091
89373
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
89092
89374
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -89130,7 +89412,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
89130
89412
|
if (entry === "lean-turbo-phase.json") {
|
|
89131
89413
|
continue;
|
|
89132
89414
|
}
|
|
89133
|
-
const filePath =
|
|
89415
|
+
const filePath = path105.join(evidenceDir, entry);
|
|
89134
89416
|
let content;
|
|
89135
89417
|
try {
|
|
89136
89418
|
content = await fs80.readFile(filePath, "utf-8");
|
|
@@ -89154,7 +89436,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
89154
89436
|
};
|
|
89155
89437
|
function defaultReadPlanJson(dir) {
|
|
89156
89438
|
try {
|
|
89157
|
-
const planPath =
|
|
89439
|
+
const planPath = path106.join(dir, ".swarm", "plan.json");
|
|
89158
89440
|
if (!fs81.existsSync(planPath))
|
|
89159
89441
|
return null;
|
|
89160
89442
|
const raw = fs81.readFileSync(planPath, "utf-8");
|
|
@@ -89169,7 +89451,7 @@ function defaultReadPlanJson(dir) {
|
|
|
89169
89451
|
}
|
|
89170
89452
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
89171
89453
|
try {
|
|
89172
|
-
const evidencePath =
|
|
89454
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
89173
89455
|
if (!fs81.existsSync(evidencePath)) {
|
|
89174
89456
|
return null;
|
|
89175
89457
|
}
|
|
@@ -89189,7 +89471,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
89189
89471
|
}
|
|
89190
89472
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
89191
89473
|
try {
|
|
89192
|
-
const evidencePath =
|
|
89474
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
89193
89475
|
if (!fs81.existsSync(evidencePath)) {
|
|
89194
89476
|
return null;
|
|
89195
89477
|
}
|
|
@@ -89208,7 +89490,7 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
89208
89490
|
}
|
|
89209
89491
|
}
|
|
89210
89492
|
function listLaneEvidenceSync(directory, phase) {
|
|
89211
|
-
const evidenceDir =
|
|
89493
|
+
const evidenceDir = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89212
89494
|
let entries;
|
|
89213
89495
|
try {
|
|
89214
89496
|
entries = fs81.readdirSync(evidenceDir);
|
|
@@ -89278,7 +89560,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89278
89560
|
...DEFAULT_CONFIG2,
|
|
89279
89561
|
...actualConfig
|
|
89280
89562
|
};
|
|
89281
|
-
const statePath =
|
|
89563
|
+
const statePath = path106.join(directory, ".swarm", "turbo-state.json");
|
|
89282
89564
|
if (!fs81.existsSync(statePath)) {
|
|
89283
89565
|
return {
|
|
89284
89566
|
ok: false,
|
|
@@ -89466,7 +89748,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89466
89748
|
}
|
|
89467
89749
|
}
|
|
89468
89750
|
if (mergedConfig.integrated_diff_required) {
|
|
89469
|
-
const evidencePath =
|
|
89751
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
89470
89752
|
let hasDiff = false;
|
|
89471
89753
|
try {
|
|
89472
89754
|
const content = fs81.readFileSync(evidencePath, "utf-8");
|
|
@@ -89739,7 +90021,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89739
90021
|
let driftCheckEnabled = true;
|
|
89740
90022
|
let driftHasSpecMd = false;
|
|
89741
90023
|
try {
|
|
89742
|
-
const specMdPath =
|
|
90024
|
+
const specMdPath = path107.join(dir, ".swarm", "spec.md");
|
|
89743
90025
|
driftHasSpecMd = fs82.existsSync(specMdPath);
|
|
89744
90026
|
const gatePlan = await loadPlan(dir);
|
|
89745
90027
|
if (gatePlan) {
|
|
@@ -89761,7 +90043,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89761
90043
|
} else {
|
|
89762
90044
|
let phaseType;
|
|
89763
90045
|
try {
|
|
89764
|
-
const planPath =
|
|
90046
|
+
const planPath = path107.join(dir, ".swarm", "plan.json");
|
|
89765
90047
|
if (fs82.existsSync(planPath)) {
|
|
89766
90048
|
const planRaw = fs82.readFileSync(planPath, "utf-8");
|
|
89767
90049
|
const plan = JSON.parse(planRaw);
|
|
@@ -89774,7 +90056,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89774
90056
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
89775
90057
|
} else {
|
|
89776
90058
|
try {
|
|
89777
|
-
const driftEvidencePath =
|
|
90059
|
+
const driftEvidencePath = path107.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
89778
90060
|
let driftVerdictFound = false;
|
|
89779
90061
|
let driftVerdictApproved = false;
|
|
89780
90062
|
try {
|
|
@@ -89812,7 +90094,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89812
90094
|
let incompleteTaskCount = 0;
|
|
89813
90095
|
let planParseable = false;
|
|
89814
90096
|
try {
|
|
89815
|
-
const planPath =
|
|
90097
|
+
const planPath = path107.join(dir, ".swarm", "plan.json");
|
|
89816
90098
|
if (fs82.existsSync(planPath)) {
|
|
89817
90099
|
const planRaw = fs82.readFileSync(planPath, "utf-8");
|
|
89818
90100
|
const plan = JSON.parse(planRaw);
|
|
@@ -89879,7 +90161,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89879
90161
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
89880
90162
|
const effective = getEffectiveGates(profile, overrides);
|
|
89881
90163
|
if (effective.hallucination_guard === true) {
|
|
89882
|
-
const hgPath =
|
|
90164
|
+
const hgPath = path107.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
89883
90165
|
let hgVerdictFound = false;
|
|
89884
90166
|
let hgVerdictApproved = false;
|
|
89885
90167
|
try {
|
|
@@ -89951,7 +90233,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89951
90233
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
89952
90234
|
const effective = getEffectiveGates(profile, overrides);
|
|
89953
90235
|
if (effective.mutation_test === true) {
|
|
89954
|
-
const mgPath =
|
|
90236
|
+
const mgPath = path107.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
89955
90237
|
let mgVerdictFound = false;
|
|
89956
90238
|
let mgVerdict;
|
|
89957
90239
|
try {
|
|
@@ -90025,7 +90307,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90025
90307
|
const effective = getEffectiveGates(profile, overrides);
|
|
90026
90308
|
if (effective.council_mode === true) {
|
|
90027
90309
|
councilModeEnabled = true;
|
|
90028
|
-
const pcPath =
|
|
90310
|
+
const pcPath = path107.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
90029
90311
|
let pcVerdictFound = false;
|
|
90030
90312
|
let _pcVerdict;
|
|
90031
90313
|
let pcQuorumSize;
|
|
@@ -90233,7 +90515,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90233
90515
|
const effective = getEffectiveGates(profile, overrides);
|
|
90234
90516
|
if (effective.final_council === true) {
|
|
90235
90517
|
finalCouncilEnabled = true;
|
|
90236
|
-
const fcPath =
|
|
90518
|
+
const fcPath = path107.join(dir, ".swarm", "evidence", "final-council.json");
|
|
90237
90519
|
let fcVerdictFound = false;
|
|
90238
90520
|
let _fcVerdict;
|
|
90239
90521
|
try {
|
|
@@ -90421,7 +90703,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90421
90703
|
}
|
|
90422
90704
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
90423
90705
|
try {
|
|
90424
|
-
const projectName =
|
|
90706
|
+
const projectName = path107.basename(dir);
|
|
90425
90707
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
90426
90708
|
if (curationResult) {
|
|
90427
90709
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -90672,7 +90954,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90672
90954
|
const phaseObj = rebuilt.phases.find((p) => p.id === phase);
|
|
90673
90955
|
if (phaseObj) {
|
|
90674
90956
|
phaseObj.status = "complete";
|
|
90675
|
-
await
|
|
90957
|
+
await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
|
|
90676
90958
|
try {
|
|
90677
90959
|
await takeSnapshotEvent(dir, rebuilt).catch(() => {});
|
|
90678
90960
|
} catch {}
|
|
@@ -90714,7 +90996,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90714
90996
|
const phaseObj = rebuilt.phases.find((p) => p.id === phase);
|
|
90715
90997
|
if (phaseObj) {
|
|
90716
90998
|
phaseObj.status = "complete";
|
|
90717
|
-
await
|
|
90999
|
+
await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
|
|
90718
91000
|
try {
|
|
90719
91001
|
await takeSnapshotEvent(dir, rebuilt).catch(() => {});
|
|
90720
91002
|
} catch {}
|
|
@@ -90791,7 +91073,7 @@ init_utils();
|
|
|
90791
91073
|
init_bun_compat();
|
|
90792
91074
|
init_create_tool();
|
|
90793
91075
|
import * as fs83 from "node:fs";
|
|
90794
|
-
import * as
|
|
91076
|
+
import * as path108 from "node:path";
|
|
90795
91077
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
90796
91078
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
90797
91079
|
function isValidEcosystem(value) {
|
|
@@ -90819,16 +91101,16 @@ function validateArgs3(args2) {
|
|
|
90819
91101
|
function detectEcosystems(directory) {
|
|
90820
91102
|
const ecosystems = [];
|
|
90821
91103
|
const cwd = directory;
|
|
90822
|
-
if (fs83.existsSync(
|
|
91104
|
+
if (fs83.existsSync(path108.join(cwd, "package.json"))) {
|
|
90823
91105
|
ecosystems.push("npm");
|
|
90824
91106
|
}
|
|
90825
|
-
if (fs83.existsSync(
|
|
91107
|
+
if (fs83.existsSync(path108.join(cwd, "pyproject.toml")) || fs83.existsSync(path108.join(cwd, "requirements.txt"))) {
|
|
90826
91108
|
ecosystems.push("pip");
|
|
90827
91109
|
}
|
|
90828
|
-
if (fs83.existsSync(
|
|
91110
|
+
if (fs83.existsSync(path108.join(cwd, "Cargo.toml"))) {
|
|
90829
91111
|
ecosystems.push("cargo");
|
|
90830
91112
|
}
|
|
90831
|
-
if (fs83.existsSync(
|
|
91113
|
+
if (fs83.existsSync(path108.join(cwd, "go.mod"))) {
|
|
90832
91114
|
ecosystems.push("go");
|
|
90833
91115
|
}
|
|
90834
91116
|
try {
|
|
@@ -90837,13 +91119,13 @@ function detectEcosystems(directory) {
|
|
|
90837
91119
|
ecosystems.push("dotnet");
|
|
90838
91120
|
}
|
|
90839
91121
|
} catch {}
|
|
90840
|
-
if (fs83.existsSync(
|
|
91122
|
+
if (fs83.existsSync(path108.join(cwd, "Gemfile")) || fs83.existsSync(path108.join(cwd, "Gemfile.lock"))) {
|
|
90841
91123
|
ecosystems.push("ruby");
|
|
90842
91124
|
}
|
|
90843
|
-
if (fs83.existsSync(
|
|
91125
|
+
if (fs83.existsSync(path108.join(cwd, "pubspec.yaml"))) {
|
|
90844
91126
|
ecosystems.push("dart");
|
|
90845
91127
|
}
|
|
90846
|
-
if (fs83.existsSync(
|
|
91128
|
+
if (fs83.existsSync(path108.join(cwd, "composer.lock"))) {
|
|
90847
91129
|
ecosystems.push("composer");
|
|
90848
91130
|
}
|
|
90849
91131
|
return ecosystems;
|
|
@@ -91979,7 +92261,7 @@ var pkg_audit = createSwarmTool({
|
|
|
91979
92261
|
init_zod();
|
|
91980
92262
|
init_manager2();
|
|
91981
92263
|
import * as fs84 from "node:fs";
|
|
91982
|
-
import * as
|
|
92264
|
+
import * as path109 from "node:path";
|
|
91983
92265
|
init_utils();
|
|
91984
92266
|
init_create_tool();
|
|
91985
92267
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -92102,7 +92384,7 @@ function isScaffoldFile(filePath) {
|
|
|
92102
92384
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
92103
92385
|
return true;
|
|
92104
92386
|
}
|
|
92105
|
-
const filename =
|
|
92387
|
+
const filename = path109.basename(filePath);
|
|
92106
92388
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
92107
92389
|
return true;
|
|
92108
92390
|
}
|
|
@@ -92119,7 +92401,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92119
92401
|
if (regex.test(normalizedPath)) {
|
|
92120
92402
|
return true;
|
|
92121
92403
|
}
|
|
92122
|
-
const filename =
|
|
92404
|
+
const filename = path109.basename(filePath);
|
|
92123
92405
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
92124
92406
|
if (filenameRegex.test(filename)) {
|
|
92125
92407
|
return true;
|
|
@@ -92128,7 +92410,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92128
92410
|
return false;
|
|
92129
92411
|
}
|
|
92130
92412
|
function isParserSupported(filePath) {
|
|
92131
|
-
const ext =
|
|
92413
|
+
const ext = path109.extname(filePath).toLowerCase();
|
|
92132
92414
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
92133
92415
|
}
|
|
92134
92416
|
function isPlanFile(filePath) {
|
|
@@ -92375,9 +92657,9 @@ async function placeholderScan(input, directory) {
|
|
|
92375
92657
|
let filesScanned = 0;
|
|
92376
92658
|
const filesWithFindings = new Set;
|
|
92377
92659
|
for (const filePath of changed_files) {
|
|
92378
|
-
const fullPath =
|
|
92379
|
-
const resolvedDirectory =
|
|
92380
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
92660
|
+
const fullPath = path109.isAbsolute(filePath) ? filePath : path109.resolve(directory, filePath);
|
|
92661
|
+
const resolvedDirectory = path109.resolve(directory);
|
|
92662
|
+
if (!fullPath.startsWith(resolvedDirectory + path109.sep) && fullPath !== resolvedDirectory) {
|
|
92381
92663
|
continue;
|
|
92382
92664
|
}
|
|
92383
92665
|
if (!fs84.existsSync(fullPath)) {
|
|
@@ -92386,7 +92668,7 @@ async function placeholderScan(input, directory) {
|
|
|
92386
92668
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
92387
92669
|
continue;
|
|
92388
92670
|
}
|
|
92389
|
-
const relativeFilePath =
|
|
92671
|
+
const relativeFilePath = path109.relative(directory, fullPath).replace(/\\/g, "/");
|
|
92390
92672
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
92391
92673
|
continue;
|
|
92392
92674
|
}
|
|
@@ -92458,7 +92740,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
92458
92740
|
});
|
|
92459
92741
|
// src/tools/pre-check-batch.ts
|
|
92460
92742
|
import * as fs88 from "node:fs";
|
|
92461
|
-
import * as
|
|
92743
|
+
import * as path113 from "node:path";
|
|
92462
92744
|
init_zod();
|
|
92463
92745
|
init_manager2();
|
|
92464
92746
|
init_utils();
|
|
@@ -92599,7 +92881,7 @@ init_zod();
|
|
|
92599
92881
|
init_manager2();
|
|
92600
92882
|
init_detector();
|
|
92601
92883
|
import * as fs87 from "node:fs";
|
|
92602
|
-
import * as
|
|
92884
|
+
import * as path112 from "node:path";
|
|
92603
92885
|
import { extname as extname19 } from "node:path";
|
|
92604
92886
|
|
|
92605
92887
|
// src/sast/rules/c.ts
|
|
@@ -93315,7 +93597,7 @@ function executeRulesSync(filePath, content, language) {
|
|
|
93315
93597
|
// src/sast/semgrep.ts
|
|
93316
93598
|
import * as child_process9 from "node:child_process";
|
|
93317
93599
|
import * as fs85 from "node:fs";
|
|
93318
|
-
import * as
|
|
93600
|
+
import * as path110 from "node:path";
|
|
93319
93601
|
var semgrepAvailableCache = null;
|
|
93320
93602
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
93321
93603
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -93502,7 +93784,7 @@ async function runSemgrep(options) {
|
|
|
93502
93784
|
}
|
|
93503
93785
|
function getRulesDirectory(projectRoot) {
|
|
93504
93786
|
if (projectRoot) {
|
|
93505
|
-
return
|
|
93787
|
+
return path110.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
93506
93788
|
}
|
|
93507
93789
|
return DEFAULT_RULES_DIR;
|
|
93508
93790
|
}
|
|
@@ -93523,24 +93805,24 @@ init_create_tool();
|
|
|
93523
93805
|
init_utils2();
|
|
93524
93806
|
import * as crypto9 from "node:crypto";
|
|
93525
93807
|
import * as fs86 from "node:fs";
|
|
93526
|
-
import * as
|
|
93808
|
+
import * as path111 from "node:path";
|
|
93527
93809
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
93528
93810
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
93529
93811
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
93530
93812
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
93531
93813
|
function normalizeFindingPath(directory, file3) {
|
|
93532
|
-
const resolved =
|
|
93533
|
-
const rel =
|
|
93814
|
+
const resolved = path111.isAbsolute(file3) ? file3 : path111.resolve(directory, file3);
|
|
93815
|
+
const rel = path111.relative(path111.resolve(directory), resolved);
|
|
93534
93816
|
return rel.replace(/\\/g, "/");
|
|
93535
93817
|
}
|
|
93536
93818
|
function baselineRelPath(phase) {
|
|
93537
|
-
return
|
|
93819
|
+
return path111.join("evidence", String(phase), "sast-baseline.json");
|
|
93538
93820
|
}
|
|
93539
93821
|
function tempRelPath(phase) {
|
|
93540
|
-
return
|
|
93822
|
+
return path111.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
93541
93823
|
}
|
|
93542
93824
|
function lockRelPath(phase) {
|
|
93543
|
-
return
|
|
93825
|
+
return path111.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
93544
93826
|
}
|
|
93545
93827
|
function getLine(lines, idx) {
|
|
93546
93828
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -93661,8 +93943,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
93661
93943
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
93662
93944
|
};
|
|
93663
93945
|
}
|
|
93664
|
-
fs86.mkdirSync(
|
|
93665
|
-
fs86.mkdirSync(
|
|
93946
|
+
fs86.mkdirSync(path111.dirname(baselinePath), { recursive: true });
|
|
93947
|
+
fs86.mkdirSync(path111.dirname(tempPath), { recursive: true });
|
|
93666
93948
|
const releaseLock = await acquireLock2(lockPath);
|
|
93667
93949
|
try {
|
|
93668
93950
|
let existing = null;
|
|
@@ -93935,9 +94217,9 @@ async function sastScan(input, directory, config3) {
|
|
|
93935
94217
|
_filesSkipped++;
|
|
93936
94218
|
continue;
|
|
93937
94219
|
}
|
|
93938
|
-
const resolvedPath =
|
|
93939
|
-
const resolvedDirectory =
|
|
93940
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
94220
|
+
const resolvedPath = path112.isAbsolute(filePath) ? filePath : path112.resolve(directory, filePath);
|
|
94221
|
+
const resolvedDirectory = path112.resolve(directory);
|
|
94222
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path112.sep) && resolvedPath !== resolvedDirectory) {
|
|
93941
94223
|
_filesSkipped++;
|
|
93942
94224
|
continue;
|
|
93943
94225
|
}
|
|
@@ -94252,18 +94534,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
94252
94534
|
let resolved;
|
|
94253
94535
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
94254
94536
|
if (isWinAbs) {
|
|
94255
|
-
resolved =
|
|
94256
|
-
} else if (
|
|
94257
|
-
resolved =
|
|
94537
|
+
resolved = path113.win32.resolve(inputPath);
|
|
94538
|
+
} else if (path113.isAbsolute(inputPath)) {
|
|
94539
|
+
resolved = path113.resolve(inputPath);
|
|
94258
94540
|
} else {
|
|
94259
|
-
resolved =
|
|
94541
|
+
resolved = path113.resolve(baseDir, inputPath);
|
|
94260
94542
|
}
|
|
94261
|
-
const workspaceResolved =
|
|
94543
|
+
const workspaceResolved = path113.resolve(workspaceDir);
|
|
94262
94544
|
let relative24;
|
|
94263
94545
|
if (isWinAbs) {
|
|
94264
|
-
relative24 =
|
|
94546
|
+
relative24 = path113.win32.relative(workspaceResolved, resolved);
|
|
94265
94547
|
} else {
|
|
94266
|
-
relative24 =
|
|
94548
|
+
relative24 = path113.relative(workspaceResolved, resolved);
|
|
94267
94549
|
}
|
|
94268
94550
|
if (relative24.startsWith("..")) {
|
|
94269
94551
|
return "path traversal detected";
|
|
@@ -94328,7 +94610,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
94328
94610
|
if (typeof file3 !== "string") {
|
|
94329
94611
|
continue;
|
|
94330
94612
|
}
|
|
94331
|
-
const resolvedPath =
|
|
94613
|
+
const resolvedPath = path113.resolve(file3);
|
|
94332
94614
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
94333
94615
|
if (validationError) {
|
|
94334
94616
|
continue;
|
|
@@ -94485,7 +94767,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
94485
94767
|
skippedFiles++;
|
|
94486
94768
|
continue;
|
|
94487
94769
|
}
|
|
94488
|
-
const resolvedPath =
|
|
94770
|
+
const resolvedPath = path113.resolve(file3);
|
|
94489
94771
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
94490
94772
|
if (validationError) {
|
|
94491
94773
|
skippedFiles++;
|
|
@@ -94503,7 +94785,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
94503
94785
|
};
|
|
94504
94786
|
}
|
|
94505
94787
|
for (const file3 of validatedFiles) {
|
|
94506
|
-
const ext =
|
|
94788
|
+
const ext = path113.extname(file3).toLowerCase();
|
|
94507
94789
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
94508
94790
|
skippedFiles++;
|
|
94509
94791
|
continue;
|
|
@@ -94722,7 +95004,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
94722
95004
|
const preexistingFindings = [];
|
|
94723
95005
|
for (const finding of findings) {
|
|
94724
95006
|
const filePath = finding.location.file;
|
|
94725
|
-
const normalised =
|
|
95007
|
+
const normalised = path113.relative(directory, filePath).replace(/\\/g, "/");
|
|
94726
95008
|
const changedLines = changedLineRanges.get(normalised);
|
|
94727
95009
|
if (changedLines?.has(finding.location.line)) {
|
|
94728
95010
|
newFindings.push(finding);
|
|
@@ -94773,7 +95055,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
94773
95055
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
94774
95056
|
continue;
|
|
94775
95057
|
}
|
|
94776
|
-
changedFiles.push(
|
|
95058
|
+
changedFiles.push(path113.resolve(directory, file3));
|
|
94777
95059
|
}
|
|
94778
95060
|
if (changedFiles.length === 0) {
|
|
94779
95061
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -94974,7 +95256,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
94974
95256
|
};
|
|
94975
95257
|
return JSON.stringify(errorResult, null, 2);
|
|
94976
95258
|
}
|
|
94977
|
-
const resolvedDirectory =
|
|
95259
|
+
const resolvedDirectory = path113.resolve(typedArgs.directory);
|
|
94978
95260
|
const workspaceAnchor = resolvedDirectory;
|
|
94979
95261
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
94980
95262
|
if (dirError) {
|
|
@@ -95015,7 +95297,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
95015
95297
|
});
|
|
95016
95298
|
// src/tools/repo-map.ts
|
|
95017
95299
|
init_zod();
|
|
95018
|
-
import * as
|
|
95300
|
+
import * as path114 from "node:path";
|
|
95019
95301
|
init_path_security();
|
|
95020
95302
|
init_create_tool();
|
|
95021
95303
|
var VALID_ACTIONS = [
|
|
@@ -95040,7 +95322,7 @@ function validateFile(p) {
|
|
|
95040
95322
|
return "file contains control characters";
|
|
95041
95323
|
if (containsPathTraversal(p))
|
|
95042
95324
|
return "file contains path traversal";
|
|
95043
|
-
if (
|
|
95325
|
+
if (path114.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
95044
95326
|
return "file must be a workspace-relative path, not absolute";
|
|
95045
95327
|
}
|
|
95046
95328
|
return null;
|
|
@@ -95063,8 +95345,8 @@ function ok(action, payload) {
|
|
|
95063
95345
|
}
|
|
95064
95346
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
95065
95347
|
const normalized = input.replace(/\\/g, "/");
|
|
95066
|
-
if (
|
|
95067
|
-
const rel =
|
|
95348
|
+
if (path114.isAbsolute(normalized)) {
|
|
95349
|
+
const rel = path114.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
95068
95350
|
return normalizeGraphPath2(rel);
|
|
95069
95351
|
}
|
|
95070
95352
|
return normalizeGraphPath2(normalized);
|
|
@@ -95209,7 +95491,7 @@ var repo_map = createSwarmTool({
|
|
|
95209
95491
|
init_zod();
|
|
95210
95492
|
init_create_tool();
|
|
95211
95493
|
import * as fs89 from "node:fs";
|
|
95212
|
-
import * as
|
|
95494
|
+
import * as path115 from "node:path";
|
|
95213
95495
|
var SPEC_FILE = ".swarm/spec.md";
|
|
95214
95496
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
95215
95497
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -95278,7 +95560,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95278
95560
|
return [];
|
|
95279
95561
|
}
|
|
95280
95562
|
for (const entry of entries) {
|
|
95281
|
-
const entryPath =
|
|
95563
|
+
const entryPath = path115.join(evidenceDir, entry);
|
|
95282
95564
|
try {
|
|
95283
95565
|
const stat8 = fs89.statSync(entryPath);
|
|
95284
95566
|
if (!stat8.isDirectory()) {
|
|
@@ -95294,11 +95576,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95294
95576
|
if (entryPhase !== String(phase)) {
|
|
95295
95577
|
continue;
|
|
95296
95578
|
}
|
|
95297
|
-
const evidenceFilePath =
|
|
95579
|
+
const evidenceFilePath = path115.join(entryPath, "evidence.json");
|
|
95298
95580
|
try {
|
|
95299
|
-
const resolvedPath =
|
|
95300
|
-
const evidenceDirResolved =
|
|
95301
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
95581
|
+
const resolvedPath = path115.resolve(evidenceFilePath);
|
|
95582
|
+
const evidenceDirResolved = path115.resolve(evidenceDir);
|
|
95583
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path115.sep)) {
|
|
95302
95584
|
continue;
|
|
95303
95585
|
}
|
|
95304
95586
|
const stat8 = fs89.lstatSync(evidenceFilePath);
|
|
@@ -95332,7 +95614,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95332
95614
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
95333
95615
|
for (const file3 of diffEntry.files_changed) {
|
|
95334
95616
|
if (typeof file3 === "string") {
|
|
95335
|
-
touchedFiles.add(
|
|
95617
|
+
touchedFiles.add(path115.resolve(cwd, file3));
|
|
95336
95618
|
}
|
|
95337
95619
|
}
|
|
95338
95620
|
}
|
|
@@ -95345,8 +95627,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95345
95627
|
}
|
|
95346
95628
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
95347
95629
|
try {
|
|
95348
|
-
const resolvedPath =
|
|
95349
|
-
const cwdResolved =
|
|
95630
|
+
const resolvedPath = path115.resolve(filePath);
|
|
95631
|
+
const cwdResolved = path115.resolve(cwd);
|
|
95350
95632
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
95351
95633
|
return false;
|
|
95352
95634
|
}
|
|
@@ -95480,7 +95762,7 @@ var req_coverage = createSwarmTool({
|
|
|
95480
95762
|
}, null, 2);
|
|
95481
95763
|
}
|
|
95482
95764
|
const cwd = inputDirectory || directory;
|
|
95483
|
-
const specPath =
|
|
95765
|
+
const specPath = path115.join(cwd, SPEC_FILE);
|
|
95484
95766
|
let specContent;
|
|
95485
95767
|
try {
|
|
95486
95768
|
specContent = fs89.readFileSync(specPath, "utf-8");
|
|
@@ -95507,7 +95789,7 @@ var req_coverage = createSwarmTool({
|
|
|
95507
95789
|
message: "No FR requirements found in spec.md"
|
|
95508
95790
|
}, null, 2);
|
|
95509
95791
|
}
|
|
95510
|
-
const evidenceDir =
|
|
95792
|
+
const evidenceDir = path115.join(cwd, EVIDENCE_DIR4);
|
|
95511
95793
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
95512
95794
|
const analyzedRequirements = [];
|
|
95513
95795
|
let coveredCount = 0;
|
|
@@ -95533,7 +95815,7 @@ var req_coverage = createSwarmTool({
|
|
|
95533
95815
|
requirements: analyzedRequirements
|
|
95534
95816
|
};
|
|
95535
95817
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
95536
|
-
const reportPath =
|
|
95818
|
+
const reportPath = path115.join(evidenceDir, reportFilename);
|
|
95537
95819
|
try {
|
|
95538
95820
|
if (!fs89.existsSync(evidenceDir)) {
|
|
95539
95821
|
fs89.mkdirSync(evidenceDir, { recursive: true });
|
|
@@ -95621,7 +95903,7 @@ init_qa_gate_profile();
|
|
|
95621
95903
|
init_file_locks();
|
|
95622
95904
|
import * as crypto10 from "node:crypto";
|
|
95623
95905
|
import * as fs90 from "node:fs";
|
|
95624
|
-
import * as
|
|
95906
|
+
import * as path116 from "node:path";
|
|
95625
95907
|
init_ledger();
|
|
95626
95908
|
init_manager();
|
|
95627
95909
|
init_state();
|
|
@@ -95699,8 +95981,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95699
95981
|
};
|
|
95700
95982
|
}
|
|
95701
95983
|
if (args2.working_directory && fallbackDir) {
|
|
95702
|
-
const resolvedTarget =
|
|
95703
|
-
const resolvedRoot =
|
|
95984
|
+
const resolvedTarget = path116.resolve(args2.working_directory);
|
|
95985
|
+
const resolvedRoot = path116.resolve(fallbackDir);
|
|
95704
95986
|
let fallbackExists = false;
|
|
95705
95987
|
try {
|
|
95706
95988
|
fs90.accessSync(resolvedRoot, fs90.constants.F_OK);
|
|
@@ -95709,7 +95991,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95709
95991
|
fallbackExists = false;
|
|
95710
95992
|
}
|
|
95711
95993
|
if (fallbackExists) {
|
|
95712
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
95994
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path116.sep);
|
|
95713
95995
|
if (isSubdirectory) {
|
|
95714
95996
|
return {
|
|
95715
95997
|
success: false,
|
|
@@ -95725,7 +96007,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95725
96007
|
let specMtime;
|
|
95726
96008
|
let specHash;
|
|
95727
96009
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
95728
|
-
const specPath =
|
|
96010
|
+
const specPath = path116.join(targetWorkspace, ".swarm", "spec.md");
|
|
95729
96011
|
try {
|
|
95730
96012
|
const stat8 = await fs90.promises.stat(specPath);
|
|
95731
96013
|
specMtime = stat8.mtime.toISOString();
|
|
@@ -95741,7 +96023,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95741
96023
|
}
|
|
95742
96024
|
}
|
|
95743
96025
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
95744
|
-
const contextPath =
|
|
96026
|
+
const contextPath = path116.join(targetWorkspace, ".swarm", "context.md");
|
|
95745
96027
|
let contextContent = "";
|
|
95746
96028
|
try {
|
|
95747
96029
|
contextContent = await fs90.promises.readFile(contextPath, "utf8");
|
|
@@ -95771,6 +96053,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95771
96053
|
}
|
|
95772
96054
|
const dir = targetWorkspace;
|
|
95773
96055
|
const existingStatusMap = new Map;
|
|
96056
|
+
const priorTaskIds = new Set;
|
|
95774
96057
|
let preservedExecutionProfile;
|
|
95775
96058
|
{
|
|
95776
96059
|
let existing = null;
|
|
@@ -95778,6 +96061,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95778
96061
|
existing = await loadPlanJsonOnly(dir);
|
|
95779
96062
|
} catch {}
|
|
95780
96063
|
if (existing) {
|
|
96064
|
+
for (const phase of existing.phases) {
|
|
96065
|
+
for (const task of phase.tasks)
|
|
96066
|
+
priorTaskIds.add(task.id);
|
|
96067
|
+
}
|
|
95781
96068
|
if (!args2.reset_statuses) {
|
|
95782
96069
|
for (const phase of existing.phases) {
|
|
95783
96070
|
for (const task of phase.tasks) {
|
|
@@ -95819,6 +96106,98 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95819
96106
|
}
|
|
95820
96107
|
resolvedProfile = parsed.data;
|
|
95821
96108
|
}
|
|
96109
|
+
const incomingTaskIds = new Set;
|
|
96110
|
+
for (const phase of args2.phases) {
|
|
96111
|
+
for (const task of phase.tasks)
|
|
96112
|
+
incomingTaskIds.add(task.id);
|
|
96113
|
+
}
|
|
96114
|
+
const missingTaskIds = [];
|
|
96115
|
+
for (const id of priorTaskIds) {
|
|
96116
|
+
if (!incomingTaskIds.has(id))
|
|
96117
|
+
missingTaskIds.push(id);
|
|
96118
|
+
}
|
|
96119
|
+
const rawRemovedIds = args2.removed_task_ids ?? [];
|
|
96120
|
+
if (rawRemovedIds.length > 0) {
|
|
96121
|
+
const seen = new Set;
|
|
96122
|
+
for (const id of rawRemovedIds) {
|
|
96123
|
+
if (seen.has(id)) {
|
|
96124
|
+
return {
|
|
96125
|
+
success: false,
|
|
96126
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains duplicate entries",
|
|
96127
|
+
errors: [`Duplicate id in removed_task_ids: "${id}"`],
|
|
96128
|
+
recovery_guidance: "Deduplicate removed_task_ids and retry save_plan."
|
|
96129
|
+
};
|
|
96130
|
+
}
|
|
96131
|
+
seen.add(id);
|
|
96132
|
+
}
|
|
96133
|
+
for (const id of rawRemovedIds) {
|
|
96134
|
+
if (incomingTaskIds.has(id)) {
|
|
96135
|
+
return {
|
|
96136
|
+
success: false,
|
|
96137
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains a task that also appears in args.phases",
|
|
96138
|
+
errors: [
|
|
96139
|
+
`Task "${id}" appears in both removed_task_ids and args.phases — these are contradictory`
|
|
96140
|
+
],
|
|
96141
|
+
recovery_guidance: "A task cannot be both kept and removed in the same save_plan call. Either drop it from args.phases or remove it from removed_task_ids."
|
|
96142
|
+
};
|
|
96143
|
+
}
|
|
96144
|
+
}
|
|
96145
|
+
for (const id of rawRemovedIds) {
|
|
96146
|
+
if (!priorTaskIds.has(id)) {
|
|
96147
|
+
return {
|
|
96148
|
+
success: false,
|
|
96149
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains an id that was not in the prior plan",
|
|
96150
|
+
errors: [
|
|
96151
|
+
`Task "${id}" is in removed_task_ids but not present in the prior plan`
|
|
96152
|
+
],
|
|
96153
|
+
recovery_guidance: "Re-read the prior plan and update removed_task_ids to only list tasks that actually existed."
|
|
96154
|
+
};
|
|
96155
|
+
}
|
|
96156
|
+
}
|
|
96157
|
+
}
|
|
96158
|
+
let resolvedRemovedIds = [...rawRemovedIds];
|
|
96159
|
+
let resolvedRemovalReason = args2.removal_reason;
|
|
96160
|
+
if (args2.reset_statuses === true && missingTaskIds.length > 0) {
|
|
96161
|
+
if (args2.confirm_destructive_reset !== true) {
|
|
96162
|
+
return {
|
|
96163
|
+
success: false,
|
|
96164
|
+
message: "PLAN_DESTRUCTIVE_RESET_NOT_CONFIRMED: reset_statuses with missing tasks requires confirm_destructive_reset: true",
|
|
96165
|
+
errors: [
|
|
96166
|
+
`reset_statuses: true would drop ${missingTaskIds.length} task(s) from the prior plan: ${missingTaskIds.join(", ")}`
|
|
96167
|
+
],
|
|
96168
|
+
recovery_guidance: "Surface the list of dropped tasks to the user and confirm intent before retrying. " + "Pass confirm_destructive_reset: true (with reset_statuses: true) to acknowledge the destructive reset, " + "or list removed_task_ids explicitly with a removal_reason."
|
|
96169
|
+
};
|
|
96170
|
+
}
|
|
96171
|
+
if (rawRemovedIds.length === 0) {
|
|
96172
|
+
resolvedRemovedIds = [...missingTaskIds];
|
|
96173
|
+
resolvedRemovalReason = "destructive reset acknowledged";
|
|
96174
|
+
}
|
|
96175
|
+
}
|
|
96176
|
+
if (resolvedRemovedIds.length > 0) {
|
|
96177
|
+
const reason = (resolvedRemovalReason ?? "").trim();
|
|
96178
|
+
if (reason.length === 0) {
|
|
96179
|
+
return {
|
|
96180
|
+
success: false,
|
|
96181
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removal_reason is required when removed_task_ids is non-empty",
|
|
96182
|
+
errors: ["removal_reason must be a non-empty, non-whitespace string"],
|
|
96183
|
+
recovery_guidance: "Provide a removal_reason describing why these tasks are being dropped."
|
|
96184
|
+
};
|
|
96185
|
+
}
|
|
96186
|
+
}
|
|
96187
|
+
if (missingTaskIds.length > 0) {
|
|
96188
|
+
const ackSet = new Set(resolvedRemovedIds);
|
|
96189
|
+
const unacked = missingTaskIds.filter((id) => !ackSet.has(id));
|
|
96190
|
+
if (unacked.length > 0) {
|
|
96191
|
+
return {
|
|
96192
|
+
success: false,
|
|
96193
|
+
message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
|
|
96194
|
+
errors: [
|
|
96195
|
+
`The following prior tasks are missing from the new save and were not listed in removed_task_ids: ${unacked.join(", ")}`
|
|
96196
|
+
],
|
|
96197
|
+
recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(unacked)} and a non-empty removal_reason. ` + "Tasks not yet finished (status pending/in_progress/blocked) MUST NOT be removed without explicit user confirmation."
|
|
96198
|
+
};
|
|
96199
|
+
}
|
|
96200
|
+
}
|
|
95822
96201
|
const plan = {
|
|
95823
96202
|
schema_version: "1.0.0",
|
|
95824
96203
|
title: args2.title,
|
|
@@ -95865,7 +96244,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95865
96244
|
}
|
|
95866
96245
|
try {
|
|
95867
96246
|
await savePlan(dir, plan, {
|
|
95868
|
-
preserveCompletedStatuses: !args2.reset_statuses
|
|
96247
|
+
preserveCompletedStatuses: !args2.reset_statuses,
|
|
96248
|
+
...resolvedRemovedIds.length > 0 ? {
|
|
96249
|
+
acknowledged_removals: {
|
|
96250
|
+
ids: resolvedRemovedIds,
|
|
96251
|
+
reason: (resolvedRemovalReason ?? "").trim(),
|
|
96252
|
+
source: "save_plan_tool"
|
|
96253
|
+
}
|
|
96254
|
+
} : {}
|
|
95869
96255
|
});
|
|
95870
96256
|
const savedPlan = await loadPlanJsonOnly(dir);
|
|
95871
96257
|
if (savedPlan) {
|
|
@@ -95894,7 +96280,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95894
96280
|
}
|
|
95895
96281
|
await writeCheckpoint(dir).catch(() => {});
|
|
95896
96282
|
try {
|
|
95897
|
-
const markerPath =
|
|
96283
|
+
const markerPath = path116.join(dir, ".swarm", ".plan-write-marker");
|
|
95898
96284
|
const marker = JSON.stringify({
|
|
95899
96285
|
source: "save_plan",
|
|
95900
96286
|
timestamp: new Date().toISOString(),
|
|
@@ -95917,7 +96303,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95917
96303
|
return {
|
|
95918
96304
|
success: true,
|
|
95919
96305
|
message: "Plan saved successfully",
|
|
95920
|
-
plan_path:
|
|
96306
|
+
plan_path: path116.join(dir, ".swarm", "plan.json"),
|
|
95921
96307
|
phases_count: plan.phases.length,
|
|
95922
96308
|
tasks_count: tasksCount,
|
|
95923
96309
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -95929,6 +96315,15 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95929
96315
|
}
|
|
95930
96316
|
}
|
|
95931
96317
|
} catch (error93) {
|
|
96318
|
+
if (error93 instanceof PlanTaskRemovalNotAcknowledgedError) {
|
|
96319
|
+
const ids = error93.missingTasks.map((t) => t.id);
|
|
96320
|
+
return {
|
|
96321
|
+
success: false,
|
|
96322
|
+
message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
|
|
96323
|
+
errors: [error93.message],
|
|
96324
|
+
recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(ids)} and a non-empty removal_reason.`
|
|
96325
|
+
};
|
|
96326
|
+
}
|
|
95932
96327
|
return {
|
|
95933
96328
|
success: false,
|
|
95934
96329
|
message: "Failed to save plan: retry with save_plan after resolving the error above",
|
|
@@ -95955,6 +96350,9 @@ var save_plan = createSwarmTool({
|
|
|
95955
96350
|
})).min(1).describe("Implementation phases"),
|
|
95956
96351
|
working_directory: exports_external.string().optional().describe("Working directory (explicit path, required - no fallback)"),
|
|
95957
96352
|
reset_statuses: exports_external.boolean().optional().describe("When true, reset ALL task statuses to pending regardless of prior completion state. " + "Use only when deliberately re-planning a phase from scratch. " + "Default false (preserves existing task statuses across plan revisions)."),
|
|
96353
|
+
removed_task_ids: exports_external.array(exports_external.string()).optional().describe("Task IDs that are present in the prior plan but intentionally being " + "removed by this save. Every task missing from `phases` MUST be enumerated " + "here, otherwise save_plan rejects with PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED. " + "Tasks not yet finished (status pending/in_progress/blocked) MUST NOT be " + "removed without explicit user confirmation."),
|
|
96354
|
+
removal_reason: exports_external.string().optional().describe("Required when removed_task_ids is non-empty. Human-readable reason recorded " + "on each task_removed ledger event."),
|
|
96355
|
+
confirm_destructive_reset: exports_external.boolean().optional().describe("Required when reset_statuses is true AND at least one task is missing from " + "the new plan. Set true to acknowledge that the destructive reset drops " + "unfinished work. When set together with reset_statuses, save_plan auto-" + "populates removed_task_ids from the missing set."),
|
|
95958
96356
|
execution_profile: exports_external.object({
|
|
95959
96357
|
parallelization_enabled: exports_external.boolean().optional().describe("When true, enables parallel task dispatch for this plan. Default false (serial)."),
|
|
95960
96358
|
max_concurrent_tasks: exports_external.number().int().min(1).max(64).optional().describe("Maximum tasks that may run concurrently when parallelization is enabled. Default 1."),
|
|
@@ -95970,7 +96368,7 @@ var save_plan = createSwarmTool({
|
|
|
95970
96368
|
init_zod();
|
|
95971
96369
|
init_manager2();
|
|
95972
96370
|
import * as fs91 from "node:fs";
|
|
95973
|
-
import * as
|
|
96371
|
+
import * as path117 from "node:path";
|
|
95974
96372
|
|
|
95975
96373
|
// src/sbom/detectors/index.ts
|
|
95976
96374
|
init_utils();
|
|
@@ -96820,7 +97218,7 @@ function findManifestFiles(rootDir) {
|
|
|
96820
97218
|
try {
|
|
96821
97219
|
const entries = fs91.readdirSync(dir, { withFileTypes: true });
|
|
96822
97220
|
for (const entry of entries) {
|
|
96823
|
-
const fullPath =
|
|
97221
|
+
const fullPath = path117.join(dir, entry.name);
|
|
96824
97222
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
96825
97223
|
continue;
|
|
96826
97224
|
}
|
|
@@ -96829,7 +97227,7 @@ function findManifestFiles(rootDir) {
|
|
|
96829
97227
|
} else if (entry.isFile()) {
|
|
96830
97228
|
for (const pattern of patterns) {
|
|
96831
97229
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
96832
|
-
manifestFiles.push(
|
|
97230
|
+
manifestFiles.push(path117.relative(rootDir, fullPath));
|
|
96833
97231
|
break;
|
|
96834
97232
|
}
|
|
96835
97233
|
}
|
|
@@ -96847,11 +97245,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
96847
97245
|
try {
|
|
96848
97246
|
const entries = fs91.readdirSync(dir, { withFileTypes: true });
|
|
96849
97247
|
for (const entry of entries) {
|
|
96850
|
-
const fullPath =
|
|
97248
|
+
const fullPath = path117.join(dir, entry.name);
|
|
96851
97249
|
if (entry.isFile()) {
|
|
96852
97250
|
for (const pattern of patterns) {
|
|
96853
97251
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
96854
|
-
found.push(
|
|
97252
|
+
found.push(path117.relative(workingDir, fullPath));
|
|
96855
97253
|
break;
|
|
96856
97254
|
}
|
|
96857
97255
|
}
|
|
@@ -96864,11 +97262,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
96864
97262
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
96865
97263
|
const dirs = new Set;
|
|
96866
97264
|
for (const file3 of changedFiles) {
|
|
96867
|
-
let currentDir =
|
|
97265
|
+
let currentDir = path117.dirname(file3);
|
|
96868
97266
|
while (true) {
|
|
96869
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
96870
|
-
dirs.add(
|
|
96871
|
-
const parent =
|
|
97267
|
+
if (currentDir && currentDir !== "." && currentDir !== path117.sep) {
|
|
97268
|
+
dirs.add(path117.join(workingDir, currentDir));
|
|
97269
|
+
const parent = path117.dirname(currentDir);
|
|
96872
97270
|
if (parent === currentDir)
|
|
96873
97271
|
break;
|
|
96874
97272
|
currentDir = parent;
|
|
@@ -96952,7 +97350,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96952
97350
|
const changedFiles = obj.changed_files;
|
|
96953
97351
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
96954
97352
|
const workingDir = directory;
|
|
96955
|
-
const outputDir =
|
|
97353
|
+
const outputDir = path117.isAbsolute(relativeOutputDir) ? relativeOutputDir : path117.join(workingDir, relativeOutputDir);
|
|
96956
97354
|
let manifestFiles = [];
|
|
96957
97355
|
if (scope === "all") {
|
|
96958
97356
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -96975,7 +97373,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96975
97373
|
const processedFiles = [];
|
|
96976
97374
|
for (const manifestFile of manifestFiles) {
|
|
96977
97375
|
try {
|
|
96978
|
-
const fullPath =
|
|
97376
|
+
const fullPath = path117.isAbsolute(manifestFile) ? manifestFile : path117.join(workingDir, manifestFile);
|
|
96979
97377
|
if (!fs91.existsSync(fullPath)) {
|
|
96980
97378
|
continue;
|
|
96981
97379
|
}
|
|
@@ -96992,7 +97390,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96992
97390
|
const bom = generateCycloneDX(allComponents);
|
|
96993
97391
|
const bomJson = serializeCycloneDX(bom);
|
|
96994
97392
|
const filename = generateSbomFilename();
|
|
96995
|
-
const outputPath =
|
|
97393
|
+
const outputPath = path117.join(outputDir, filename);
|
|
96996
97394
|
fs91.writeFileSync(outputPath, bomJson, "utf-8");
|
|
96997
97395
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
96998
97396
|
try {
|
|
@@ -97036,7 +97434,7 @@ var sbom_generate = createSwarmTool({
|
|
|
97036
97434
|
init_zod();
|
|
97037
97435
|
init_create_tool();
|
|
97038
97436
|
import * as fs92 from "node:fs";
|
|
97039
|
-
import * as
|
|
97437
|
+
import * as path118 from "node:path";
|
|
97040
97438
|
var SPEC_CANDIDATES = [
|
|
97041
97439
|
"openapi.json",
|
|
97042
97440
|
"openapi.yaml",
|
|
@@ -97068,12 +97466,12 @@ function normalizePath4(p) {
|
|
|
97068
97466
|
}
|
|
97069
97467
|
function discoverSpecFile(cwd, specFileArg) {
|
|
97070
97468
|
if (specFileArg) {
|
|
97071
|
-
const resolvedPath =
|
|
97072
|
-
const normalizedCwd = cwd.endsWith(
|
|
97469
|
+
const resolvedPath = path118.resolve(cwd, specFileArg);
|
|
97470
|
+
const normalizedCwd = cwd.endsWith(path118.sep) ? cwd : cwd + path118.sep;
|
|
97073
97471
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
97074
97472
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
97075
97473
|
}
|
|
97076
|
-
const ext =
|
|
97474
|
+
const ext = path118.extname(resolvedPath).toLowerCase();
|
|
97077
97475
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
97078
97476
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
97079
97477
|
}
|
|
@@ -97087,7 +97485,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
97087
97485
|
return resolvedPath;
|
|
97088
97486
|
}
|
|
97089
97487
|
for (const candidate of SPEC_CANDIDATES) {
|
|
97090
|
-
const candidatePath =
|
|
97488
|
+
const candidatePath = path118.resolve(cwd, candidate);
|
|
97091
97489
|
if (fs92.existsSync(candidatePath)) {
|
|
97092
97490
|
const stats = fs92.statSync(candidatePath);
|
|
97093
97491
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -97099,7 +97497,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
97099
97497
|
}
|
|
97100
97498
|
function parseSpec(specFile) {
|
|
97101
97499
|
const content = fs92.readFileSync(specFile, "utf-8");
|
|
97102
|
-
const ext =
|
|
97500
|
+
const ext = path118.extname(specFile).toLowerCase();
|
|
97103
97501
|
if (ext === ".json") {
|
|
97104
97502
|
return parseJsonSpec(content);
|
|
97105
97503
|
}
|
|
@@ -97175,7 +97573,7 @@ function extractRoutes(cwd) {
|
|
|
97175
97573
|
return;
|
|
97176
97574
|
}
|
|
97177
97575
|
for (const entry of entries) {
|
|
97178
|
-
const fullPath =
|
|
97576
|
+
const fullPath = path118.join(dir, entry.name);
|
|
97179
97577
|
if (entry.isSymbolicLink()) {
|
|
97180
97578
|
continue;
|
|
97181
97579
|
}
|
|
@@ -97185,7 +97583,7 @@ function extractRoutes(cwd) {
|
|
|
97185
97583
|
}
|
|
97186
97584
|
walkDir(fullPath);
|
|
97187
97585
|
} else if (entry.isFile()) {
|
|
97188
|
-
const ext =
|
|
97586
|
+
const ext = path118.extname(entry.name).toLowerCase();
|
|
97189
97587
|
const baseName = entry.name.toLowerCase();
|
|
97190
97588
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
97191
97589
|
continue;
|
|
@@ -97353,7 +97751,7 @@ init_bun_compat();
|
|
|
97353
97751
|
init_path_security();
|
|
97354
97752
|
init_create_tool();
|
|
97355
97753
|
import * as fs93 from "node:fs";
|
|
97356
|
-
import * as
|
|
97754
|
+
import * as path119 from "node:path";
|
|
97357
97755
|
var DEFAULT_MAX_RESULTS = 100;
|
|
97358
97756
|
var DEFAULT_MAX_LINES = 200;
|
|
97359
97757
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -97389,11 +97787,11 @@ function containsWindowsAttacks3(str) {
|
|
|
97389
97787
|
}
|
|
97390
97788
|
function isPathInWorkspace3(filePath, workspace) {
|
|
97391
97789
|
try {
|
|
97392
|
-
const resolvedPath =
|
|
97790
|
+
const resolvedPath = path119.resolve(workspace, filePath);
|
|
97393
97791
|
const realWorkspace = fs93.realpathSync(workspace);
|
|
97394
97792
|
const realResolvedPath = fs93.realpathSync(resolvedPath);
|
|
97395
|
-
const relativePath =
|
|
97396
|
-
if (relativePath.startsWith("..") ||
|
|
97793
|
+
const relativePath = path119.relative(realWorkspace, realResolvedPath);
|
|
97794
|
+
if (relativePath.startsWith("..") || path119.isAbsolute(relativePath)) {
|
|
97397
97795
|
return false;
|
|
97398
97796
|
}
|
|
97399
97797
|
return true;
|
|
@@ -97406,11 +97804,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
97406
97804
|
}
|
|
97407
97805
|
function findRgInEnvPath() {
|
|
97408
97806
|
const searchPath = process.env.PATH ?? "";
|
|
97409
|
-
for (const dir of searchPath.split(
|
|
97807
|
+
for (const dir of searchPath.split(path119.delimiter)) {
|
|
97410
97808
|
if (!dir)
|
|
97411
97809
|
continue;
|
|
97412
97810
|
const isWindows = process.platform === "win32";
|
|
97413
|
-
const candidate =
|
|
97811
|
+
const candidate = path119.join(dir, isWindows ? "rg.exe" : "rg");
|
|
97414
97812
|
if (fs93.existsSync(candidate))
|
|
97415
97813
|
return candidate;
|
|
97416
97814
|
}
|
|
@@ -97540,8 +97938,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
97540
97938
|
try {
|
|
97541
97939
|
const entries = fs93.readdirSync(dir, { withFileTypes: true });
|
|
97542
97940
|
for (const entry of entries) {
|
|
97543
|
-
const fullPath =
|
|
97544
|
-
const relativePath =
|
|
97941
|
+
const fullPath = path119.join(dir, entry.name);
|
|
97942
|
+
const relativePath = path119.relative(workspace, fullPath);
|
|
97545
97943
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
97546
97944
|
continue;
|
|
97547
97945
|
}
|
|
@@ -97582,7 +97980,7 @@ async function fallbackSearch(opts) {
|
|
|
97582
97980
|
const matches = [];
|
|
97583
97981
|
let total = 0;
|
|
97584
97982
|
for (const file3 of files) {
|
|
97585
|
-
const fullPath =
|
|
97983
|
+
const fullPath = path119.join(opts.workspace, file3);
|
|
97586
97984
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
97587
97985
|
continue;
|
|
97588
97986
|
}
|
|
@@ -97950,7 +98348,7 @@ init_config();
|
|
|
97950
98348
|
init_schema();
|
|
97951
98349
|
init_create_tool();
|
|
97952
98350
|
import { mkdir as mkdir19, rename as rename8, writeFile as writeFile15 } from "node:fs/promises";
|
|
97953
|
-
import * as
|
|
98351
|
+
import * as path120 from "node:path";
|
|
97954
98352
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
97955
98353
|
var spec_write = createSwarmTool({
|
|
97956
98354
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -97991,8 +98389,8 @@ var spec_write = createSwarmTool({
|
|
|
97991
98389
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
97992
98390
|
}, null, 2);
|
|
97993
98391
|
}
|
|
97994
|
-
const target =
|
|
97995
|
-
await mkdir19(
|
|
98392
|
+
const target = path120.join(directory, ".swarm", "spec.md");
|
|
98393
|
+
await mkdir19(path120.dirname(target), { recursive: true });
|
|
97996
98394
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
97997
98395
|
let finalContent = content;
|
|
97998
98396
|
if (mode === "append") {
|
|
@@ -98020,14 +98418,14 @@ ${content}
|
|
|
98020
98418
|
init_zod();
|
|
98021
98419
|
init_loader();
|
|
98022
98420
|
import {
|
|
98023
|
-
existsSync as
|
|
98421
|
+
existsSync as existsSync70,
|
|
98024
98422
|
mkdirSync as mkdirSync29,
|
|
98025
|
-
readFileSync as
|
|
98423
|
+
readFileSync as readFileSync61,
|
|
98026
98424
|
renameSync as renameSync19,
|
|
98027
98425
|
unlinkSync as unlinkSync15,
|
|
98028
98426
|
writeFileSync as writeFileSync23
|
|
98029
98427
|
} from "node:fs";
|
|
98030
|
-
import
|
|
98428
|
+
import path121 from "node:path";
|
|
98031
98429
|
init_create_tool();
|
|
98032
98430
|
init_resolve_working_directory();
|
|
98033
98431
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -98157,9 +98555,9 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
98157
98555
|
}
|
|
98158
98556
|
});
|
|
98159
98557
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
98160
|
-
const mutationGatePath =
|
|
98558
|
+
const mutationGatePath = path121.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
98161
98559
|
try {
|
|
98162
|
-
const raw =
|
|
98560
|
+
const raw = readFileSync61(mutationGatePath, "utf-8");
|
|
98163
98561
|
const parsed = JSON.parse(raw);
|
|
98164
98562
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
98165
98563
|
if (!gateEntry) {
|
|
@@ -98219,9 +98617,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
98219
98617
|
}
|
|
98220
98618
|
}
|
|
98221
98619
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
98222
|
-
const evidenceDir =
|
|
98620
|
+
const evidenceDir = path121.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
98223
98621
|
mkdirSync29(evidenceDir, { recursive: true });
|
|
98224
|
-
const evidenceFile =
|
|
98622
|
+
const evidenceFile = path121.join(evidenceDir, "phase-council.json");
|
|
98225
98623
|
const evidenceBundle = {
|
|
98226
98624
|
entries: [
|
|
98227
98625
|
{
|
|
@@ -98257,7 +98655,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
98257
98655
|
writeFileSync23(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
98258
98656
|
renameSync19(tempFile, evidenceFile);
|
|
98259
98657
|
} finally {
|
|
98260
|
-
if (
|
|
98658
|
+
if (existsSync70(tempFile)) {
|
|
98261
98659
|
unlinkSync15(tempFile);
|
|
98262
98660
|
}
|
|
98263
98661
|
}
|
|
@@ -98307,7 +98705,7 @@ init_zod();
|
|
|
98307
98705
|
init_path_security();
|
|
98308
98706
|
init_create_tool();
|
|
98309
98707
|
import * as fs94 from "node:fs";
|
|
98310
|
-
import * as
|
|
98708
|
+
import * as path122 from "node:path";
|
|
98311
98709
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
98312
98710
|
function containsWindowsAttacks4(str) {
|
|
98313
98711
|
if (/:[^\\/]/.test(str))
|
|
@@ -98321,14 +98719,14 @@ function containsWindowsAttacks4(str) {
|
|
|
98321
98719
|
}
|
|
98322
98720
|
function isPathInWorkspace4(filePath, workspace) {
|
|
98323
98721
|
try {
|
|
98324
|
-
const resolvedPath =
|
|
98722
|
+
const resolvedPath = path122.resolve(workspace, filePath);
|
|
98325
98723
|
if (!fs94.existsSync(resolvedPath)) {
|
|
98326
98724
|
return true;
|
|
98327
98725
|
}
|
|
98328
98726
|
const realWorkspace = fs94.realpathSync(workspace);
|
|
98329
98727
|
const realResolvedPath = fs94.realpathSync(resolvedPath);
|
|
98330
|
-
const relativePath =
|
|
98331
|
-
if (relativePath.startsWith("..") ||
|
|
98728
|
+
const relativePath = path122.relative(realWorkspace, realResolvedPath);
|
|
98729
|
+
if (relativePath.startsWith("..") || path122.isAbsolute(relativePath)) {
|
|
98332
98730
|
return false;
|
|
98333
98731
|
}
|
|
98334
98732
|
return true;
|
|
@@ -98536,7 +98934,7 @@ var suggestPatch = createSwarmTool({
|
|
|
98536
98934
|
});
|
|
98537
98935
|
continue;
|
|
98538
98936
|
}
|
|
98539
|
-
const fullPath =
|
|
98937
|
+
const fullPath = path122.resolve(directory, change.file);
|
|
98540
98938
|
if (!fs94.existsSync(fullPath)) {
|
|
98541
98939
|
errors5.push({
|
|
98542
98940
|
success: false,
|
|
@@ -98840,11 +99238,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
98840
99238
|
init_zod();
|
|
98841
99239
|
init_constants();
|
|
98842
99240
|
import * as fs96 from "node:fs";
|
|
98843
|
-
import * as
|
|
99241
|
+
import * as path124 from "node:path";
|
|
98844
99242
|
|
|
98845
99243
|
// src/turbo/lean/conflicts.ts
|
|
98846
99244
|
import * as fs95 from "node:fs";
|
|
98847
|
-
import * as
|
|
99245
|
+
import * as path123 from "node:path";
|
|
98848
99246
|
var DEFAULT_GLOBAL_FILES = [
|
|
98849
99247
|
"package.json",
|
|
98850
99248
|
"package-lock.json",
|
|
@@ -98971,7 +99369,7 @@ function isProtectedPath2(normalizedPath) {
|
|
|
98971
99369
|
return false;
|
|
98972
99370
|
}
|
|
98973
99371
|
function readTaskScopes(directory, taskId) {
|
|
98974
|
-
const scopePath =
|
|
99372
|
+
const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
98975
99373
|
try {
|
|
98976
99374
|
if (!fs95.existsSync(scopePath)) {
|
|
98977
99375
|
return null;
|
|
@@ -99359,7 +99757,7 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
99359
99757
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
99360
99758
|
init_create_tool();
|
|
99361
99759
|
function readPlanJson(directory) {
|
|
99362
|
-
const planPath =
|
|
99760
|
+
const planPath = path124.join(directory, ".swarm", "plan.json");
|
|
99363
99761
|
if (!fs96.existsSync(planPath)) {
|
|
99364
99762
|
return null;
|
|
99365
99763
|
}
|
|
@@ -99414,7 +99812,7 @@ init_config();
|
|
|
99414
99812
|
// src/turbo/lean/reviewer.ts
|
|
99415
99813
|
init_state();
|
|
99416
99814
|
import * as fs97 from "node:fs/promises";
|
|
99417
|
-
import * as
|
|
99815
|
+
import * as path125 from "node:path";
|
|
99418
99816
|
init_state3();
|
|
99419
99817
|
var DEFAULT_CONFIG3 = {
|
|
99420
99818
|
reviewerAgent: "",
|
|
@@ -99530,9 +99928,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
99530
99928
|
return { verdict, reason };
|
|
99531
99929
|
}
|
|
99532
99930
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
99533
|
-
const evidenceDir =
|
|
99931
|
+
const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
|
|
99534
99932
|
await fs97.mkdir(evidenceDir, { recursive: true });
|
|
99535
|
-
const evidencePath =
|
|
99933
|
+
const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
99536
99934
|
const content = JSON.stringify({
|
|
99537
99935
|
phase,
|
|
99538
99936
|
verdict,
|
|
@@ -100337,7 +100735,7 @@ var lean_turbo_status = createSwarmTool({
|
|
|
100337
100735
|
init_spec_schema();
|
|
100338
100736
|
init_create_tool();
|
|
100339
100737
|
import * as fs98 from "node:fs";
|
|
100340
|
-
import * as
|
|
100738
|
+
import * as path126 from "node:path";
|
|
100341
100739
|
var SPEC_FILE_NAME = "spec.md";
|
|
100342
100740
|
var SWARM_DIR2 = ".swarm";
|
|
100343
100741
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -100390,7 +100788,7 @@ var lint_spec = createSwarmTool({
|
|
|
100390
100788
|
async execute(_args, directory) {
|
|
100391
100789
|
const errors5 = [];
|
|
100392
100790
|
const warnings = [];
|
|
100393
|
-
const specPath =
|
|
100791
|
+
const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
100394
100792
|
if (!fs98.existsSync(specPath)) {
|
|
100395
100793
|
const result2 = {
|
|
100396
100794
|
valid: false,
|
|
@@ -100461,12 +100859,12 @@ var lint_spec = createSwarmTool({
|
|
|
100461
100859
|
// src/tools/mutation-test.ts
|
|
100462
100860
|
init_zod();
|
|
100463
100861
|
import * as fs99 from "node:fs";
|
|
100464
|
-
import * as
|
|
100862
|
+
import * as path128 from "node:path";
|
|
100465
100863
|
|
|
100466
100864
|
// src/mutation/engine.ts
|
|
100467
100865
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
100468
100866
|
import { unlinkSync as unlinkSync16, writeFileSync as writeFileSync24 } from "node:fs";
|
|
100469
|
-
import * as
|
|
100867
|
+
import * as path127 from "node:path";
|
|
100470
100868
|
|
|
100471
100869
|
// src/mutation/equivalence.ts
|
|
100472
100870
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -100606,7 +101004,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
100606
101004
|
let patchFile;
|
|
100607
101005
|
try {
|
|
100608
101006
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
100609
|
-
patchFile =
|
|
101007
|
+
patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
100610
101008
|
try {
|
|
100611
101009
|
writeFileSync24(patchFile, patch.patch);
|
|
100612
101010
|
} catch (writeErr) {
|
|
@@ -101005,7 +101403,7 @@ var mutation_test = createSwarmTool({
|
|
|
101005
101403
|
];
|
|
101006
101404
|
for (const filePath of uniquePaths) {
|
|
101007
101405
|
try {
|
|
101008
|
-
const resolvedPath =
|
|
101406
|
+
const resolvedPath = path128.resolve(cwd, filePath);
|
|
101009
101407
|
sourceFiles.set(filePath, fs99.readFileSync(resolvedPath, "utf-8"));
|
|
101010
101408
|
} catch {}
|
|
101011
101409
|
}
|
|
@@ -101025,7 +101423,7 @@ init_zod();
|
|
|
101025
101423
|
init_manager2();
|
|
101026
101424
|
init_detector();
|
|
101027
101425
|
import * as fs100 from "node:fs";
|
|
101028
|
-
import * as
|
|
101426
|
+
import * as path129 from "node:path";
|
|
101029
101427
|
init_create_tool();
|
|
101030
101428
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
101031
101429
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -101091,7 +101489,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101091
101489
|
if (languages?.length) {
|
|
101092
101490
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
101093
101491
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
101094
|
-
const ext =
|
|
101492
|
+
const ext = path129.extname(file3.path).toLowerCase();
|
|
101095
101493
|
const langDef = getLanguageForExtension(ext);
|
|
101096
101494
|
const fileProfile = getProfileForFile(file3.path);
|
|
101097
101495
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -101104,7 +101502,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101104
101502
|
let skippedCount = 0;
|
|
101105
101503
|
for (const fileInfo of filesToCheck) {
|
|
101106
101504
|
const { path: filePath } = fileInfo;
|
|
101107
|
-
const fullPath =
|
|
101505
|
+
const fullPath = path129.isAbsolute(filePath) ? filePath : path129.join(directory, filePath);
|
|
101108
101506
|
const result = {
|
|
101109
101507
|
path: filePath,
|
|
101110
101508
|
language: "",
|
|
@@ -101153,7 +101551,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101153
101551
|
results.push(result);
|
|
101154
101552
|
continue;
|
|
101155
101553
|
}
|
|
101156
|
-
const ext =
|
|
101554
|
+
const ext = path129.extname(filePath).toLowerCase();
|
|
101157
101555
|
const langDef = getLanguageForExtension(ext);
|
|
101158
101556
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
101159
101557
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -101246,7 +101644,7 @@ init_utils();
|
|
|
101246
101644
|
init_create_tool();
|
|
101247
101645
|
init_path_security();
|
|
101248
101646
|
import * as fs101 from "node:fs";
|
|
101249
|
-
import * as
|
|
101647
|
+
import * as path130 from "node:path";
|
|
101250
101648
|
var MAX_TEXT_LENGTH = 200;
|
|
101251
101649
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
101252
101650
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -101312,9 +101710,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
101312
101710
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
101313
101711
|
}
|
|
101314
101712
|
try {
|
|
101315
|
-
const resolvedPath =
|
|
101316
|
-
const normalizedCwd =
|
|
101317
|
-
const normalizedResolved =
|
|
101713
|
+
const resolvedPath = path130.resolve(paths);
|
|
101714
|
+
const normalizedCwd = path130.resolve(cwd);
|
|
101715
|
+
const normalizedResolved = path130.resolve(resolvedPath);
|
|
101318
101716
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
101319
101717
|
return {
|
|
101320
101718
|
error: "paths must be within the current working directory",
|
|
@@ -101330,7 +101728,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
101330
101728
|
}
|
|
101331
101729
|
}
|
|
101332
101730
|
function isSupportedExtension(filePath) {
|
|
101333
|
-
const ext =
|
|
101731
|
+
const ext = path130.extname(filePath).toLowerCase();
|
|
101334
101732
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
101335
101733
|
}
|
|
101336
101734
|
function findSourceFiles3(dir, files = []) {
|
|
@@ -101345,7 +101743,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
101345
101743
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
101346
101744
|
continue;
|
|
101347
101745
|
}
|
|
101348
|
-
const fullPath =
|
|
101746
|
+
const fullPath = path130.join(dir, entry);
|
|
101349
101747
|
let stat8;
|
|
101350
101748
|
try {
|
|
101351
101749
|
stat8 = fs101.statSync(fullPath);
|
|
@@ -101457,7 +101855,7 @@ var todo_extract = createSwarmTool({
|
|
|
101457
101855
|
filesToScan.push(scanPath);
|
|
101458
101856
|
} else {
|
|
101459
101857
|
const errorResult = {
|
|
101460
|
-
error: `unsupported file extension: ${
|
|
101858
|
+
error: `unsupported file extension: ${path130.extname(scanPath)}`,
|
|
101461
101859
|
total: 0,
|
|
101462
101860
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
101463
101861
|
entries: []
|
|
@@ -101506,17 +101904,17 @@ init_schema();
|
|
|
101506
101904
|
init_qa_gate_profile();
|
|
101507
101905
|
init_gate_evidence();
|
|
101508
101906
|
import * as fs105 from "node:fs";
|
|
101509
|
-
import * as
|
|
101907
|
+
import * as path134 from "node:path";
|
|
101510
101908
|
|
|
101511
101909
|
// src/hooks/diff-scope.ts
|
|
101512
101910
|
init_bun_compat();
|
|
101513
101911
|
import * as fs103 from "node:fs";
|
|
101514
|
-
import * as
|
|
101912
|
+
import * as path132 from "node:path";
|
|
101515
101913
|
|
|
101516
101914
|
// src/utils/gitignore-warning.ts
|
|
101517
101915
|
init_bun_compat();
|
|
101518
101916
|
import * as fs102 from "node:fs";
|
|
101519
|
-
import * as
|
|
101917
|
+
import * as path131 from "node:path";
|
|
101520
101918
|
var _internals48 = { bunSpawn };
|
|
101521
101919
|
var _swarmGitExcludedChecked = false;
|
|
101522
101920
|
function fileCoversSwarm(content) {
|
|
@@ -101590,10 +101988,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
101590
101988
|
const excludeRelPath = excludePathRaw.trim();
|
|
101591
101989
|
if (!excludeRelPath)
|
|
101592
101990
|
return;
|
|
101593
|
-
const excludePath =
|
|
101991
|
+
const excludePath = path131.isAbsolute(excludeRelPath) ? excludeRelPath : path131.join(directory, excludeRelPath);
|
|
101594
101992
|
if (checkIgnoreExitCode !== 0) {
|
|
101595
101993
|
try {
|
|
101596
|
-
fs102.mkdirSync(
|
|
101994
|
+
fs102.mkdirSync(path131.dirname(excludePath), { recursive: true });
|
|
101597
101995
|
let existing = "";
|
|
101598
101996
|
try {
|
|
101599
101997
|
existing = fs102.readFileSync(excludePath, "utf8");
|
|
@@ -101637,7 +102035,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
101637
102035
|
var _internals49 = { bunSpawn };
|
|
101638
102036
|
function getDeclaredScope(taskId, directory) {
|
|
101639
102037
|
try {
|
|
101640
|
-
const planPath =
|
|
102038
|
+
const planPath = path132.join(directory, ".swarm", "plan.json");
|
|
101641
102039
|
if (!fs103.existsSync(planPath))
|
|
101642
102040
|
return null;
|
|
101643
102041
|
const raw = fs103.readFileSync(planPath, "utf-8");
|
|
@@ -101743,7 +102141,7 @@ init_telemetry();
|
|
|
101743
102141
|
// src/turbo/lean/task-completion.ts
|
|
101744
102142
|
init_file_locks();
|
|
101745
102143
|
import * as fs104 from "node:fs";
|
|
101746
|
-
import * as
|
|
102144
|
+
import * as path133 from "node:path";
|
|
101747
102145
|
var _internals50 = {
|
|
101748
102146
|
listActiveLocks,
|
|
101749
102147
|
verifyLeanTurboTaskCompletion
|
|
@@ -101762,7 +102160,7 @@ var TIER_3_PATTERNS = [
|
|
|
101762
102160
|
];
|
|
101763
102161
|
function matchesTier3Pattern(files) {
|
|
101764
102162
|
for (const file3 of files) {
|
|
101765
|
-
const fileName =
|
|
102163
|
+
const fileName = path133.basename(file3);
|
|
101766
102164
|
for (const pattern of TIER_3_PATTERNS) {
|
|
101767
102165
|
if (pattern.test(fileName)) {
|
|
101768
102166
|
return true;
|
|
@@ -101774,7 +102172,7 @@ function matchesTier3Pattern(files) {
|
|
|
101774
102172
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
101775
102173
|
let persisted = null;
|
|
101776
102174
|
try {
|
|
101777
|
-
const statePath =
|
|
102175
|
+
const statePath = path133.join(directory, ".swarm", "turbo-state.json");
|
|
101778
102176
|
if (!fs104.existsSync(statePath)) {
|
|
101779
102177
|
return {
|
|
101780
102178
|
ok: false,
|
|
@@ -101858,11 +102256,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
101858
102256
|
};
|
|
101859
102257
|
}
|
|
101860
102258
|
const phase = runState.phase ?? 0;
|
|
101861
|
-
const evidencePath =
|
|
101862
|
-
const expectedDir =
|
|
101863
|
-
const resolvedPath =
|
|
101864
|
-
const resolvedDir =
|
|
101865
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
102259
|
+
const evidencePath = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
102260
|
+
const expectedDir = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
102261
|
+
const resolvedPath = path133.resolve(evidencePath);
|
|
102262
|
+
const resolvedDir = path133.resolve(expectedDir);
|
|
102263
|
+
if (!resolvedPath.startsWith(resolvedDir + path133.sep) && resolvedPath !== resolvedDir) {
|
|
101866
102264
|
return {
|
|
101867
102265
|
ok: false,
|
|
101868
102266
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -101902,7 +102300,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
101902
102300
|
}
|
|
101903
102301
|
let filesTouched = [];
|
|
101904
102302
|
try {
|
|
101905
|
-
const planPath =
|
|
102303
|
+
const planPath = path133.join(directory, ".swarm", "plan.json");
|
|
101906
102304
|
const planRaw = fs104.readFileSync(planPath, "utf-8");
|
|
101907
102305
|
const plan = JSON.parse(planRaw);
|
|
101908
102306
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -101985,7 +102383,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
101985
102383
|
];
|
|
101986
102384
|
function matchesTier3Pattern2(files) {
|
|
101987
102385
|
for (const file3 of files) {
|
|
101988
|
-
const fileName =
|
|
102386
|
+
const fileName = path134.basename(file3);
|
|
101989
102387
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
101990
102388
|
if (pattern.test(fileName)) {
|
|
101991
102389
|
return true;
|
|
@@ -102017,7 +102415,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102017
102415
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
102018
102416
|
const resolvedDir2 = workingDirectory;
|
|
102019
102417
|
try {
|
|
102020
|
-
const planPath =
|
|
102418
|
+
const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
|
|
102021
102419
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102022
102420
|
const plan = JSON.parse(planRaw);
|
|
102023
102421
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -102084,7 +102482,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102084
102482
|
}
|
|
102085
102483
|
try {
|
|
102086
102484
|
const resolvedDir2 = workingDirectory;
|
|
102087
|
-
const planPath =
|
|
102485
|
+
const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
|
|
102088
102486
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102089
102487
|
const plan = JSON.parse(planRaw);
|
|
102090
102488
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -102269,8 +102667,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102269
102667
|
};
|
|
102270
102668
|
}
|
|
102271
102669
|
}
|
|
102272
|
-
normalizedDir =
|
|
102273
|
-
const pathParts = normalizedDir.split(
|
|
102670
|
+
normalizedDir = path134.normalize(args2.working_directory);
|
|
102671
|
+
const pathParts = normalizedDir.split(path134.sep);
|
|
102274
102672
|
if (pathParts.includes("..")) {
|
|
102275
102673
|
return {
|
|
102276
102674
|
success: false,
|
|
@@ -102280,10 +102678,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102280
102678
|
]
|
|
102281
102679
|
};
|
|
102282
102680
|
}
|
|
102283
|
-
const resolvedDir =
|
|
102681
|
+
const resolvedDir = path134.resolve(normalizedDir);
|
|
102284
102682
|
try {
|
|
102285
102683
|
const realPath = fs105.realpathSync(resolvedDir);
|
|
102286
|
-
const planPath =
|
|
102684
|
+
const planPath = path134.join(realPath, ".swarm", "plan.json");
|
|
102287
102685
|
if (!fs105.existsSync(planPath)) {
|
|
102288
102686
|
return {
|
|
102289
102687
|
success: false,
|
|
@@ -102315,8 +102713,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102315
102713
|
}
|
|
102316
102714
|
if (args2.status === "in_progress") {
|
|
102317
102715
|
try {
|
|
102318
|
-
const evidencePath =
|
|
102319
|
-
fs105.mkdirSync(
|
|
102716
|
+
const evidencePath = path134.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
102717
|
+
fs105.mkdirSync(path134.dirname(evidencePath), { recursive: true });
|
|
102320
102718
|
const fd = fs105.openSync(evidencePath, "wx");
|
|
102321
102719
|
let writeOk = false;
|
|
102322
102720
|
try {
|
|
@@ -102340,7 +102738,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102340
102738
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
102341
102739
|
let phaseRequiresReviewer = true;
|
|
102342
102740
|
try {
|
|
102343
|
-
const planPath =
|
|
102741
|
+
const planPath = path134.join(directory, ".swarm", "plan.json");
|
|
102344
102742
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102345
102743
|
const plan = JSON.parse(planRaw);
|
|
102346
102744
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -102652,7 +103050,7 @@ init_ledger();
|
|
|
102652
103050
|
init_manager();
|
|
102653
103051
|
init_create_tool();
|
|
102654
103052
|
import fs106 from "node:fs";
|
|
102655
|
-
import
|
|
103053
|
+
import path135 from "node:path";
|
|
102656
103054
|
function normalizeVerdict(verdict) {
|
|
102657
103055
|
switch (verdict) {
|
|
102658
103056
|
case "APPROVED":
|
|
@@ -102700,7 +103098,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
102700
103098
|
entries: [evidenceEntry]
|
|
102701
103099
|
};
|
|
102702
103100
|
const filename = "drift-verifier.json";
|
|
102703
|
-
const relativePath =
|
|
103101
|
+
const relativePath = path135.join("evidence", String(phase), filename);
|
|
102704
103102
|
let validatedPath;
|
|
102705
103103
|
try {
|
|
102706
103104
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -102711,10 +103109,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
102711
103109
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
102712
103110
|
}, null, 2);
|
|
102713
103111
|
}
|
|
102714
|
-
const evidenceDir =
|
|
103112
|
+
const evidenceDir = path135.dirname(validatedPath);
|
|
102715
103113
|
try {
|
|
102716
103114
|
await fs106.promises.mkdir(evidenceDir, { recursive: true });
|
|
102717
|
-
const tempPath =
|
|
103115
|
+
const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
|
|
102718
103116
|
await fs106.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
102719
103117
|
await fs106.promises.rename(tempPath, validatedPath);
|
|
102720
103118
|
let snapshotInfo;
|
|
@@ -102810,7 +103208,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
102810
103208
|
init_zod();
|
|
102811
103209
|
init_loader();
|
|
102812
103210
|
import fs107 from "node:fs";
|
|
102813
|
-
import
|
|
103211
|
+
import path136 from "node:path";
|
|
102814
103212
|
init_utils2();
|
|
102815
103213
|
init_manager();
|
|
102816
103214
|
init_create_tool();
|
|
@@ -102898,7 +103296,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
102898
103296
|
timestamp: synthesis.timestamp
|
|
102899
103297
|
};
|
|
102900
103298
|
const filename = "final-council.json";
|
|
102901
|
-
const relativePath =
|
|
103299
|
+
const relativePath = path136.join("evidence", filename);
|
|
102902
103300
|
let validatedPath;
|
|
102903
103301
|
try {
|
|
102904
103302
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -102912,10 +103310,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
102912
103310
|
const evidenceContent = {
|
|
102913
103311
|
entries: [evidenceEntry]
|
|
102914
103312
|
};
|
|
102915
|
-
const evidenceDir =
|
|
103313
|
+
const evidenceDir = path136.dirname(validatedPath);
|
|
102916
103314
|
try {
|
|
102917
103315
|
await fs107.promises.mkdir(evidenceDir, { recursive: true });
|
|
102918
|
-
const tempPath =
|
|
103316
|
+
const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
|
|
102919
103317
|
await fs107.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
102920
103318
|
await fs107.promises.rename(tempPath, validatedPath);
|
|
102921
103319
|
return JSON.stringify({
|
|
@@ -102974,7 +103372,7 @@ init_zod();
|
|
|
102974
103372
|
init_utils2();
|
|
102975
103373
|
init_create_tool();
|
|
102976
103374
|
import fs108 from "node:fs";
|
|
102977
|
-
import
|
|
103375
|
+
import path137 from "node:path";
|
|
102978
103376
|
function normalizeVerdict2(verdict) {
|
|
102979
103377
|
switch (verdict) {
|
|
102980
103378
|
case "APPROVED":
|
|
@@ -103022,7 +103420,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103022
103420
|
entries: [evidenceEntry]
|
|
103023
103421
|
};
|
|
103024
103422
|
const filename = "hallucination-guard.json";
|
|
103025
|
-
const relativePath =
|
|
103423
|
+
const relativePath = path137.join("evidence", String(phase), filename);
|
|
103026
103424
|
let validatedPath;
|
|
103027
103425
|
try {
|
|
103028
103426
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103033,10 +103431,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103033
103431
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103034
103432
|
}, null, 2);
|
|
103035
103433
|
}
|
|
103036
|
-
const evidenceDir =
|
|
103434
|
+
const evidenceDir = path137.dirname(validatedPath);
|
|
103037
103435
|
try {
|
|
103038
103436
|
await fs108.promises.mkdir(evidenceDir, { recursive: true });
|
|
103039
|
-
const tempPath =
|
|
103437
|
+
const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
|
|
103040
103438
|
await fs108.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
103041
103439
|
await fs108.promises.rename(tempPath, validatedPath);
|
|
103042
103440
|
return JSON.stringify({
|
|
@@ -103085,7 +103483,7 @@ init_zod();
|
|
|
103085
103483
|
init_utils2();
|
|
103086
103484
|
init_create_tool();
|
|
103087
103485
|
import fs109 from "node:fs";
|
|
103088
|
-
import
|
|
103486
|
+
import path138 from "node:path";
|
|
103089
103487
|
function normalizeVerdict3(verdict) {
|
|
103090
103488
|
switch (verdict) {
|
|
103091
103489
|
case "PASS":
|
|
@@ -103159,7 +103557,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103159
103557
|
entries: [evidenceEntry]
|
|
103160
103558
|
};
|
|
103161
103559
|
const filename = "mutation-gate.json";
|
|
103162
|
-
const relativePath =
|
|
103560
|
+
const relativePath = path138.join("evidence", String(phase), filename);
|
|
103163
103561
|
let validatedPath;
|
|
103164
103562
|
try {
|
|
103165
103563
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103170,10 +103568,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103170
103568
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103171
103569
|
}, null, 2);
|
|
103172
103570
|
}
|
|
103173
|
-
const evidenceDir =
|
|
103571
|
+
const evidenceDir = path138.dirname(validatedPath);
|
|
103174
103572
|
try {
|
|
103175
103573
|
await fs109.promises.mkdir(evidenceDir, { recursive: true });
|
|
103176
|
-
const tempPath =
|
|
103574
|
+
const tempPath = path138.join(evidenceDir, `.${filename}.tmp`);
|
|
103177
103575
|
await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
103178
103576
|
await fs109.promises.rename(tempPath, validatedPath);
|
|
103179
103577
|
return JSON.stringify({
|
|
@@ -103518,7 +103916,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
103518
103916
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
103519
103917
|
preflightTriggerManager = new PTM(automationConfig);
|
|
103520
103918
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
103521
|
-
const swarmDir =
|
|
103919
|
+
const swarmDir = path140.resolve(ctx.directory, ".swarm");
|
|
103522
103920
|
statusArtifact = new ASA(swarmDir);
|
|
103523
103921
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
103524
103922
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|