opencode-swarm 7.19.0 → 7.19.1
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 +213 -32
- 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 +960 -595
- 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/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.1",
|
|
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") {
|
|
@@ -59956,6 +60101,25 @@ var init_context_budget_service = __esm(() => {
|
|
|
59956
60101
|
});
|
|
59957
60102
|
|
|
59958
60103
|
// src/services/status-service.ts
|
|
60104
|
+
import * as fsSync3 from "node:fs";
|
|
60105
|
+
import * as path54 from "node:path";
|
|
60106
|
+
function readSpecStalenessSnapshot(directory) {
|
|
60107
|
+
try {
|
|
60108
|
+
const p = path54.join(directory, ".swarm", "spec-staleness.json");
|
|
60109
|
+
if (!fsSync3.existsSync(p))
|
|
60110
|
+
return { stale: false };
|
|
60111
|
+
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
60112
|
+
const parsed = JSON.parse(raw);
|
|
60113
|
+
return {
|
|
60114
|
+
stale: true,
|
|
60115
|
+
reason: typeof parsed?.reason === "string" ? parsed.reason : undefined,
|
|
60116
|
+
storedHash: typeof parsed?.specHash_plan === "string" ? parsed.specHash_plan : undefined,
|
|
60117
|
+
currentHash: typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null ? parsed.specHash_current : undefined
|
|
60118
|
+
};
|
|
60119
|
+
} catch {
|
|
60120
|
+
return { stale: false };
|
|
60121
|
+
}
|
|
60122
|
+
}
|
|
59959
60123
|
async function getStatusData(directory, agents) {
|
|
59960
60124
|
const plan = await loadPlan(directory);
|
|
59961
60125
|
let status;
|
|
@@ -60021,6 +60185,16 @@ async function getStatusData(directory, agents) {
|
|
|
60021
60185
|
};
|
|
60022
60186
|
}
|
|
60023
60187
|
}
|
|
60188
|
+
const drift = readSpecStalenessSnapshot(directory);
|
|
60189
|
+
if (drift.stale) {
|
|
60190
|
+
status.specStale = true;
|
|
60191
|
+
status.specStaleReason = drift.reason;
|
|
60192
|
+
status.specStaleStoredHash = drift.storedHash;
|
|
60193
|
+
status.specStaleCurrentHash = drift.currentHash;
|
|
60194
|
+
} else if (plan && plan._specStale) {
|
|
60195
|
+
status.specStale = true;
|
|
60196
|
+
status.specStaleReason = plan._specStaleReason;
|
|
60197
|
+
}
|
|
60024
60198
|
return enrichWithLeanTurbo(status, directory);
|
|
60025
60199
|
}
|
|
60026
60200
|
function enrichWithLeanTurbo(status, directory) {
|
|
@@ -60087,6 +60261,12 @@ function formatStatusMarkdown(status) {
|
|
|
60087
60261
|
`**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,
|
|
60088
60262
|
`**Agents**: ${status.agentCount} registered`
|
|
60089
60263
|
];
|
|
60264
|
+
if (status.specStale) {
|
|
60265
|
+
const reason = status.specStaleReason ?? "spec.md changed since plan saved";
|
|
60266
|
+
const stored = status.specStaleStoredHash ?? "unknown";
|
|
60267
|
+
const current = status.specStaleCurrentHash ?? "(spec.md missing)";
|
|
60268
|
+
lines.push("", `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`, "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.");
|
|
60269
|
+
}
|
|
60090
60270
|
if (status.turboStrategy && status.turboStrategy !== "off") {
|
|
60091
60271
|
lines.push("");
|
|
60092
60272
|
if (status.turboStrategy === "lean") {
|
|
@@ -60136,6 +60316,18 @@ function formatStatusMarkdown(status) {
|
|
|
60136
60316
|
async function handleStatusCommand(directory, agents) {
|
|
60137
60317
|
const statusData = await getStatusData(directory, agents);
|
|
60138
60318
|
if (!statusData.hasPlan) {
|
|
60319
|
+
if (statusData.specStale) {
|
|
60320
|
+
const reason = statusData.specStaleReason ?? "spec.md changed since plan saved";
|
|
60321
|
+
const stored = statusData.specStaleStoredHash ?? "unknown";
|
|
60322
|
+
const current = statusData.specStaleCurrentHash ?? "(spec.md missing)";
|
|
60323
|
+
return [
|
|
60324
|
+
"No active swarm plan found.",
|
|
60325
|
+
"",
|
|
60326
|
+
`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,
|
|
60327
|
+
"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."
|
|
60328
|
+
].join(`
|
|
60329
|
+
`);
|
|
60330
|
+
}
|
|
60139
60331
|
return "No active swarm plan found.";
|
|
60140
60332
|
}
|
|
60141
60333
|
return formatStatusMarkdown(statusData);
|
|
@@ -60439,7 +60631,7 @@ var init_write_retro2 = __esm(() => {
|
|
|
60439
60631
|
|
|
60440
60632
|
// src/commands/command-dispatch.ts
|
|
60441
60633
|
import fs36 from "node:fs";
|
|
60442
|
-
import
|
|
60634
|
+
import path55 from "node:path";
|
|
60443
60635
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
60444
60636
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
60445
60637
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -60475,9 +60667,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
60475
60667
|
`);
|
|
60476
60668
|
}
|
|
60477
60669
|
function maybeMarkFirstRun(directory) {
|
|
60478
|
-
const sentinelPath =
|
|
60670
|
+
const sentinelPath = path55.join(directory, ".swarm", ".first-run-complete");
|
|
60479
60671
|
try {
|
|
60480
|
-
const swarmDir =
|
|
60672
|
+
const swarmDir = path55.join(directory, ".swarm");
|
|
60481
60673
|
fs36.mkdirSync(swarmDir, { recursive: true });
|
|
60482
60674
|
fs36.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
60483
60675
|
`, { flag: "wx" });
|
|
@@ -61145,24 +61337,24 @@ function validateAliases() {
|
|
|
61145
61337
|
}
|
|
61146
61338
|
aliasTargets.get(target).push(name2);
|
|
61147
61339
|
const visited = new Set;
|
|
61148
|
-
const
|
|
61340
|
+
const path56 = [];
|
|
61149
61341
|
let current = target;
|
|
61150
61342
|
while (current) {
|
|
61151
61343
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
61152
61344
|
if (!currentEntry)
|
|
61153
61345
|
break;
|
|
61154
61346
|
if (visited.has(current)) {
|
|
61155
|
-
const cycleStart =
|
|
61347
|
+
const cycleStart = path56.indexOf(current);
|
|
61156
61348
|
const fullChain = [
|
|
61157
61349
|
name2,
|
|
61158
|
-
...
|
|
61350
|
+
...path56.slice(0, cycleStart > 0 ? cycleStart : path56.length),
|
|
61159
61351
|
current
|
|
61160
61352
|
].join(" → ");
|
|
61161
61353
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
61162
61354
|
break;
|
|
61163
61355
|
}
|
|
61164
61356
|
visited.add(current);
|
|
61165
|
-
|
|
61357
|
+
path56.push(current);
|
|
61166
61358
|
current = currentEntry.aliasOf || "";
|
|
61167
61359
|
}
|
|
61168
61360
|
}
|
|
@@ -63375,6 +63567,18 @@ If resuming a project with an existing approved plan, CRITIC-GATE is already sat
|
|
|
63375
63567
|
- Run /swarm clarify to update the spec and align it with the plan, OR
|
|
63376
63568
|
- Run /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings
|
|
63377
63569
|
- Do NOT proceed with implementation until spec staleness is resolved.
|
|
63570
|
+
- When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task
|
|
63571
|
+
present in the prior plan but absent from the new args.phases be enumerated
|
|
63572
|
+
in removed_task_ids with a removal_reason. save_plan will reject the call
|
|
63573
|
+
otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished
|
|
63574
|
+
(status: pending, in_progress, blocked) MUST NOT be removed without explicit
|
|
63575
|
+
user confirmation — surface the list to the user and ask before populating
|
|
63576
|
+
removed_task_ids.
|
|
63577
|
+
- While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the
|
|
63578
|
+
following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,
|
|
63579
|
+
phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call
|
|
63580
|
+
returns SPEC_DRIFT_BLOCK, do NOT retry; instead present the drift to the
|
|
63581
|
+
user and run /swarm clarify or /swarm acknowledge-spec-drift first.
|
|
63378
63582
|
|
|
63379
63583
|
### MODE: EXECUTE
|
|
63380
63584
|
For each task (respecting dependencies):
|
|
@@ -65785,7 +65989,7 @@ COVERAGE REPORTING:
|
|
|
65785
65989
|
|
|
65786
65990
|
// src/agents/index.ts
|
|
65787
65991
|
import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
|
|
65788
|
-
import * as
|
|
65992
|
+
import * as path56 from "node:path";
|
|
65789
65993
|
function stripSwarmPrefix(agentName, swarmPrefix) {
|
|
65790
65994
|
if (!swarmPrefix || !agentName)
|
|
65791
65995
|
return agentName;
|
|
@@ -66181,14 +66385,14 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
|
|
|
66181
66385
|
}));
|
|
66182
66386
|
if (directory) {
|
|
66183
66387
|
const sid = sessionId ?? `init-${Date.now()}`;
|
|
66184
|
-
const evidenceDir =
|
|
66388
|
+
const evidenceDir = path56.join(directory, ".swarm", "evidence");
|
|
66185
66389
|
const filename = `agent-tools-${sid}.json`;
|
|
66186
66390
|
const snapshotData = JSON.stringify({
|
|
66187
66391
|
sessionId: sid,
|
|
66188
66392
|
generatedAt: new Date().toISOString(),
|
|
66189
66393
|
agents: agentToolSnapshot
|
|
66190
66394
|
}, null, 2);
|
|
66191
|
-
mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(
|
|
66395
|
+
mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path56.join(evidenceDir, filename), snapshotData)).catch(() => {});
|
|
66192
66396
|
}
|
|
66193
66397
|
return result;
|
|
66194
66398
|
}
|
|
@@ -66225,14 +66429,14 @@ __export(exports_evidence_summary_integration, {
|
|
|
66225
66429
|
createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
|
|
66226
66430
|
EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
|
|
66227
66431
|
});
|
|
66228
|
-
import { existsSync as
|
|
66229
|
-
import * as
|
|
66432
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
|
|
66433
|
+
import * as path57 from "node:path";
|
|
66230
66434
|
function persistSummary(projectDir, artifact, filename) {
|
|
66231
|
-
const swarmPath =
|
|
66232
|
-
if (!
|
|
66435
|
+
const swarmPath = path57.join(projectDir, ".swarm");
|
|
66436
|
+
if (!existsSync32(swarmPath)) {
|
|
66233
66437
|
mkdirSync16(swarmPath, { recursive: true });
|
|
66234
66438
|
}
|
|
66235
|
-
const artifactPath =
|
|
66439
|
+
const artifactPath = path57.join(swarmPath, filename);
|
|
66236
66440
|
const content = JSON.stringify(artifact, null, 2);
|
|
66237
66441
|
writeFileSync8(artifactPath, content, "utf-8");
|
|
66238
66442
|
log("[EvidenceSummaryIntegration] Summary persisted", {
|
|
@@ -66351,7 +66555,7 @@ __export(exports_status_artifact, {
|
|
|
66351
66555
|
AutomationStatusArtifact: () => AutomationStatusArtifact
|
|
66352
66556
|
});
|
|
66353
66557
|
import * as fs38 from "node:fs";
|
|
66354
|
-
import * as
|
|
66558
|
+
import * as path59 from "node:path";
|
|
66355
66559
|
function createEmptySnapshot(mode, capabilities) {
|
|
66356
66560
|
return {
|
|
66357
66561
|
timestamp: Date.now(),
|
|
@@ -66410,7 +66614,7 @@ class AutomationStatusArtifact {
|
|
|
66410
66614
|
});
|
|
66411
66615
|
}
|
|
66412
66616
|
getFilePath() {
|
|
66413
|
-
return
|
|
66617
|
+
return path59.join(this.swarmDir, this.filename);
|
|
66414
66618
|
}
|
|
66415
66619
|
load() {
|
|
66416
66620
|
const filePath = this.getFilePath();
|
|
@@ -66823,12 +67027,12 @@ __export(exports_review_receipt, {
|
|
|
66823
67027
|
});
|
|
66824
67028
|
import * as crypto5 from "node:crypto";
|
|
66825
67029
|
import * as fs44 from "node:fs";
|
|
66826
|
-
import * as
|
|
67030
|
+
import * as path62 from "node:path";
|
|
66827
67031
|
function resolveReceiptsDir(directory) {
|
|
66828
|
-
return
|
|
67032
|
+
return path62.join(directory, ".swarm", "review-receipts");
|
|
66829
67033
|
}
|
|
66830
67034
|
function resolveReceiptIndexPath(directory) {
|
|
66831
|
-
return
|
|
67035
|
+
return path62.join(resolveReceiptsDir(directory), "index.json");
|
|
66832
67036
|
}
|
|
66833
67037
|
function buildReceiptFilename(id, date9) {
|
|
66834
67038
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -66867,7 +67071,7 @@ async function readReceiptIndex(directory) {
|
|
|
66867
67071
|
}
|
|
66868
67072
|
async function writeReceiptIndex(directory, index) {
|
|
66869
67073
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
66870
|
-
const dir =
|
|
67074
|
+
const dir = path62.dirname(indexPath);
|
|
66871
67075
|
await fs44.promises.mkdir(dir, { recursive: true });
|
|
66872
67076
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
66873
67077
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
@@ -66878,7 +67082,7 @@ async function persistReviewReceipt(directory, receipt) {
|
|
|
66878
67082
|
await fs44.promises.mkdir(receiptsDir, { recursive: true });
|
|
66879
67083
|
const now = new Date(receipt.reviewed_at);
|
|
66880
67084
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
66881
|
-
const receiptPath =
|
|
67085
|
+
const receiptPath = path62.join(receiptsDir, filename);
|
|
66882
67086
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
66883
67087
|
await fs44.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
66884
67088
|
fs44.renameSync(tmpPath, receiptPath);
|
|
@@ -66900,7 +67104,7 @@ async function readReceiptById(directory, receiptId) {
|
|
|
66900
67104
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
66901
67105
|
if (!entry)
|
|
66902
67106
|
return null;
|
|
66903
|
-
const receiptPath =
|
|
67107
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66904
67108
|
try {
|
|
66905
67109
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66906
67110
|
return JSON.parse(content);
|
|
@@ -66913,7 +67117,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
66913
67117
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
66914
67118
|
const receipts = [];
|
|
66915
67119
|
for (const entry of matching) {
|
|
66916
|
-
const receiptPath =
|
|
67120
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66917
67121
|
try {
|
|
66918
67122
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66919
67123
|
receipts.push(JSON.parse(content));
|
|
@@ -66926,7 +67130,7 @@ async function readAllReceipts(directory) {
|
|
|
66926
67130
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
66927
67131
|
const receipts = [];
|
|
66928
67132
|
for (const entry of sorted) {
|
|
66929
|
-
const receiptPath =
|
|
67133
|
+
const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
|
|
66930
67134
|
try {
|
|
66931
67135
|
const content = await fs44.promises.readFile(receiptPath, "utf-8");
|
|
66932
67136
|
receipts.push(JSON.parse(content));
|
|
@@ -68514,11 +68718,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
68514
68718
|
throw toThrow;
|
|
68515
68719
|
}, "quit_");
|
|
68516
68720
|
var scriptDirectory = "";
|
|
68517
|
-
function locateFile(
|
|
68721
|
+
function locateFile(path77) {
|
|
68518
68722
|
if (Module["locateFile"]) {
|
|
68519
|
-
return Module["locateFile"](
|
|
68723
|
+
return Module["locateFile"](path77, scriptDirectory);
|
|
68520
68724
|
}
|
|
68521
|
-
return scriptDirectory +
|
|
68725
|
+
return scriptDirectory + path77;
|
|
68522
68726
|
}
|
|
68523
68727
|
__name(locateFile, "locateFile");
|
|
68524
68728
|
var readAsync, readBinary;
|
|
@@ -70268,12 +70472,12 @@ __export(exports_runtime, {
|
|
|
70268
70472
|
clearParserCache: () => clearParserCache,
|
|
70269
70473
|
_internals: () => _internals35
|
|
70270
70474
|
});
|
|
70271
|
-
import * as
|
|
70475
|
+
import * as path77 from "node:path";
|
|
70272
70476
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
70273
70477
|
async function initTreeSitter() {
|
|
70274
70478
|
if (!treeSitterInitPromise) {
|
|
70275
70479
|
treeSitterInitPromise = (async () => {
|
|
70276
|
-
const thisDir =
|
|
70480
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
70277
70481
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
70278
70482
|
if (isSource) {
|
|
70279
70483
|
await _internals35.parserInit();
|
|
@@ -70281,7 +70485,7 @@ async function initTreeSitter() {
|
|
|
70281
70485
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
70282
70486
|
await _internals35.parserInit({
|
|
70283
70487
|
locateFile(scriptName) {
|
|
70284
|
-
return
|
|
70488
|
+
return path77.join(grammarsDir, scriptName);
|
|
70285
70489
|
}
|
|
70286
70490
|
});
|
|
70287
70491
|
}
|
|
@@ -70307,11 +70511,11 @@ function getWasmFileName(languageId) {
|
|
|
70307
70511
|
return `tree-sitter-${sanitized}.wasm`;
|
|
70308
70512
|
}
|
|
70309
70513
|
function getGrammarsDirAbsolute() {
|
|
70310
|
-
const thisDir =
|
|
70514
|
+
const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
|
|
70311
70515
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
70312
70516
|
const isSource = normalized.endsWith("/src/lang");
|
|
70313
70517
|
const isCliBundle = normalized.endsWith("/cli");
|
|
70314
|
-
return isSource ?
|
|
70518
|
+
return isSource ? path77.join(thisDir, "grammars") : isCliBundle ? path77.join(thisDir, "..", "lang", "grammars") : path77.join(thisDir, "lang", "grammars");
|
|
70315
70519
|
}
|
|
70316
70520
|
async function loadGrammar(languageId) {
|
|
70317
70521
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -70327,9 +70531,9 @@ async function loadGrammar(languageId) {
|
|
|
70327
70531
|
await initTreeSitter();
|
|
70328
70532
|
const parser = new Parser;
|
|
70329
70533
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
70330
|
-
const wasmPath =
|
|
70331
|
-
const { existsSync:
|
|
70332
|
-
if (!
|
|
70534
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
70535
|
+
const { existsSync: existsSync42 } = await import("node:fs");
|
|
70536
|
+
if (!existsSync42(wasmPath)) {
|
|
70333
70537
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
70334
70538
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
70335
70539
|
}
|
|
@@ -70362,7 +70566,7 @@ async function isGrammarAvailable(languageId) {
|
|
|
70362
70566
|
}
|
|
70363
70567
|
try {
|
|
70364
70568
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
70365
|
-
const wasmPath =
|
|
70569
|
+
const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
70366
70570
|
const { statSync: statSync20 } = await import("node:fs");
|
|
70367
70571
|
statSync20(wasmPath);
|
|
70368
70572
|
return true;
|
|
@@ -70431,13 +70635,13 @@ import {
|
|
|
70431
70635
|
stat as stat6,
|
|
70432
70636
|
writeFile as writeFile12
|
|
70433
70637
|
} from "node:fs/promises";
|
|
70434
|
-
import * as
|
|
70638
|
+
import * as path79 from "node:path";
|
|
70435
70639
|
function normalizeSeparators(filePath) {
|
|
70436
70640
|
return filePath.replace(/\\/g, "/");
|
|
70437
70641
|
}
|
|
70438
70642
|
function matchesDocPattern(filePath, patterns) {
|
|
70439
70643
|
const normalizedPath = normalizeSeparators(filePath);
|
|
70440
|
-
const basename10 =
|
|
70644
|
+
const basename10 = path79.basename(filePath);
|
|
70441
70645
|
for (const pattern of patterns) {
|
|
70442
70646
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
70443
70647
|
if (basename10 === pattern) {
|
|
@@ -70493,7 +70697,7 @@ function stripMarkdown(text) {
|
|
|
70493
70697
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
70494
70698
|
}
|
|
70495
70699
|
async function scanDocIndex(directory) {
|
|
70496
|
-
const manifestPath =
|
|
70700
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70497
70701
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
70498
70702
|
const extraPatterns = [
|
|
70499
70703
|
"ARCHITECTURE.md",
|
|
@@ -70510,7 +70714,7 @@ async function scanDocIndex(directory) {
|
|
|
70510
70714
|
let cacheValid = true;
|
|
70511
70715
|
for (const file3 of existingManifest.files) {
|
|
70512
70716
|
try {
|
|
70513
|
-
const fullPath =
|
|
70717
|
+
const fullPath = path79.join(directory, file3.path);
|
|
70514
70718
|
const stat7 = fs53.statSync(fullPath);
|
|
70515
70719
|
if (stat7.mtimeMs > file3.mtime) {
|
|
70516
70720
|
cacheValid = false;
|
|
@@ -70545,10 +70749,10 @@ async function scanDocIndex(directory) {
|
|
|
70545
70749
|
let isFile = entry.isFile();
|
|
70546
70750
|
if (entry.isSymbolicLink()) {
|
|
70547
70751
|
try {
|
|
70548
|
-
const symlinkPath =
|
|
70752
|
+
const symlinkPath = path79.join(dir, entry.name);
|
|
70549
70753
|
const resolved = await realpath2(symlinkPath);
|
|
70550
|
-
const rel =
|
|
70551
|
-
if (rel.startsWith("..") ||
|
|
70754
|
+
const rel = path79.relative(resolvedDirectory, resolved);
|
|
70755
|
+
if (rel.startsWith("..") || path79.isAbsolute(rel))
|
|
70552
70756
|
continue;
|
|
70553
70757
|
const targetStat = await stat6(symlinkPath);
|
|
70554
70758
|
isFile = targetStat.isFile();
|
|
@@ -70558,14 +70762,14 @@ async function scanDocIndex(directory) {
|
|
|
70558
70762
|
}
|
|
70559
70763
|
if (isDir) {
|
|
70560
70764
|
if (!SKIP_DIRECTORIES3.has(entry.name)) {
|
|
70561
|
-
await walkDir(
|
|
70765
|
+
await walkDir(path79.join(dir, entry.name));
|
|
70562
70766
|
}
|
|
70563
70767
|
continue;
|
|
70564
70768
|
}
|
|
70565
70769
|
if (!isFile)
|
|
70566
70770
|
continue;
|
|
70567
|
-
const fullPath =
|
|
70568
|
-
const relPath = normalizeSeparators(
|
|
70771
|
+
const fullPath = path79.join(dir, entry.name);
|
|
70772
|
+
const relPath = normalizeSeparators(path79.relative(directory, fullPath));
|
|
70569
70773
|
let skipThisFile = false;
|
|
70570
70774
|
for (const pattern of SKIP_PATTERNS) {
|
|
70571
70775
|
if (pattern.test(relPath)) {
|
|
@@ -70589,7 +70793,7 @@ async function scanDocIndex(directory) {
|
|
|
70589
70793
|
} catch {
|
|
70590
70794
|
continue;
|
|
70591
70795
|
}
|
|
70592
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
70796
|
+
const { title, summary } = extractTitleAndSummary(content, path79.basename(relPath));
|
|
70593
70797
|
discoveredFiles.push({
|
|
70594
70798
|
path: relPath,
|
|
70595
70799
|
title,
|
|
@@ -70626,7 +70830,7 @@ async function scanDocIndex(directory) {
|
|
|
70626
70830
|
files: discoveredFiles
|
|
70627
70831
|
};
|
|
70628
70832
|
try {
|
|
70629
|
-
await mkdir13(
|
|
70833
|
+
await mkdir13(path79.dirname(manifestPath), { recursive: true });
|
|
70630
70834
|
await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
70631
70835
|
} catch {}
|
|
70632
70836
|
return { manifest, cached: false };
|
|
@@ -70665,7 +70869,7 @@ function extractConstraintsFromContent(content) {
|
|
|
70665
70869
|
return constraints;
|
|
70666
70870
|
}
|
|
70667
70871
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
70668
|
-
const manifestPath =
|
|
70872
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70669
70873
|
let manifest;
|
|
70670
70874
|
try {
|
|
70671
70875
|
const content = await readFile12(manifestPath, "utf-8");
|
|
@@ -70691,7 +70895,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
70691
70895
|
}
|
|
70692
70896
|
let fullContent;
|
|
70693
70897
|
try {
|
|
70694
|
-
fullContent = await readFile12(
|
|
70898
|
+
fullContent = await readFile12(path79.join(directory, docFile.path), "utf-8");
|
|
70695
70899
|
} catch {
|
|
70696
70900
|
skippedCount++;
|
|
70697
70901
|
continue;
|
|
@@ -70714,7 +70918,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
70714
70918
|
tier: "swarm",
|
|
70715
70919
|
lesson: constraint,
|
|
70716
70920
|
category: "architecture",
|
|
70717
|
-
tags: ["doc-scan",
|
|
70921
|
+
tags: ["doc-scan", path79.basename(docFile.path)],
|
|
70718
70922
|
scope: "global",
|
|
70719
70923
|
confidence: 0.5,
|
|
70720
70924
|
status: "candidate",
|
|
@@ -70793,7 +70997,7 @@ var init_doc_scan = __esm(() => {
|
|
|
70793
70997
|
}
|
|
70794
70998
|
} catch {}
|
|
70795
70999
|
if (force) {
|
|
70796
|
-
const manifestPath =
|
|
71000
|
+
const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
|
|
70797
71001
|
try {
|
|
70798
71002
|
fs53.unlinkSync(manifestPath);
|
|
70799
71003
|
} catch {}
|
|
@@ -70989,9 +71193,9 @@ __export(exports_curator_drift, {
|
|
|
70989
71193
|
_internals: () => _internals38
|
|
70990
71194
|
});
|
|
70991
71195
|
import * as fs60 from "node:fs";
|
|
70992
|
-
import * as
|
|
71196
|
+
import * as path85 from "node:path";
|
|
70993
71197
|
async function readPriorDriftReports(directory) {
|
|
70994
|
-
const swarmDir =
|
|
71198
|
+
const swarmDir = path85.join(directory, ".swarm");
|
|
70995
71199
|
const entries = await fs60.promises.readdir(swarmDir).catch(() => null);
|
|
70996
71200
|
if (entries === null)
|
|
70997
71201
|
return [];
|
|
@@ -71018,7 +71222,7 @@ async function readPriorDriftReports(directory) {
|
|
|
71018
71222
|
async function writeDriftReport(directory, report) {
|
|
71019
71223
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
71020
71224
|
const filePath = validateSwarmPath(directory, filename);
|
|
71021
|
-
const swarmDir =
|
|
71225
|
+
const swarmDir = path85.dirname(filePath);
|
|
71022
71226
|
await fs60.promises.mkdir(swarmDir, { recursive: true });
|
|
71023
71227
|
try {
|
|
71024
71228
|
await fs60.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -71164,7 +71368,7 @@ __export(exports_project_context, {
|
|
|
71164
71368
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
71165
71369
|
});
|
|
71166
71370
|
import * as fs110 from "node:fs";
|
|
71167
|
-
import * as
|
|
71371
|
+
import * as path139 from "node:path";
|
|
71168
71372
|
function detectFileExists2(directory, pattern) {
|
|
71169
71373
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
71170
71374
|
try {
|
|
@@ -71176,7 +71380,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71176
71380
|
}
|
|
71177
71381
|
}
|
|
71178
71382
|
try {
|
|
71179
|
-
fs110.accessSync(
|
|
71383
|
+
fs110.accessSync(path139.join(directory, pattern));
|
|
71180
71384
|
return true;
|
|
71181
71385
|
} catch {
|
|
71182
71386
|
return false;
|
|
@@ -71185,7 +71389,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71185
71389
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
71186
71390
|
let pkgRaw;
|
|
71187
71391
|
try {
|
|
71188
|
-
pkgRaw = fs110.readFileSync(
|
|
71392
|
+
pkgRaw = fs110.readFileSync(path139.join(directory, "package.json"), "utf-8");
|
|
71189
71393
|
} catch {
|
|
71190
71394
|
return null;
|
|
71191
71395
|
}
|
|
@@ -71294,7 +71498,7 @@ var init_project_context = __esm(() => {
|
|
|
71294
71498
|
init_package();
|
|
71295
71499
|
init_agents2();
|
|
71296
71500
|
init_critic();
|
|
71297
|
-
import * as
|
|
71501
|
+
import * as path140 from "node:path";
|
|
71298
71502
|
|
|
71299
71503
|
// src/background/index.ts
|
|
71300
71504
|
init_event_bus();
|
|
@@ -71305,7 +71509,7 @@ init_manager3();
|
|
|
71305
71509
|
init_manager();
|
|
71306
71510
|
init_utils();
|
|
71307
71511
|
import * as fs37 from "node:fs";
|
|
71308
|
-
import * as
|
|
71512
|
+
import * as path58 from "node:path";
|
|
71309
71513
|
|
|
71310
71514
|
class PlanSyncWorker {
|
|
71311
71515
|
directory;
|
|
@@ -71329,10 +71533,10 @@ class PlanSyncWorker {
|
|
|
71329
71533
|
this.onSyncComplete = options.onSyncComplete;
|
|
71330
71534
|
}
|
|
71331
71535
|
getSwarmDir() {
|
|
71332
|
-
return
|
|
71536
|
+
return path58.resolve(this.directory, ".swarm");
|
|
71333
71537
|
}
|
|
71334
71538
|
getPlanJsonPath() {
|
|
71335
|
-
return
|
|
71539
|
+
return path58.join(this.getSwarmDir(), "plan.json");
|
|
71336
71540
|
}
|
|
71337
71541
|
start() {
|
|
71338
71542
|
if (this.disposed) {
|
|
@@ -71551,8 +71755,8 @@ class PlanSyncWorker {
|
|
|
71551
71755
|
checkForUnauthorizedWrite() {
|
|
71552
71756
|
try {
|
|
71553
71757
|
const swarmDir = this.getSwarmDir();
|
|
71554
|
-
const planJsonPath =
|
|
71555
|
-
const markerPath =
|
|
71758
|
+
const planJsonPath = path58.join(swarmDir, "plan.json");
|
|
71759
|
+
const markerPath = path58.join(swarmDir, ".plan-write-marker");
|
|
71556
71760
|
const planStats = fs37.statSync(planJsonPath);
|
|
71557
71761
|
const planMtimeMs = Math.floor(planStats.mtimeMs);
|
|
71558
71762
|
const markerContent = fs37.readFileSync(markerPath, "utf8");
|
|
@@ -71593,13 +71797,13 @@ init_constants();
|
|
|
71593
71797
|
// src/config/project-init.ts
|
|
71594
71798
|
init_constants();
|
|
71595
71799
|
import * as fs39 from "node:fs";
|
|
71596
|
-
import * as
|
|
71800
|
+
import * as path60 from "node:path";
|
|
71597
71801
|
var STARTER_CONTENT = `{}
|
|
71598
71802
|
`;
|
|
71599
71803
|
function writeProjectConfigIfNew(directory, quiet = false) {
|
|
71600
71804
|
try {
|
|
71601
|
-
const opencodeDir =
|
|
71602
|
-
const dest =
|
|
71805
|
+
const opencodeDir = path60.join(directory, ".opencode");
|
|
71806
|
+
const dest = path60.join(opencodeDir, "opencode-swarm.json");
|
|
71603
71807
|
try {
|
|
71604
71808
|
const stat4 = fs39.lstatSync(opencodeDir);
|
|
71605
71809
|
if (stat4.isSymbolicLink())
|
|
@@ -71624,8 +71828,8 @@ function writeProjectConfigIfNew(directory, quiet = false) {
|
|
|
71624
71828
|
}
|
|
71625
71829
|
function writeSwarmConfigExampleIfNew(projectDirectory) {
|
|
71626
71830
|
try {
|
|
71627
|
-
const swarmDir =
|
|
71628
|
-
const dest =
|
|
71831
|
+
const swarmDir = path60.join(projectDirectory, ".swarm");
|
|
71832
|
+
const dest = path60.join(swarmDir, "config.example.json");
|
|
71629
71833
|
if (fs39.existsSync(dest))
|
|
71630
71834
|
return;
|
|
71631
71835
|
if (!fs39.existsSync(swarmDir)) {
|
|
@@ -71662,7 +71866,7 @@ init_state();
|
|
|
71662
71866
|
init_logger();
|
|
71663
71867
|
init_state2();
|
|
71664
71868
|
import * as fs40 from "node:fs";
|
|
71665
|
-
import * as
|
|
71869
|
+
import * as path61 from "node:path";
|
|
71666
71870
|
var oversightSequenceCounter = 0;
|
|
71667
71871
|
var VALID_VERDICTS = [
|
|
71668
71872
|
"APPROVED",
|
|
@@ -71836,10 +72040,10 @@ async function writeFullAutoOversightEvidence(directory, phase, event) {
|
|
|
71836
72040
|
if (phase === undefined)
|
|
71837
72041
|
return;
|
|
71838
72042
|
try {
|
|
71839
|
-
const evidenceDir = validateSwarmPath(directory,
|
|
72043
|
+
const evidenceDir = validateSwarmPath(directory, path61.posix.join("evidence", String(phase)));
|
|
71840
72044
|
fs40.mkdirSync(evidenceDir, { recursive: true });
|
|
71841
72045
|
const fileName = `full-auto-${event.oversight_sequence}.json`;
|
|
71842
|
-
const filePath = validateSwarmPath(directory,
|
|
72046
|
+
const filePath = validateSwarmPath(directory, path61.posix.join("evidence", String(phase), fileName));
|
|
71843
72047
|
fs40.writeFileSync(filePath, `${JSON.stringify(event, null, 2)}
|
|
71844
72048
|
`, "utf-8");
|
|
71845
72049
|
return filePath;
|
|
@@ -72248,11 +72452,11 @@ async function doFlush(directory) {
|
|
|
72248
72452
|
const activitySection = renderActivitySection();
|
|
72249
72453
|
const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
|
|
72250
72454
|
const flushedCount = swarmState.pendingEvents;
|
|
72251
|
-
const
|
|
72252
|
-
const tempPath = `${
|
|
72455
|
+
const path62 = nodePath2.join(directory, ".swarm", "context.md");
|
|
72456
|
+
const tempPath = `${path62}.tmp`;
|
|
72253
72457
|
try {
|
|
72254
72458
|
await bunWrite(tempPath, updated);
|
|
72255
|
-
renameSync13(tempPath,
|
|
72459
|
+
renameSync13(tempPath, path62);
|
|
72256
72460
|
} catch (writeError) {
|
|
72257
72461
|
try {
|
|
72258
72462
|
unlinkSync10(tempPath);
|
|
@@ -72495,7 +72699,7 @@ init_state();
|
|
|
72495
72699
|
init_extractors();
|
|
72496
72700
|
init_utils2();
|
|
72497
72701
|
import * as fs41 from "node:fs";
|
|
72498
|
-
import { join as
|
|
72702
|
+
import { join as join55 } from "node:path";
|
|
72499
72703
|
function createCompactionCustomizerHook(config3, directory) {
|
|
72500
72704
|
const enabled = config3.hooks?.compaction !== false;
|
|
72501
72705
|
if (!enabled) {
|
|
@@ -72540,7 +72744,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
72540
72744
|
}
|
|
72541
72745
|
}
|
|
72542
72746
|
try {
|
|
72543
|
-
const summariesDir =
|
|
72747
|
+
const summariesDir = join55(directory, ".swarm", "summaries");
|
|
72544
72748
|
const files = await fs41.promises.readdir(summariesDir);
|
|
72545
72749
|
if (files.length > 0) {
|
|
72546
72750
|
const count = files.length;
|
|
@@ -73920,7 +74124,7 @@ init_schema();
|
|
|
73920
74124
|
init_manager();
|
|
73921
74125
|
init_curator();
|
|
73922
74126
|
init_utils2();
|
|
73923
|
-
import * as
|
|
74127
|
+
import * as path63 from "node:path";
|
|
73924
74128
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
73925
74129
|
let lastKnownPhase = null;
|
|
73926
74130
|
const handler = async (input, _output) => {
|
|
@@ -73940,9 +74144,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
73940
74144
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
73941
74145
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
73942
74146
|
if (initResult.briefing) {
|
|
73943
|
-
const briefingPath =
|
|
74147
|
+
const briefingPath = path63.join(directory, ".swarm", "curator-briefing.md");
|
|
73944
74148
|
const { mkdir: mkdir11, writeFile: writeFile11 } = await import("node:fs/promises");
|
|
73945
|
-
await mkdir11(
|
|
74149
|
+
await mkdir11(path63.dirname(briefingPath), { recursive: true });
|
|
73946
74150
|
await writeFile11(briefingPath, initResult.briefing, "utf-8");
|
|
73947
74151
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
73948
74152
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -74069,16 +74273,16 @@ ${originalText}`;
|
|
|
74069
74273
|
// src/hooks/repo-graph-builder.ts
|
|
74070
74274
|
init_constants();
|
|
74071
74275
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
74072
|
-
import * as
|
|
74276
|
+
import * as path70 from "node:path";
|
|
74073
74277
|
|
|
74074
74278
|
// src/tools/repo-graph/builder.ts
|
|
74075
74279
|
init_logger();
|
|
74076
74280
|
init_path_security();
|
|
74077
|
-
import * as
|
|
74078
|
-
import { existsSync as
|
|
74281
|
+
import * as fsSync4 from "node:fs";
|
|
74282
|
+
import { existsSync as existsSync38, realpathSync as realpathSync6 } from "node:fs";
|
|
74079
74283
|
import * as fsPromises5 from "node:fs/promises";
|
|
74080
74284
|
import * as os7 from "node:os";
|
|
74081
|
-
import * as
|
|
74285
|
+
import * as path66 from "node:path";
|
|
74082
74286
|
|
|
74083
74287
|
// src/utils/timeout.ts
|
|
74084
74288
|
async function withTimeout(promise3, ms, timeoutError) {
|
|
@@ -74110,7 +74314,7 @@ init_zod();
|
|
|
74110
74314
|
init_create_tool();
|
|
74111
74315
|
init_path_security();
|
|
74112
74316
|
import * as fs45 from "node:fs";
|
|
74113
|
-
import * as
|
|
74317
|
+
import * as path64 from "node:path";
|
|
74114
74318
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
74115
74319
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
74116
74320
|
function containsWindowsAttacks(str) {
|
|
@@ -74127,11 +74331,11 @@ function containsWindowsAttacks(str) {
|
|
|
74127
74331
|
}
|
|
74128
74332
|
function isPathInWorkspace(filePath, workspace) {
|
|
74129
74333
|
try {
|
|
74130
|
-
const resolvedPath =
|
|
74334
|
+
const resolvedPath = path64.resolve(workspace, filePath);
|
|
74131
74335
|
const realWorkspace = fs45.realpathSync(workspace);
|
|
74132
74336
|
const realResolvedPath = fs45.realpathSync(resolvedPath);
|
|
74133
|
-
const relativePath =
|
|
74134
|
-
if (relativePath.startsWith("..") ||
|
|
74337
|
+
const relativePath = path64.relative(realWorkspace, realResolvedPath);
|
|
74338
|
+
if (relativePath.startsWith("..") || path64.isAbsolute(relativePath)) {
|
|
74135
74339
|
return false;
|
|
74136
74340
|
}
|
|
74137
74341
|
return true;
|
|
@@ -74143,7 +74347,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
74143
74347
|
return isPathInWorkspace(filePath, workspace);
|
|
74144
74348
|
}
|
|
74145
74349
|
function extractTSSymbols(filePath, cwd) {
|
|
74146
|
-
const fullPath =
|
|
74350
|
+
const fullPath = path64.join(cwd, filePath);
|
|
74147
74351
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
74148
74352
|
return [];
|
|
74149
74353
|
}
|
|
@@ -74295,7 +74499,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
74295
74499
|
});
|
|
74296
74500
|
}
|
|
74297
74501
|
function extractPythonSymbols(filePath, cwd) {
|
|
74298
|
-
const fullPath =
|
|
74502
|
+
const fullPath = path64.join(cwd, filePath);
|
|
74299
74503
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
74300
74504
|
return [];
|
|
74301
74505
|
}
|
|
@@ -74378,7 +74582,7 @@ var symbols = createSwarmTool({
|
|
|
74378
74582
|
}, null, 2);
|
|
74379
74583
|
}
|
|
74380
74584
|
const cwd = directory;
|
|
74381
|
-
const ext =
|
|
74585
|
+
const ext = path64.extname(file3);
|
|
74382
74586
|
if (containsControlChars(file3)) {
|
|
74383
74587
|
return JSON.stringify({
|
|
74384
74588
|
file: file3,
|
|
@@ -74439,16 +74643,16 @@ var symbols = createSwarmTool({
|
|
|
74439
74643
|
});
|
|
74440
74644
|
|
|
74441
74645
|
// src/tools/repo-graph/types.ts
|
|
74442
|
-
import * as
|
|
74646
|
+
import * as path65 from "node:path";
|
|
74443
74647
|
var REPO_GRAPH_FILENAME = "repo-graph.json";
|
|
74444
74648
|
var GRAPH_SCHEMA_VERSION = "1.0.0";
|
|
74445
74649
|
function normalizeGraphPath(filePath) {
|
|
74446
|
-
return
|
|
74650
|
+
return path65.normalize(filePath).replace(/\\/g, "/");
|
|
74447
74651
|
}
|
|
74448
74652
|
function createEmptyGraph(workspaceRoot) {
|
|
74449
74653
|
return {
|
|
74450
74654
|
schema_version: GRAPH_SCHEMA_VERSION,
|
|
74451
|
-
workspaceRoot:
|
|
74655
|
+
workspaceRoot: path65.normalize(workspaceRoot),
|
|
74452
74656
|
nodes: {},
|
|
74453
74657
|
edges: [],
|
|
74454
74658
|
metadata: {
|
|
@@ -74623,8 +74827,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74623
74827
|
}
|
|
74624
74828
|
try {
|
|
74625
74829
|
if (specifier.startsWith(".")) {
|
|
74626
|
-
const sourceDir =
|
|
74627
|
-
let resolved =
|
|
74830
|
+
const sourceDir = path66.dirname(sourceFile);
|
|
74831
|
+
let resolved = path66.resolve(sourceDir, specifier);
|
|
74628
74832
|
let realResolved;
|
|
74629
74833
|
try {
|
|
74630
74834
|
realResolved = realpathSync6(resolved);
|
|
@@ -74635,9 +74839,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74635
74839
|
try {
|
|
74636
74840
|
realRoot = realpathSync6(workspaceRoot);
|
|
74637
74841
|
} catch {
|
|
74638
|
-
realRoot =
|
|
74842
|
+
realRoot = path66.normalize(workspaceRoot);
|
|
74639
74843
|
}
|
|
74640
|
-
if (!
|
|
74844
|
+
if (!existsSync38(resolved)) {
|
|
74641
74845
|
const EXTENSIONS = [
|
|
74642
74846
|
".ts",
|
|
74643
74847
|
".tsx",
|
|
@@ -74651,7 +74855,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74651
74855
|
let found = null;
|
|
74652
74856
|
for (const ext of EXTENSIONS) {
|
|
74653
74857
|
const candidate = resolved + ext;
|
|
74654
|
-
if (
|
|
74858
|
+
if (existsSync38(candidate)) {
|
|
74655
74859
|
found = candidate;
|
|
74656
74860
|
break;
|
|
74657
74861
|
}
|
|
@@ -74667,9 +74871,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
|
|
|
74667
74871
|
return null;
|
|
74668
74872
|
}
|
|
74669
74873
|
}
|
|
74670
|
-
const normalizedResolved =
|
|
74671
|
-
const normalizedRoot =
|
|
74672
|
-
if (!normalizedResolved.startsWith(normalizedRoot +
|
|
74874
|
+
const normalizedResolved = path66.normalize(realResolved);
|
|
74875
|
+
const normalizedRoot = path66.normalize(realRoot);
|
|
74876
|
+
if (!normalizedResolved.startsWith(normalizedRoot + path66.sep) && normalizedResolved !== normalizedRoot) {
|
|
74673
74877
|
return null;
|
|
74674
74878
|
}
|
|
74675
74879
|
return resolved;
|
|
@@ -74684,12 +74888,12 @@ function isRefusedWorkspaceRoot(target) {
|
|
|
74684
74888
|
try {
|
|
74685
74889
|
resolved = realpathSync6(target);
|
|
74686
74890
|
} catch {
|
|
74687
|
-
resolved =
|
|
74891
|
+
resolved = path66.resolve(target);
|
|
74688
74892
|
}
|
|
74689
74893
|
const refused = new Set;
|
|
74690
74894
|
const add = (p) => {
|
|
74691
74895
|
if (typeof p === "string" && p.length > 0) {
|
|
74692
|
-
refused.add(
|
|
74896
|
+
refused.add(path66.resolve(p));
|
|
74693
74897
|
}
|
|
74694
74898
|
};
|
|
74695
74899
|
add(os7.homedir());
|
|
@@ -74799,7 +75003,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74799
75003
|
ctx.stats.skippedDirs++;
|
|
74800
75004
|
continue;
|
|
74801
75005
|
}
|
|
74802
|
-
const fullPath =
|
|
75006
|
+
const fullPath = path66.join(current, entry.name);
|
|
74803
75007
|
if (entry.isSymbolicLink() && !ctx.followSymlinks) {
|
|
74804
75008
|
ctx.stats.skippedDirs++;
|
|
74805
75009
|
continue;
|
|
@@ -74807,7 +75011,7 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74807
75011
|
if (entry.isDirectory()) {
|
|
74808
75012
|
queue.push(fullPath);
|
|
74809
75013
|
} else if (entry.isFile()) {
|
|
74810
|
-
const ext =
|
|
75014
|
+
const ext = path66.extname(fullPath).toLowerCase();
|
|
74811
75015
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
74812
75016
|
files.push(fullPath);
|
|
74813
75017
|
}
|
|
@@ -74824,11 +75028,11 @@ async function findSourceFilesAsync(dir, stats, options) {
|
|
|
74824
75028
|
return files;
|
|
74825
75029
|
}
|
|
74826
75030
|
function toModuleName(filePath, workspaceRoot) {
|
|
74827
|
-
const relative11 =
|
|
74828
|
-
return relative11.split(
|
|
75031
|
+
const relative11 = path66.relative(workspaceRoot, filePath);
|
|
75032
|
+
return relative11.split(path66.sep).join("/");
|
|
74829
75033
|
}
|
|
74830
75034
|
function getLanguage(filePath) {
|
|
74831
|
-
const ext =
|
|
75035
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
74832
75036
|
return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
|
|
74833
75037
|
}
|
|
74834
75038
|
function isBinaryContent(content) {
|
|
@@ -74841,26 +75045,26 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
|
|
|
74841
75045
|
let content;
|
|
74842
75046
|
let fileStats;
|
|
74843
75047
|
try {
|
|
74844
|
-
fileStats =
|
|
75048
|
+
fileStats = fsSync4.statSync(filePath);
|
|
74845
75049
|
if (fileStats.size > maxFileSize) {
|
|
74846
75050
|
return { node: null, edges: [] };
|
|
74847
75051
|
}
|
|
74848
|
-
content =
|
|
75052
|
+
content = fsSync4.readFileSync(filePath, "utf-8");
|
|
74849
75053
|
} catch {
|
|
74850
75054
|
return { node: null, edges: [] };
|
|
74851
75055
|
}
|
|
74852
75056
|
if (isBinaryContent(content)) {
|
|
74853
75057
|
return { node: null, edges: [] };
|
|
74854
75058
|
}
|
|
74855
|
-
const ext =
|
|
75059
|
+
const ext = path66.extname(filePath).toLowerCase();
|
|
74856
75060
|
let exports = [];
|
|
74857
75061
|
try {
|
|
74858
75062
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
74859
|
-
const relativePath =
|
|
75063
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
74860
75064
|
const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
|
|
74861
75065
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
74862
75066
|
} else if (ext === ".py") {
|
|
74863
|
-
const relativePath =
|
|
75067
|
+
const relativePath = path66.relative(absoluteRoot, filePath);
|
|
74864
75068
|
const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
|
|
74865
75069
|
exports = symbols2.filter((s) => s.exported).map((s) => s.name);
|
|
74866
75070
|
}
|
|
@@ -74897,8 +75101,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
74897
75101
|
const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
|
|
74898
75102
|
const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
|
|
74899
75103
|
const followSymlinks = options?.followSymlinks ?? false;
|
|
74900
|
-
const absoluteRoot =
|
|
74901
|
-
if (!
|
|
75104
|
+
const absoluteRoot = path66.resolve(workspaceRoot);
|
|
75105
|
+
if (!existsSync38(absoluteRoot)) {
|
|
74902
75106
|
throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
|
|
74903
75107
|
}
|
|
74904
75108
|
if (isRefusedWorkspaceRoot(absoluteRoot)) {
|
|
@@ -74953,15 +75157,15 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
|
|
|
74953
75157
|
return graph;
|
|
74954
75158
|
}
|
|
74955
75159
|
// src/tools/repo-graph/cache.ts
|
|
74956
|
-
import * as
|
|
75160
|
+
import * as path67 from "node:path";
|
|
74957
75161
|
var graphCache = new Map;
|
|
74958
75162
|
var dirtyFlags = new Map;
|
|
74959
75163
|
var mtimeCache = new Map;
|
|
74960
75164
|
function getCachedGraph(workspace) {
|
|
74961
|
-
return graphCache.get(
|
|
75165
|
+
return graphCache.get(path67.normalize(workspace));
|
|
74962
75166
|
}
|
|
74963
75167
|
function setCachedGraph(workspace, graph, mtime) {
|
|
74964
|
-
const normalized =
|
|
75168
|
+
const normalized = path67.normalize(workspace);
|
|
74965
75169
|
graphCache.set(normalized, graph);
|
|
74966
75170
|
dirtyFlags.set(normalized, false);
|
|
74967
75171
|
if (mtime !== undefined) {
|
|
@@ -74969,30 +75173,30 @@ function setCachedGraph(workspace, graph, mtime) {
|
|
|
74969
75173
|
}
|
|
74970
75174
|
}
|
|
74971
75175
|
function isDirty(workspace) {
|
|
74972
|
-
return dirtyFlags.get(
|
|
75176
|
+
return dirtyFlags.get(path67.normalize(workspace)) ?? false;
|
|
74973
75177
|
}
|
|
74974
75178
|
function clearCache(workspace) {
|
|
74975
|
-
const normalized =
|
|
75179
|
+
const normalized = path67.normalize(workspace);
|
|
74976
75180
|
graphCache.delete(normalized);
|
|
74977
75181
|
dirtyFlags.delete(normalized);
|
|
74978
75182
|
mtimeCache.delete(normalized);
|
|
74979
75183
|
}
|
|
74980
75184
|
function getCachedMtime(workspace) {
|
|
74981
|
-
return mtimeCache.get(
|
|
75185
|
+
return mtimeCache.get(path67.normalize(workspace));
|
|
74982
75186
|
}
|
|
74983
75187
|
// src/tools/repo-graph/incremental.ts
|
|
74984
75188
|
init_logger();
|
|
74985
|
-
import { existsSync as
|
|
75189
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
74986
75190
|
import * as fsPromises7 from "node:fs/promises";
|
|
74987
|
-
import * as
|
|
75191
|
+
import * as path69 from "node:path";
|
|
74988
75192
|
|
|
74989
75193
|
// src/tools/repo-graph/storage.ts
|
|
74990
75194
|
init_utils2();
|
|
74991
75195
|
init_logger();
|
|
74992
75196
|
init_path_security();
|
|
74993
|
-
import { constants as constants4, existsSync as
|
|
75197
|
+
import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
|
|
74994
75198
|
import * as fsPromises6 from "node:fs/promises";
|
|
74995
|
-
import * as
|
|
75199
|
+
import * as path68 from "node:path";
|
|
74996
75200
|
var WINDOWS_RENAME_MAX_RETRIES2 = 3;
|
|
74997
75201
|
var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
|
|
74998
75202
|
function getGraphPath(workspace) {
|
|
@@ -75003,12 +75207,12 @@ function getGraphPath(workspace) {
|
|
|
75003
75207
|
}
|
|
75004
75208
|
async function loadGraph(workspace) {
|
|
75005
75209
|
validateWorkspace(workspace);
|
|
75006
|
-
const normalized =
|
|
75210
|
+
const normalized = path68.normalize(workspace);
|
|
75007
75211
|
const cached3 = getCachedGraph(normalized);
|
|
75008
75212
|
if (cached3 && !isDirty(normalized)) {
|
|
75009
75213
|
try {
|
|
75010
75214
|
const graphPath = getGraphPath(workspace);
|
|
75011
|
-
if (
|
|
75215
|
+
if (existsSync39(graphPath)) {
|
|
75012
75216
|
const stats = await fsPromises6.stat(graphPath);
|
|
75013
75217
|
const cachedMtime = getCachedMtime(normalized);
|
|
75014
75218
|
if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
|
|
@@ -75025,7 +75229,7 @@ async function loadGraph(workspace) {
|
|
|
75025
75229
|
}
|
|
75026
75230
|
try {
|
|
75027
75231
|
const graphPath = getGraphPath(workspace);
|
|
75028
|
-
if (!
|
|
75232
|
+
if (!existsSync39(graphPath)) {
|
|
75029
75233
|
return null;
|
|
75030
75234
|
}
|
|
75031
75235
|
const stats = await fsPromises6.stat(graphPath);
|
|
@@ -75097,28 +75301,28 @@ async function saveGraph(workspace, graph, options) {
|
|
|
75097
75301
|
if (!Array.isArray(graph.edges)) {
|
|
75098
75302
|
throw new Error("Graph must have edges array");
|
|
75099
75303
|
}
|
|
75100
|
-
const normalizedWorkspace =
|
|
75304
|
+
const normalizedWorkspace = path68.normalize(workspace);
|
|
75101
75305
|
let realWorkspace;
|
|
75102
75306
|
try {
|
|
75103
75307
|
realWorkspace = realpathSync7(workspace);
|
|
75104
75308
|
} catch {
|
|
75105
75309
|
realWorkspace = normalizedWorkspace;
|
|
75106
75310
|
}
|
|
75107
|
-
const normalizedGraphRoot =
|
|
75311
|
+
const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
|
|
75108
75312
|
let realGraphRoot;
|
|
75109
75313
|
try {
|
|
75110
75314
|
realGraphRoot = realpathSync7(graph.workspaceRoot);
|
|
75111
75315
|
} catch {
|
|
75112
75316
|
realGraphRoot = normalizedGraphRoot;
|
|
75113
75317
|
}
|
|
75114
|
-
if (
|
|
75318
|
+
if (path68.normalize(realWorkspace) !== path68.normalize(realGraphRoot)) {
|
|
75115
75319
|
throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
|
|
75116
75320
|
}
|
|
75117
75321
|
const normalized = normalizedWorkspace;
|
|
75118
75322
|
const graphPath = getGraphPath(workspace);
|
|
75119
75323
|
updateGraphMetadata(graph);
|
|
75120
75324
|
const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
75121
|
-
await fsPromises6.mkdir(
|
|
75325
|
+
await fsPromises6.mkdir(path68.dirname(tempPath), { recursive: true });
|
|
75122
75326
|
let lastError = null;
|
|
75123
75327
|
try {
|
|
75124
75328
|
if (options?.createAtomic) {
|
|
@@ -75186,12 +75390,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
75186
75390
|
return graph2;
|
|
75187
75391
|
}
|
|
75188
75392
|
const graph = existingGraph;
|
|
75189
|
-
const absoluteRoot =
|
|
75393
|
+
const absoluteRoot = path69.resolve(workspaceRoot);
|
|
75190
75394
|
const maxFileSize = 1024 * 1024;
|
|
75191
75395
|
const updatedPaths = new Set;
|
|
75192
75396
|
for (const rawFilePath of filePaths) {
|
|
75193
75397
|
const normalizedPath = normalizeGraphPath(rawFilePath);
|
|
75194
|
-
const fileExists =
|
|
75398
|
+
const fileExists = existsSync40(rawFilePath);
|
|
75195
75399
|
if (fileExists) {
|
|
75196
75400
|
graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
|
|
75197
75401
|
const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
|
|
@@ -75226,12 +75430,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
|
|
|
75226
75430
|
await saveGraph(workspaceRoot, rebuiltGraph);
|
|
75227
75431
|
return rebuiltGraph;
|
|
75228
75432
|
}
|
|
75229
|
-
const normalizedWorkspace =
|
|
75433
|
+
const normalizedWorkspace = path69.normalize(workspaceRoot);
|
|
75230
75434
|
const loadedMtime = getCachedMtime(normalizedWorkspace);
|
|
75231
75435
|
if (loadedMtime !== undefined) {
|
|
75232
75436
|
try {
|
|
75233
75437
|
const graphPath = getGraphPath(workspaceRoot);
|
|
75234
|
-
if (
|
|
75438
|
+
if (existsSync40(graphPath)) {
|
|
75235
75439
|
const currentStats = await fsPromises7.stat(graphPath);
|
|
75236
75440
|
if (currentStats.mtimeMs !== loadedMtime) {
|
|
75237
75441
|
warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
|
|
@@ -75324,7 +75528,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
75324
75528
|
return;
|
|
75325
75529
|
if (!isSupportedSourceFile(filePath))
|
|
75326
75530
|
return;
|
|
75327
|
-
const absoluteFilePath =
|
|
75531
|
+
const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
|
|
75328
75532
|
let realFilePath;
|
|
75329
75533
|
try {
|
|
75330
75534
|
realFilePath = realpathSync8(absoluteFilePath);
|
|
@@ -75351,7 +75555,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
|
|
|
75351
75555
|
try {
|
|
75352
75556
|
await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
|
|
75353
75557
|
consecutiveFailures = 0;
|
|
75354
|
-
log(`[repo-graph] Incremental update for ${
|
|
75558
|
+
log(`[repo-graph] Incremental update for ${path70.basename(filePath)}`);
|
|
75355
75559
|
} catch (error93) {
|
|
75356
75560
|
const message = error93 instanceof Error ? error93.message : String(error93);
|
|
75357
75561
|
consecutiveFailures++;
|
|
@@ -75374,14 +75578,14 @@ init_manager2();
|
|
|
75374
75578
|
init_detector();
|
|
75375
75579
|
init_manager();
|
|
75376
75580
|
import * as fs54 from "node:fs";
|
|
75377
|
-
import * as
|
|
75581
|
+
import * as path80 from "node:path";
|
|
75378
75582
|
|
|
75379
75583
|
// src/services/decision-drift-analyzer.ts
|
|
75380
75584
|
init_utils2();
|
|
75381
75585
|
init_manager();
|
|
75382
75586
|
init_utils();
|
|
75383
75587
|
import * as fs46 from "node:fs";
|
|
75384
|
-
import * as
|
|
75588
|
+
import * as path71 from "node:path";
|
|
75385
75589
|
var DEFAULT_DRIFT_CONFIG = {
|
|
75386
75590
|
staleThresholdPhases: 1,
|
|
75387
75591
|
detectContradictions: true,
|
|
@@ -75535,7 +75739,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
75535
75739
|
currentPhase = legacyPhase;
|
|
75536
75740
|
}
|
|
75537
75741
|
}
|
|
75538
|
-
const contextPath =
|
|
75742
|
+
const contextPath = path71.join(directory, ".swarm", "context.md");
|
|
75539
75743
|
let contextContent = "";
|
|
75540
75744
|
try {
|
|
75541
75745
|
if (fs46.existsSync(contextPath)) {
|
|
@@ -75674,7 +75878,7 @@ init_utils();
|
|
|
75674
75878
|
init_constants();
|
|
75675
75879
|
init_schema();
|
|
75676
75880
|
import * as fs47 from "node:fs/promises";
|
|
75677
|
-
import * as
|
|
75881
|
+
import * as path72 from "node:path";
|
|
75678
75882
|
function safeGet(obj, key) {
|
|
75679
75883
|
if (!obj || !Object.hasOwn(obj, key))
|
|
75680
75884
|
return;
|
|
@@ -75906,9 +76110,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
75906
76110
|
let eventLogged = false;
|
|
75907
76111
|
let checkpointCreated = false;
|
|
75908
76112
|
try {
|
|
75909
|
-
const swarmDir =
|
|
76113
|
+
const swarmDir = path72.join(directory, ".swarm");
|
|
75910
76114
|
await fs47.mkdir(swarmDir, { recursive: true });
|
|
75911
|
-
const eventsPath =
|
|
76115
|
+
const eventsPath = path72.join(swarmDir, "events.jsonl");
|
|
75912
76116
|
await fs47.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
75913
76117
|
`);
|
|
75914
76118
|
eventLogged = true;
|
|
@@ -76044,7 +76248,7 @@ import * as fs51 from "node:fs";
|
|
|
76044
76248
|
|
|
76045
76249
|
// src/graph/graph-builder.ts
|
|
76046
76250
|
import * as fs49 from "node:fs";
|
|
76047
|
-
import * as
|
|
76251
|
+
import * as path75 from "node:path";
|
|
76048
76252
|
|
|
76049
76253
|
// node_modules/yocto-queue/index.js
|
|
76050
76254
|
class Node {
|
|
@@ -76205,7 +76409,7 @@ function validateConcurrency(concurrency) {
|
|
|
76205
76409
|
// src/graph/import-extractor.ts
|
|
76206
76410
|
init_path_security();
|
|
76207
76411
|
import * as fs48 from "node:fs";
|
|
76208
|
-
import * as
|
|
76412
|
+
import * as path73 from "node:path";
|
|
76209
76413
|
var SOURCE_EXTENSIONS2 = [
|
|
76210
76414
|
".ts",
|
|
76211
76415
|
".tsx",
|
|
@@ -76250,14 +76454,14 @@ function getLanguageFromExtension(ext) {
|
|
|
76250
76454
|
return null;
|
|
76251
76455
|
}
|
|
76252
76456
|
function toRelForwardSlash(absPath, root) {
|
|
76253
|
-
return
|
|
76457
|
+
return path73.relative(root, absPath).replace(/\\/g, "/");
|
|
76254
76458
|
}
|
|
76255
76459
|
function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
76256
76460
|
if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
|
|
76257
76461
|
return null;
|
|
76258
76462
|
}
|
|
76259
|
-
const sourceDir =
|
|
76260
|
-
const baseAbs =
|
|
76463
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
76464
|
+
const baseAbs = path73.resolve(sourceDir, rawModule);
|
|
76261
76465
|
const probe = (basePath) => {
|
|
76262
76466
|
for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
|
|
76263
76467
|
const test = basePath + ext;
|
|
@@ -76268,7 +76472,7 @@ function tryResolveTSJS(rawModule, sourceFileAbs) {
|
|
|
76268
76472
|
} catch {}
|
|
76269
76473
|
}
|
|
76270
76474
|
for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
|
|
76271
|
-
const test =
|
|
76475
|
+
const test = path73.join(basePath, indexFile);
|
|
76272
76476
|
try {
|
|
76273
76477
|
const stat6 = fs48.statSync(test);
|
|
76274
76478
|
if (stat6.isFile())
|
|
@@ -76298,13 +76502,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
76298
76502
|
}
|
|
76299
76503
|
const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
|
|
76300
76504
|
const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
|
|
76301
|
-
const sourceDir =
|
|
76302
|
-
const baseAbs =
|
|
76505
|
+
const sourceDir = path73.dirname(sourceFileAbs);
|
|
76506
|
+
const baseAbs = path73.resolve(sourceDir, upDirs + remainder);
|
|
76303
76507
|
const accept = (test) => {
|
|
76304
76508
|
try {
|
|
76305
76509
|
const stat6 = fs48.statSync(test);
|
|
76306
76510
|
if (stat6.isFile()) {
|
|
76307
|
-
const rel =
|
|
76511
|
+
const rel = path73.relative(workspaceRoot, test).replace(/\\/g, "/");
|
|
76308
76512
|
if (rel.startsWith(".."))
|
|
76309
76513
|
return null;
|
|
76310
76514
|
return test;
|
|
@@ -76318,7 +76522,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
|
|
|
76318
76522
|
return hit;
|
|
76319
76523
|
}
|
|
76320
76524
|
for (const indexFile of PY_INDEX_CANDIDATES) {
|
|
76321
|
-
const hit = accept(
|
|
76525
|
+
const hit = accept(path73.join(baseAbs, indexFile));
|
|
76322
76526
|
if (hit)
|
|
76323
76527
|
return hit;
|
|
76324
76528
|
}
|
|
@@ -76689,7 +76893,7 @@ function parseRustUses(content) {
|
|
|
76689
76893
|
}
|
|
76690
76894
|
function extractImports5(opts) {
|
|
76691
76895
|
const { absoluteFilePath, workspaceRoot } = opts;
|
|
76692
|
-
const ext =
|
|
76896
|
+
const ext = path73.extname(absoluteFilePath).toLowerCase();
|
|
76693
76897
|
const language = getLanguageFromExtension(ext);
|
|
76694
76898
|
if (!language)
|
|
76695
76899
|
return [];
|
|
@@ -76740,9 +76944,9 @@ function extractImports5(opts) {
|
|
|
76740
76944
|
}
|
|
76741
76945
|
|
|
76742
76946
|
// src/graph/symbol-extractor.ts
|
|
76743
|
-
import * as
|
|
76947
|
+
import * as path74 from "node:path";
|
|
76744
76948
|
function extractExportedSymbols(relativeFilePath, workspaceRoot) {
|
|
76745
|
-
const ext =
|
|
76949
|
+
const ext = path74.extname(relativeFilePath).toLowerCase();
|
|
76746
76950
|
const language = getLanguageFromExtension(ext);
|
|
76747
76951
|
if (!language)
|
|
76748
76952
|
return [];
|
|
@@ -76831,15 +77035,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
|
76831
77035
|
if (entry.isDirectory()) {
|
|
76832
77036
|
if (skipDirs.has(entry.name))
|
|
76833
77037
|
continue;
|
|
76834
|
-
stack.push(
|
|
77038
|
+
stack.push(path75.join(dir, entry.name));
|
|
76835
77039
|
continue;
|
|
76836
77040
|
}
|
|
76837
77041
|
if (!entry.isFile())
|
|
76838
77042
|
continue;
|
|
76839
|
-
const ext =
|
|
77043
|
+
const ext = path75.extname(entry.name).toLowerCase();
|
|
76840
77044
|
if (!SOURCE_EXT_SET.has(ext))
|
|
76841
77045
|
continue;
|
|
76842
|
-
out2.push(
|
|
77046
|
+
out2.push(path75.join(dir, entry.name));
|
|
76843
77047
|
}
|
|
76844
77048
|
}
|
|
76845
77049
|
return out2;
|
|
@@ -76867,7 +77071,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
|
|
|
76867
77071
|
};
|
|
76868
77072
|
}
|
|
76869
77073
|
async function processFile(absoluteFilePath, workspaceRoot) {
|
|
76870
|
-
const ext =
|
|
77074
|
+
const ext = path75.extname(absoluteFilePath).toLowerCase();
|
|
76871
77075
|
const language = getLanguageFromExtension(ext);
|
|
76872
77076
|
if (!language)
|
|
76873
77077
|
return null;
|
|
@@ -76887,7 +77091,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
|
|
|
76887
77091
|
} catch {
|
|
76888
77092
|
return null;
|
|
76889
77093
|
}
|
|
76890
|
-
const relPath =
|
|
77094
|
+
const relPath = path75.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
|
|
76891
77095
|
const imports = extractImports5({
|
|
76892
77096
|
absoluteFilePath,
|
|
76893
77097
|
workspaceRoot,
|
|
@@ -77129,10 +77333,10 @@ function formatSummary(opts) {
|
|
|
77129
77333
|
// src/graph/graph-store.ts
|
|
77130
77334
|
import * as crypto6 from "node:crypto";
|
|
77131
77335
|
import * as fs50 from "node:fs";
|
|
77132
|
-
import * as
|
|
77336
|
+
import * as path76 from "node:path";
|
|
77133
77337
|
var SWARM_DIR = ".swarm";
|
|
77134
77338
|
function getGraphPath2(workspaceRoot) {
|
|
77135
|
-
return
|
|
77339
|
+
return path76.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
|
|
77136
77340
|
}
|
|
77137
77341
|
function loadGraph2(workspaceRoot) {
|
|
77138
77342
|
const file3 = getGraphPath2(workspaceRoot);
|
|
@@ -77154,7 +77358,7 @@ function loadGraph2(workspaceRoot) {
|
|
|
77154
77358
|
}
|
|
77155
77359
|
function saveGraph2(workspaceRoot, graph) {
|
|
77156
77360
|
const file3 = getGraphPath2(workspaceRoot);
|
|
77157
|
-
const dir =
|
|
77361
|
+
const dir = path76.dirname(file3);
|
|
77158
77362
|
try {
|
|
77159
77363
|
const stat6 = fs50.lstatSync(dir);
|
|
77160
77364
|
if (stat6.isSymbolicLink()) {
|
|
@@ -77260,7 +77464,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
|
|
|
77260
77464
|
// src/hooks/semantic-diff-injection.ts
|
|
77261
77465
|
import * as child_process5 from "node:child_process";
|
|
77262
77466
|
import * as fs52 from "node:fs";
|
|
77263
|
-
import * as
|
|
77467
|
+
import * as path78 from "node:path";
|
|
77264
77468
|
|
|
77265
77469
|
// src/diff/ast-diff.ts
|
|
77266
77470
|
init_tree_sitter();
|
|
@@ -78007,17 +78211,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
78007
78211
|
const fileConsumers = {};
|
|
78008
78212
|
if (graph) {
|
|
78009
78213
|
for (const f of filesToProcess) {
|
|
78010
|
-
const relativePath =
|
|
78214
|
+
const relativePath = path78.isAbsolute(f) ? path78.relative(directory, f) : f;
|
|
78011
78215
|
const normalized = normalizeGraphPath2(relativePath);
|
|
78012
78216
|
fileConsumers[normalized] = getImporters(graph, normalized).length;
|
|
78013
78217
|
fileConsumers[f] = fileConsumers[normalized];
|
|
78014
78218
|
}
|
|
78015
78219
|
}
|
|
78016
78220
|
for (const filePath of filesToProcess) {
|
|
78017
|
-
const normalizedPath =
|
|
78018
|
-
const resolvedPath =
|
|
78019
|
-
const relativeToDir =
|
|
78020
|
-
if (relativeToDir.startsWith("..") ||
|
|
78221
|
+
const normalizedPath = path78.normalize(filePath);
|
|
78222
|
+
const resolvedPath = path78.resolve(directory, normalizedPath);
|
|
78223
|
+
const relativeToDir = path78.relative(directory, resolvedPath);
|
|
78224
|
+
if (relativeToDir.startsWith("..") || path78.isAbsolute(relativeToDir)) {
|
|
78021
78225
|
continue;
|
|
78022
78226
|
}
|
|
78023
78227
|
try {
|
|
@@ -78044,7 +78248,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
|
|
|
78044
78248
|
stdio: "pipe",
|
|
78045
78249
|
maxBuffer: 5 * 1024 * 1024
|
|
78046
78250
|
}) : "";
|
|
78047
|
-
const newContent = fs52.readFileSync(
|
|
78251
|
+
const newContent = fs52.readFileSync(path78.join(directory, filePath), "utf-8");
|
|
78048
78252
|
const astResult = await computeASTDiff(filePath, oldContent, newContent);
|
|
78049
78253
|
if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
|
|
78050
78254
|
astDiffs.push(astResult);
|
|
@@ -78071,6 +78275,49 @@ ${markdown}`;
|
|
|
78071
78275
|
|
|
78072
78276
|
// src/hooks/system-enhancer.ts
|
|
78073
78277
|
init_utils2();
|
|
78278
|
+
function buildSpecDriftAdvisory(args2) {
|
|
78279
|
+
const lines = [
|
|
78280
|
+
"[spec-drift]",
|
|
78281
|
+
`Reason: ${args2.reason}`,
|
|
78282
|
+
`Stored spec hash: ${args2.storedHash}`,
|
|
78283
|
+
`Current spec hash: ${args2.currentHash ?? "(spec.md missing)"}`,
|
|
78284
|
+
"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."
|
|
78285
|
+
];
|
|
78286
|
+
if (args2.midLoadRemovals) {
|
|
78287
|
+
lines.push(`Auto-removed during recovery: ${args2.midLoadRemovals.count} task(s) ` + `(source: ${args2.midLoadRemovals.source}). See ` + ".swarm/plan-ledger.jsonl for IDs.");
|
|
78288
|
+
}
|
|
78289
|
+
return lines.join(`
|
|
78290
|
+
`);
|
|
78291
|
+
}
|
|
78292
|
+
function readSpecStalenessSnapshot2(directory) {
|
|
78293
|
+
try {
|
|
78294
|
+
const p = path80.join(directory, ".swarm", "spec-staleness.json");
|
|
78295
|
+
if (!fs54.existsSync(p))
|
|
78296
|
+
return null;
|
|
78297
|
+
const raw = fs54.readFileSync(p, "utf-8");
|
|
78298
|
+
const parsed = JSON.parse(raw);
|
|
78299
|
+
if (typeof parsed?.specHash_plan === "string" && (typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null)) {
|
|
78300
|
+
return {
|
|
78301
|
+
specHash_plan: parsed.specHash_plan,
|
|
78302
|
+
specHash_current: parsed.specHash_current
|
|
78303
|
+
};
|
|
78304
|
+
}
|
|
78305
|
+
} catch {}
|
|
78306
|
+
return null;
|
|
78307
|
+
}
|
|
78308
|
+
function maybeAppendSpecDriftAdvisory(output, directory, plan) {
|
|
78309
|
+
if (!plan?._specStale)
|
|
78310
|
+
return;
|
|
78311
|
+
const snap = readSpecStalenessSnapshot2(directory);
|
|
78312
|
+
const storedHash = snap?.specHash_plan ?? plan.specHash ?? "(unknown — plan missing specHash)";
|
|
78313
|
+
const currentHash = snap?.specHash_current ?? null;
|
|
78314
|
+
output.system.push(buildSpecDriftAdvisory({
|
|
78315
|
+
reason: plan._specStaleReason ?? "spec.md changed since plan was saved",
|
|
78316
|
+
currentHash,
|
|
78317
|
+
storedHash,
|
|
78318
|
+
midLoadRemovals: plan._midLoadRemovals
|
|
78319
|
+
}));
|
|
78320
|
+
}
|
|
78074
78321
|
function extractAgentPrefix(fullAgentName) {
|
|
78075
78322
|
if (!fullAgentName)
|
|
78076
78323
|
return "";
|
|
@@ -78392,7 +78639,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
78392
78639
|
await fs54.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
78393
78640
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
78394
78641
|
try {
|
|
78395
|
-
const projectName =
|
|
78642
|
+
const projectName = path80.basename(path80.resolve(directory));
|
|
78396
78643
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
78397
78644
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
78398
78645
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -78433,6 +78680,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
78433
78680
|
} catch (error93) {
|
|
78434
78681
|
warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
78435
78682
|
}
|
|
78683
|
+
maybeAppendSpecDriftAdvisory(output, directory, plan2);
|
|
78436
78684
|
const mode = await detectArchitectMode(directory);
|
|
78437
78685
|
let planContent = null;
|
|
78438
78686
|
let phaseHeader = "";
|
|
@@ -78591,7 +78839,7 @@ ${lines.join(`
|
|
|
78591
78839
|
try {
|
|
78592
78840
|
const taskId_ccp = ccpSession?.currentTaskId;
|
|
78593
78841
|
if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
|
|
78594
|
-
const evidencePath =
|
|
78842
|
+
const evidencePath = path80.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
|
|
78595
78843
|
if (fs54.existsSync(evidencePath)) {
|
|
78596
78844
|
const evidenceContent = fs54.readFileSync(evidencePath, "utf-8");
|
|
78597
78845
|
const evidenceData = JSON.parse(evidenceContent);
|
|
@@ -78806,6 +79054,7 @@ ${budgetWarning}`);
|
|
|
78806
79054
|
} catch (error93) {
|
|
78807
79055
|
warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
78808
79056
|
}
|
|
79057
|
+
maybeAppendSpecDriftAdvisory(output, directory, plan);
|
|
78809
79058
|
let currentPhase = null;
|
|
78810
79059
|
let currentTask = null;
|
|
78811
79060
|
if (plan && plan.migration_status !== "migration_failed") {
|
|
@@ -79754,7 +80003,7 @@ import * as fs56 from "node:fs";
|
|
|
79754
80003
|
// src/full-auto/policy.ts
|
|
79755
80004
|
init_constants();
|
|
79756
80005
|
import * as fs55 from "node:fs";
|
|
79757
|
-
import * as
|
|
80006
|
+
import * as path81 from "node:path";
|
|
79758
80007
|
var READ_ONLY_TOOLS = new Set([
|
|
79759
80008
|
"check_gate_status",
|
|
79760
80009
|
"completion_verify",
|
|
@@ -79949,11 +80198,11 @@ function normalizePath3(p) {
|
|
|
79949
80198
|
function isWithinDirectory(target, root) {
|
|
79950
80199
|
if (!target || !root)
|
|
79951
80200
|
return false;
|
|
79952
|
-
const resolvedTarget =
|
|
79953
|
-
const resolvedRoot =
|
|
80201
|
+
const resolvedTarget = path81.resolve(target);
|
|
80202
|
+
const resolvedRoot = path81.resolve(root);
|
|
79954
80203
|
if (resolvedTarget === resolvedRoot)
|
|
79955
80204
|
return true;
|
|
79956
|
-
const withSep = resolvedRoot.endsWith(
|
|
80205
|
+
const withSep = resolvedRoot.endsWith(path81.sep) ? resolvedRoot : resolvedRoot + path81.sep;
|
|
79957
80206
|
if (process.platform === "win32") {
|
|
79958
80207
|
return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());
|
|
79959
80208
|
}
|
|
@@ -80012,7 +80261,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80012
80261
|
highRiskBuild: false
|
|
80013
80262
|
};
|
|
80014
80263
|
}
|
|
80015
|
-
const absolute =
|
|
80264
|
+
const absolute = path81.isAbsolute(filePath) ? filePath : path81.resolve(context.directory, filePath);
|
|
80016
80265
|
const resolvedAbsolute = (() => {
|
|
80017
80266
|
try {
|
|
80018
80267
|
let candidate = absolute;
|
|
@@ -80028,7 +80277,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80028
80277
|
}
|
|
80029
80278
|
return absolute;
|
|
80030
80279
|
}
|
|
80031
|
-
const parent =
|
|
80280
|
+
const parent = path81.dirname(candidate);
|
|
80032
80281
|
if (parent === candidate)
|
|
80033
80282
|
break;
|
|
80034
80283
|
candidate = parent;
|
|
@@ -80040,7 +80289,7 @@ function classifyPathRisk(filePath, context) {
|
|
|
80040
80289
|
}
|
|
80041
80290
|
})();
|
|
80042
80291
|
const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
|
|
80043
|
-
const relative17 =
|
|
80292
|
+
const relative17 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
|
|
80044
80293
|
let withinDeclaredScope = null;
|
|
80045
80294
|
if (Array.isArray(context.declaredScope)) {
|
|
80046
80295
|
withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
|
|
@@ -80350,7 +80599,7 @@ function classifyFullAutoToolAction(input) {
|
|
|
80350
80599
|
recoverable: true
|
|
80351
80600
|
};
|
|
80352
80601
|
}
|
|
80353
|
-
if (isProtectedPath(
|
|
80602
|
+
if (isProtectedPath(path81.relative(input.directory, path81.resolve(input.directory, p)), config3)) {
|
|
80354
80603
|
return {
|
|
80355
80604
|
action: "escalate_critic",
|
|
80356
80605
|
reason: `write to protected path requires critic approval: ${p}`,
|
|
@@ -81124,7 +81373,7 @@ init_hive_promoter();
|
|
|
81124
81373
|
|
|
81125
81374
|
// src/hooks/incremental-verify.ts
|
|
81126
81375
|
import * as fs58 from "node:fs";
|
|
81127
|
-
import * as
|
|
81376
|
+
import * as path82 from "node:path";
|
|
81128
81377
|
|
|
81129
81378
|
// src/hooks/spawn-helper.ts
|
|
81130
81379
|
import * as child_process6 from "node:child_process";
|
|
@@ -81202,18 +81451,18 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
81202
81451
|
// src/hooks/incremental-verify.ts
|
|
81203
81452
|
var emittedSkipAdvisories = new Set;
|
|
81204
81453
|
function detectPackageManager(projectDir) {
|
|
81205
|
-
if (fs58.existsSync(
|
|
81454
|
+
if (fs58.existsSync(path82.join(projectDir, "bun.lockb")))
|
|
81206
81455
|
return "bun";
|
|
81207
|
-
if (fs58.existsSync(
|
|
81456
|
+
if (fs58.existsSync(path82.join(projectDir, "pnpm-lock.yaml")))
|
|
81208
81457
|
return "pnpm";
|
|
81209
|
-
if (fs58.existsSync(
|
|
81458
|
+
if (fs58.existsSync(path82.join(projectDir, "yarn.lock")))
|
|
81210
81459
|
return "yarn";
|
|
81211
|
-
if (fs58.existsSync(
|
|
81460
|
+
if (fs58.existsSync(path82.join(projectDir, "package-lock.json")))
|
|
81212
81461
|
return "npm";
|
|
81213
81462
|
return "bun";
|
|
81214
81463
|
}
|
|
81215
81464
|
function detectTypecheckCommand(projectDir) {
|
|
81216
|
-
const pkgPath =
|
|
81465
|
+
const pkgPath = path82.join(projectDir, "package.json");
|
|
81217
81466
|
if (fs58.existsSync(pkgPath)) {
|
|
81218
81467
|
try {
|
|
81219
81468
|
const pkg = JSON.parse(fs58.readFileSync(pkgPath, "utf8"));
|
|
@@ -81230,8 +81479,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
81230
81479
|
...pkg.dependencies,
|
|
81231
81480
|
...pkg.devDependencies
|
|
81232
81481
|
};
|
|
81233
|
-
if (!deps?.typescript && !fs58.existsSync(
|
|
81234
|
-
const hasTSMarkers = deps?.typescript || fs58.existsSync(
|
|
81482
|
+
if (!deps?.typescript && !fs58.existsSync(path82.join(projectDir, "tsconfig.json"))) {}
|
|
81483
|
+
const hasTSMarkers = deps?.typescript || fs58.existsSync(path82.join(projectDir, "tsconfig.json"));
|
|
81235
81484
|
if (hasTSMarkers) {
|
|
81236
81485
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
81237
81486
|
}
|
|
@@ -81239,13 +81488,13 @@ function detectTypecheckCommand(projectDir) {
|
|
|
81239
81488
|
return null;
|
|
81240
81489
|
}
|
|
81241
81490
|
}
|
|
81242
|
-
if (fs58.existsSync(
|
|
81491
|
+
if (fs58.existsSync(path82.join(projectDir, "go.mod"))) {
|
|
81243
81492
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
81244
81493
|
}
|
|
81245
|
-
if (fs58.existsSync(
|
|
81494
|
+
if (fs58.existsSync(path82.join(projectDir, "Cargo.toml"))) {
|
|
81246
81495
|
return { command: ["cargo", "check"], language: "rust" };
|
|
81247
81496
|
}
|
|
81248
|
-
if (fs58.existsSync(
|
|
81497
|
+
if (fs58.existsSync(path82.join(projectDir, "pyproject.toml")) || fs58.existsSync(path82.join(projectDir, "requirements.txt")) || fs58.existsSync(path82.join(projectDir, "setup.py"))) {
|
|
81249
81498
|
return { command: null, language: "python" };
|
|
81250
81499
|
}
|
|
81251
81500
|
try {
|
|
@@ -81322,17 +81571,17 @@ init_schema();
|
|
|
81322
81571
|
init_state();
|
|
81323
81572
|
init_logger();
|
|
81324
81573
|
import { appendFile as appendFile7, mkdir as mkdir15 } from "node:fs/promises";
|
|
81325
|
-
import * as
|
|
81574
|
+
import * as path84 from "node:path";
|
|
81326
81575
|
|
|
81327
81576
|
// src/hooks/knowledge-application.ts
|
|
81328
81577
|
init_logger();
|
|
81329
81578
|
init_knowledge_store();
|
|
81330
81579
|
var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
|
|
81331
|
-
import { existsSync as
|
|
81580
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
81332
81581
|
import { appendFile as appendFile6, mkdir as mkdir14, readFile as readFile13 } from "node:fs/promises";
|
|
81333
|
-
import * as
|
|
81582
|
+
import * as path83 from "node:path";
|
|
81334
81583
|
function resolveApplicationLogPath(directory) {
|
|
81335
|
-
return
|
|
81584
|
+
return path83.join(directory, ".swarm", "knowledge-application.jsonl");
|
|
81336
81585
|
}
|
|
81337
81586
|
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
81587
|
function parseAcknowledgments(text) {
|
|
@@ -81350,7 +81599,7 @@ function parseAcknowledgments(text) {
|
|
|
81350
81599
|
}
|
|
81351
81600
|
async function appendAudit(directory, record3) {
|
|
81352
81601
|
const filePath = resolveApplicationLogPath(directory);
|
|
81353
|
-
await mkdir14(
|
|
81602
|
+
await mkdir14(path83.dirname(filePath), { recursive: true });
|
|
81354
81603
|
await appendFile6(filePath, `${JSON.stringify(record3)}
|
|
81355
81604
|
`, "utf-8");
|
|
81356
81605
|
}
|
|
@@ -81394,7 +81643,7 @@ async function bumpCountersBatch(directory, bumps) {
|
|
|
81394
81643
|
if (applyOne(swarm))
|
|
81395
81644
|
await rewriteKnowledge(swarmPath, swarm);
|
|
81396
81645
|
const hivePath = resolveHiveKnowledgePath();
|
|
81397
|
-
if (
|
|
81646
|
+
if (existsSync45(hivePath)) {
|
|
81398
81647
|
const hive = await readKnowledge(hivePath);
|
|
81399
81648
|
if (applyOne(hive))
|
|
81400
81649
|
await rewriteKnowledge(hivePath, hive);
|
|
@@ -81516,8 +81765,8 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
|
|
|
81516
81765
|
}).catch(() => {});
|
|
81517
81766
|
}
|
|
81518
81767
|
async function writeWarnEvent(directory, record3) {
|
|
81519
|
-
const filePath =
|
|
81520
|
-
await mkdir15(
|
|
81768
|
+
const filePath = path84.join(directory, ".swarm", "events.jsonl");
|
|
81769
|
+
await mkdir15(path84.dirname(filePath), { recursive: true });
|
|
81521
81770
|
await appendFile7(filePath, `${JSON.stringify(record3)}
|
|
81522
81771
|
`, "utf-8");
|
|
81523
81772
|
}
|
|
@@ -82018,7 +82267,7 @@ init_scope_persistence();
|
|
|
82018
82267
|
init_state();
|
|
82019
82268
|
init_delegation_gate();
|
|
82020
82269
|
init_normalize_tool_name();
|
|
82021
|
-
import * as
|
|
82270
|
+
import * as path86 from "node:path";
|
|
82022
82271
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
82023
82272
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
82024
82273
|
const enabled = config3.enabled ?? true;
|
|
@@ -82076,13 +82325,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
82076
82325
|
}
|
|
82077
82326
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
82078
82327
|
const dir = directory ?? process.cwd();
|
|
82079
|
-
const resolvedFile =
|
|
82328
|
+
const resolvedFile = path86.resolve(dir, filePath);
|
|
82080
82329
|
return scopeEntries.some((scope) => {
|
|
82081
|
-
const resolvedScope =
|
|
82330
|
+
const resolvedScope = path86.resolve(dir, scope);
|
|
82082
82331
|
if (resolvedFile === resolvedScope)
|
|
82083
82332
|
return true;
|
|
82084
|
-
const rel =
|
|
82085
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
82333
|
+
const rel = path86.relative(resolvedScope, resolvedFile);
|
|
82334
|
+
return rel.length > 0 && !rel.startsWith("..") && !path86.isAbsolute(rel);
|
|
82086
82335
|
});
|
|
82087
82336
|
}
|
|
82088
82337
|
|
|
@@ -82134,7 +82383,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
82134
82383
|
|
|
82135
82384
|
// src/hooks/slop-detector.ts
|
|
82136
82385
|
import * as fs61 from "node:fs";
|
|
82137
|
-
import * as
|
|
82386
|
+
import * as path87 from "node:path";
|
|
82138
82387
|
var WRITE_EDIT_TOOLS = new Set([
|
|
82139
82388
|
"write",
|
|
82140
82389
|
"edit",
|
|
@@ -82184,7 +82433,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
82184
82433
|
break;
|
|
82185
82434
|
if (entry.isSymbolicLink())
|
|
82186
82435
|
continue;
|
|
82187
|
-
const full =
|
|
82436
|
+
const full = path87.join(dir, entry.name);
|
|
82188
82437
|
if (entry.isDirectory()) {
|
|
82189
82438
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
82190
82439
|
continue;
|
|
@@ -82199,7 +82448,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
82199
82448
|
return results;
|
|
82200
82449
|
}
|
|
82201
82450
|
function checkDeadExports(content, projectDir, startTime) {
|
|
82202
|
-
const hasPackageJson = fs61.existsSync(
|
|
82451
|
+
const hasPackageJson = fs61.existsSync(path87.join(projectDir, "package.json"));
|
|
82203
82452
|
if (!hasPackageJson)
|
|
82204
82453
|
return null;
|
|
82205
82454
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -82313,14 +82562,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
|
|
|
82313
82562
|
for (const utilDir of utilityDirs) {
|
|
82314
82563
|
if (Date.now() > deadline)
|
|
82315
82564
|
break;
|
|
82316
|
-
const utilPath =
|
|
82565
|
+
const utilPath = path87.join(projectDir, utilDir);
|
|
82317
82566
|
if (!fs61.existsSync(utilPath))
|
|
82318
82567
|
continue;
|
|
82319
82568
|
const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
|
|
82320
82569
|
for (const file3 of files) {
|
|
82321
82570
|
if (Date.now() > deadline)
|
|
82322
82571
|
break;
|
|
82323
|
-
if (targetFile &&
|
|
82572
|
+
if (targetFile && path87.resolve(file3) === path87.resolve(targetFile))
|
|
82324
82573
|
continue;
|
|
82325
82574
|
try {
|
|
82326
82575
|
const text = fs61.readFileSync(file3, "utf-8");
|
|
@@ -82458,14 +82707,14 @@ function createSteeringConsumedHook(directory) {
|
|
|
82458
82707
|
// src/hooks/trajectory-logger.ts
|
|
82459
82708
|
init_manager2();
|
|
82460
82709
|
import * as fs64 from "node:fs/promises";
|
|
82461
|
-
import * as
|
|
82710
|
+
import * as path89 from "node:path";
|
|
82462
82711
|
|
|
82463
82712
|
// src/prm/trajectory-store.ts
|
|
82464
82713
|
init_utils2();
|
|
82465
82714
|
import * as fs63 from "node:fs/promises";
|
|
82466
|
-
import * as
|
|
82715
|
+
import * as path88 from "node:path";
|
|
82467
82716
|
function getTrajectoryPath(sessionId, directory) {
|
|
82468
|
-
const relativePath =
|
|
82717
|
+
const relativePath = path88.join("trajectories", `${sessionId}.jsonl`);
|
|
82469
82718
|
return validateSwarmPath(directory, relativePath);
|
|
82470
82719
|
}
|
|
82471
82720
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -82484,7 +82733,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
|
|
|
82484
82733
|
_inMemoryTrajectoryCache.set(sessionId, cached3);
|
|
82485
82734
|
}
|
|
82486
82735
|
const trajectoryPath = getTrajectoryPath(sessionId, directory);
|
|
82487
|
-
await fs63.mkdir(
|
|
82736
|
+
await fs63.mkdir(path88.dirname(trajectoryPath), { recursive: true });
|
|
82488
82737
|
const line = `${JSON.stringify(entry)}
|
|
82489
82738
|
`;
|
|
82490
82739
|
await fs63.appendFile(trajectoryPath, line, "utf-8");
|
|
@@ -82523,7 +82772,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
82523
82772
|
for (const entry of entries) {
|
|
82524
82773
|
if (!entry.isFile())
|
|
82525
82774
|
continue;
|
|
82526
|
-
const filePath =
|
|
82775
|
+
const filePath = path88.join(dirPath, entry.name);
|
|
82527
82776
|
try {
|
|
82528
82777
|
const stat8 = await fs63.stat(filePath);
|
|
82529
82778
|
if (now - stat8.mtimeMs > cutoffMs) {
|
|
@@ -82715,10 +82964,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
|
|
|
82715
82964
|
elapsed_ms
|
|
82716
82965
|
};
|
|
82717
82966
|
const sanitized = sanitizeTaskId2(taskId);
|
|
82718
|
-
const relativePath =
|
|
82967
|
+
const relativePath = path89.join("evidence", sanitized, "trajectory.jsonl");
|
|
82719
82968
|
const trajectoryPath = validateSwarmPath(_directory, relativePath);
|
|
82720
82969
|
try {
|
|
82721
|
-
await fs64.mkdir(
|
|
82970
|
+
await fs64.mkdir(path89.dirname(trajectoryPath), { recursive: true });
|
|
82722
82971
|
const line = `${JSON.stringify(entry)}
|
|
82723
82972
|
`;
|
|
82724
82973
|
await fs64.appendFile(trajectoryPath, line, "utf-8");
|
|
@@ -83269,16 +83518,16 @@ init_telemetry();
|
|
|
83269
83518
|
|
|
83270
83519
|
// src/prm/replay.ts
|
|
83271
83520
|
import { promises as fs65 } from "node:fs";
|
|
83272
|
-
import
|
|
83521
|
+
import path90 from "node:path";
|
|
83273
83522
|
function isPathSafe2(targetPath, basePath) {
|
|
83274
|
-
const resolvedTarget =
|
|
83275
|
-
const resolvedBase =
|
|
83276
|
-
const rel =
|
|
83277
|
-
return !rel.startsWith("..") && !
|
|
83523
|
+
const resolvedTarget = path90.resolve(targetPath);
|
|
83524
|
+
const resolvedBase = path90.resolve(basePath);
|
|
83525
|
+
const rel = path90.relative(resolvedBase, resolvedTarget);
|
|
83526
|
+
return !rel.startsWith("..") && !path90.isAbsolute(rel);
|
|
83278
83527
|
}
|
|
83279
83528
|
function isWithinReplaysDir(targetPath) {
|
|
83280
|
-
const resolved =
|
|
83281
|
-
const parts2 = resolved.split(
|
|
83529
|
+
const resolved = path90.resolve(targetPath);
|
|
83530
|
+
const parts2 = resolved.split(path90.sep);
|
|
83282
83531
|
for (let i2 = 0;i2 < parts2.length - 1; i2++) {
|
|
83283
83532
|
if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
|
|
83284
83533
|
return true;
|
|
@@ -83291,10 +83540,10 @@ function sanitizeFilename(input) {
|
|
|
83291
83540
|
}
|
|
83292
83541
|
async function startReplayRecording(sessionID, directory) {
|
|
83293
83542
|
try {
|
|
83294
|
-
const replayDir =
|
|
83543
|
+
const replayDir = path90.join(directory, ".swarm", "replays");
|
|
83295
83544
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
83296
83545
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
83297
|
-
const filepath =
|
|
83546
|
+
const filepath = path90.join(replayDir, filename);
|
|
83298
83547
|
if (!isPathSafe2(filepath, replayDir)) {
|
|
83299
83548
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
83300
83549
|
return null;
|
|
@@ -83668,7 +83917,7 @@ init_telemetry();
|
|
|
83668
83917
|
init_dist();
|
|
83669
83918
|
init_create_tool();
|
|
83670
83919
|
import * as fs66 from "node:fs";
|
|
83671
|
-
import * as
|
|
83920
|
+
import * as path91 from "node:path";
|
|
83672
83921
|
init_path_security();
|
|
83673
83922
|
var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
83674
83923
|
function containsWindowsAttacks2(str) {
|
|
@@ -83685,14 +83934,14 @@ function containsWindowsAttacks2(str) {
|
|
|
83685
83934
|
}
|
|
83686
83935
|
function isPathInWorkspace2(filePath, workspace) {
|
|
83687
83936
|
try {
|
|
83688
|
-
const resolvedPath =
|
|
83937
|
+
const resolvedPath = path91.resolve(workspace, filePath);
|
|
83689
83938
|
if (!fs66.existsSync(resolvedPath)) {
|
|
83690
83939
|
return true;
|
|
83691
83940
|
}
|
|
83692
83941
|
const realWorkspace = fs66.realpathSync(workspace);
|
|
83693
83942
|
const realResolvedPath = fs66.realpathSync(resolvedPath);
|
|
83694
|
-
const relativePath =
|
|
83695
|
-
if (relativePath.startsWith("..") ||
|
|
83943
|
+
const relativePath = path91.relative(realWorkspace, realResolvedPath);
|
|
83944
|
+
if (relativePath.startsWith("..") || path91.isAbsolute(relativePath)) {
|
|
83696
83945
|
return false;
|
|
83697
83946
|
}
|
|
83698
83947
|
return true;
|
|
@@ -83701,7 +83950,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
83701
83950
|
}
|
|
83702
83951
|
}
|
|
83703
83952
|
function processFile2(file3, cwd, exportedOnly) {
|
|
83704
|
-
const ext =
|
|
83953
|
+
const ext = path91.extname(file3);
|
|
83705
83954
|
if (containsControlChars(file3)) {
|
|
83706
83955
|
return {
|
|
83707
83956
|
file: file3,
|
|
@@ -83734,7 +83983,7 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
83734
83983
|
errorType: "path-outside-workspace"
|
|
83735
83984
|
};
|
|
83736
83985
|
}
|
|
83737
|
-
const fullPath =
|
|
83986
|
+
const fullPath = path91.join(cwd, file3);
|
|
83738
83987
|
if (!fs66.existsSync(fullPath)) {
|
|
83739
83988
|
return {
|
|
83740
83989
|
file: file3,
|
|
@@ -84026,15 +84275,15 @@ init_task_id();
|
|
|
84026
84275
|
init_create_tool();
|
|
84027
84276
|
init_resolve_working_directory();
|
|
84028
84277
|
import * as fs67 from "node:fs";
|
|
84029
|
-
import * as
|
|
84278
|
+
import * as path92 from "node:path";
|
|
84030
84279
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
84031
84280
|
function isValidTaskId3(taskId) {
|
|
84032
84281
|
return isStrictTaskId(taskId);
|
|
84033
84282
|
}
|
|
84034
84283
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
84035
|
-
const normalizedWorkspace =
|
|
84036
|
-
const swarmPath =
|
|
84037
|
-
const normalizedPath =
|
|
84284
|
+
const normalizedWorkspace = path92.resolve(workspaceRoot);
|
|
84285
|
+
const swarmPath = path92.join(normalizedWorkspace, ".swarm", "evidence");
|
|
84286
|
+
const normalizedPath = path92.resolve(filePath);
|
|
84038
84287
|
return normalizedPath.startsWith(swarmPath);
|
|
84039
84288
|
}
|
|
84040
84289
|
function readEvidenceFile(evidencePath) {
|
|
@@ -84115,7 +84364,7 @@ var check_gate_status = createSwarmTool({
|
|
|
84115
84364
|
};
|
|
84116
84365
|
return JSON.stringify(errorResult, null, 2);
|
|
84117
84366
|
}
|
|
84118
|
-
const evidencePath =
|
|
84367
|
+
const evidencePath = path92.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
84119
84368
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
84120
84369
|
const errorResult = {
|
|
84121
84370
|
taskId: taskIdInput,
|
|
@@ -84212,7 +84461,7 @@ init_state();
|
|
|
84212
84461
|
init_create_tool();
|
|
84213
84462
|
init_resolve_working_directory();
|
|
84214
84463
|
import * as fs68 from "node:fs";
|
|
84215
|
-
import * as
|
|
84464
|
+
import * as path93 from "node:path";
|
|
84216
84465
|
function extractMatches(regex, text) {
|
|
84217
84466
|
return Array.from(text.matchAll(regex));
|
|
84218
84467
|
}
|
|
@@ -84364,10 +84613,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84364
84613
|
let hasFileReadFailure = false;
|
|
84365
84614
|
for (const filePath of fileTargets) {
|
|
84366
84615
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
84367
|
-
const resolvedPath =
|
|
84368
|
-
const projectRoot =
|
|
84369
|
-
const relative20 =
|
|
84370
|
-
const withinProject = relative20 === "" || !relative20.startsWith("..") && !
|
|
84616
|
+
const resolvedPath = path93.resolve(directory, normalizedPath);
|
|
84617
|
+
const projectRoot = path93.resolve(directory);
|
|
84618
|
+
const relative20 = path93.relative(projectRoot, resolvedPath);
|
|
84619
|
+
const withinProject = relative20 === "" || !relative20.startsWith("..") && !path93.isAbsolute(relative20);
|
|
84371
84620
|
if (!withinProject) {
|
|
84372
84621
|
blockedTasks.push({
|
|
84373
84622
|
task_id: task.id,
|
|
@@ -84422,8 +84671,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84422
84671
|
blockedTasks
|
|
84423
84672
|
};
|
|
84424
84673
|
try {
|
|
84425
|
-
const evidenceDir =
|
|
84426
|
-
const evidencePath =
|
|
84674
|
+
const evidenceDir = path93.join(directory, ".swarm", "evidence", `${phase}`);
|
|
84675
|
+
const evidencePath = path93.join(evidenceDir, "completion-verify.json");
|
|
84427
84676
|
fs68.mkdirSync(evidenceDir, { recursive: true });
|
|
84428
84677
|
const evidenceBundle = {
|
|
84429
84678
|
schema_version: "1.0.0",
|
|
@@ -84500,11 +84749,11 @@ var completion_verify = createSwarmTool({
|
|
|
84500
84749
|
// src/tools/complexity-hotspots.ts
|
|
84501
84750
|
init_zod();
|
|
84502
84751
|
import * as fs70 from "node:fs";
|
|
84503
|
-
import * as
|
|
84752
|
+
import * as path95 from "node:path";
|
|
84504
84753
|
|
|
84505
84754
|
// src/quality/metrics.ts
|
|
84506
84755
|
import * as fs69 from "node:fs";
|
|
84507
|
-
import * as
|
|
84756
|
+
import * as path94 from "node:path";
|
|
84508
84757
|
var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
|
|
84509
84758
|
var MIN_DUPLICATION_LINES = 10;
|
|
84510
84759
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -84556,7 +84805,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
84556
84805
|
let totalComplexity = 0;
|
|
84557
84806
|
const analyzedFiles = [];
|
|
84558
84807
|
for (const file3 of files) {
|
|
84559
|
-
const fullPath =
|
|
84808
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84560
84809
|
if (!fs69.existsSync(fullPath)) {
|
|
84561
84810
|
continue;
|
|
84562
84811
|
}
|
|
@@ -84679,7 +84928,7 @@ function countGoExports(content) {
|
|
|
84679
84928
|
function getExportCountForFile(filePath) {
|
|
84680
84929
|
try {
|
|
84681
84930
|
const content = fs69.readFileSync(filePath, "utf-8");
|
|
84682
|
-
const ext =
|
|
84931
|
+
const ext = path94.extname(filePath).toLowerCase();
|
|
84683
84932
|
switch (ext) {
|
|
84684
84933
|
case ".ts":
|
|
84685
84934
|
case ".tsx":
|
|
@@ -84705,7 +84954,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
84705
84954
|
let totalExports = 0;
|
|
84706
84955
|
const analyzedFiles = [];
|
|
84707
84956
|
for (const file3 of files) {
|
|
84708
|
-
const fullPath =
|
|
84957
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84709
84958
|
if (!fs69.existsSync(fullPath)) {
|
|
84710
84959
|
continue;
|
|
84711
84960
|
}
|
|
@@ -84739,7 +84988,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
84739
84988
|
let duplicateLines = 0;
|
|
84740
84989
|
const analyzedFiles = [];
|
|
84741
84990
|
for (const file3 of files) {
|
|
84742
|
-
const fullPath =
|
|
84991
|
+
const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
|
|
84743
84992
|
if (!fs69.existsSync(fullPath)) {
|
|
84744
84993
|
continue;
|
|
84745
84994
|
}
|
|
@@ -84772,8 +85021,8 @@ function countCodeLines(content) {
|
|
|
84772
85021
|
return lines.length;
|
|
84773
85022
|
}
|
|
84774
85023
|
function isTestFile(filePath) {
|
|
84775
|
-
const basename12 =
|
|
84776
|
-
const _ext =
|
|
85024
|
+
const basename12 = path94.basename(filePath);
|
|
85025
|
+
const _ext = path94.extname(filePath).toLowerCase();
|
|
84777
85026
|
const testPatterns = [
|
|
84778
85027
|
".test.",
|
|
84779
85028
|
".spec.",
|
|
@@ -84854,8 +85103,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
84854
85103
|
}
|
|
84855
85104
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
84856
85105
|
}
|
|
84857
|
-
function matchesGlobSegment(
|
|
84858
|
-
const normalizedPath =
|
|
85106
|
+
function matchesGlobSegment(path95, glob) {
|
|
85107
|
+
const normalizedPath = path95.replace(/\\/g, "/");
|
|
84859
85108
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
84860
85109
|
if (normalizedPath.includes("//")) {
|
|
84861
85110
|
return false;
|
|
@@ -84886,8 +85135,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
84886
85135
|
function hasGlobstar(glob) {
|
|
84887
85136
|
return glob.includes("**");
|
|
84888
85137
|
}
|
|
84889
|
-
function globMatches(
|
|
84890
|
-
const normalizedPath =
|
|
85138
|
+
function globMatches(path95, glob) {
|
|
85139
|
+
const normalizedPath = path95.replace(/\\/g, "/");
|
|
84891
85140
|
if (!glob || glob === "") {
|
|
84892
85141
|
if (normalizedPath.includes("//")) {
|
|
84893
85142
|
return false;
|
|
@@ -84923,7 +85172,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
84923
85172
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
84924
85173
|
let testLines = 0;
|
|
84925
85174
|
let codeLines = 0;
|
|
84926
|
-
const srcDir =
|
|
85175
|
+
const srcDir = path94.join(workingDir, "src");
|
|
84927
85176
|
if (fs69.existsSync(srcDir)) {
|
|
84928
85177
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
84929
85178
|
codeLines += lines;
|
|
@@ -84931,14 +85180,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
84931
85180
|
}
|
|
84932
85181
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
84933
85182
|
for (const dir of possibleSrcDirs) {
|
|
84934
|
-
const dirPath =
|
|
85183
|
+
const dirPath = path94.join(workingDir, dir);
|
|
84935
85184
|
if (fs69.existsSync(dirPath)) {
|
|
84936
85185
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
84937
85186
|
codeLines += lines;
|
|
84938
85187
|
});
|
|
84939
85188
|
}
|
|
84940
85189
|
}
|
|
84941
|
-
const testsDir =
|
|
85190
|
+
const testsDir = path94.join(workingDir, "tests");
|
|
84942
85191
|
if (fs69.existsSync(testsDir)) {
|
|
84943
85192
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
84944
85193
|
testLines += lines;
|
|
@@ -84946,7 +85195,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
84946
85195
|
}
|
|
84947
85196
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
84948
85197
|
for (const dir of possibleTestDirs) {
|
|
84949
|
-
const dirPath =
|
|
85198
|
+
const dirPath = path94.join(workingDir, dir);
|
|
84950
85199
|
if (fs69.existsSync(dirPath) && dirPath !== testsDir) {
|
|
84951
85200
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
84952
85201
|
testLines += lines;
|
|
@@ -84961,7 +85210,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
84961
85210
|
try {
|
|
84962
85211
|
const entries = fs69.readdirSync(dirPath, { withFileTypes: true });
|
|
84963
85212
|
for (const entry of entries) {
|
|
84964
|
-
const fullPath =
|
|
85213
|
+
const fullPath = path94.join(dirPath, entry.name);
|
|
84965
85214
|
if (entry.isDirectory()) {
|
|
84966
85215
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
84967
85216
|
continue;
|
|
@@ -84969,7 +85218,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
84969
85218
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
84970
85219
|
} else if (entry.isFile()) {
|
|
84971
85220
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
84972
|
-
const ext =
|
|
85221
|
+
const ext = path94.extname(entry.name).toLowerCase();
|
|
84973
85222
|
const validExts = [
|
|
84974
85223
|
".ts",
|
|
84975
85224
|
".tsx",
|
|
@@ -85220,7 +85469,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85220
85469
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
85221
85470
|
const filteredChurn = new Map;
|
|
85222
85471
|
for (const [file3, count] of churnMap) {
|
|
85223
|
-
const ext =
|
|
85472
|
+
const ext = path95.extname(file3).toLowerCase();
|
|
85224
85473
|
if (extSet.has(ext)) {
|
|
85225
85474
|
filteredChurn.set(file3, count);
|
|
85226
85475
|
}
|
|
@@ -85231,7 +85480,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85231
85480
|
for (const [file3, churnCount] of filteredChurn) {
|
|
85232
85481
|
let fullPath = file3;
|
|
85233
85482
|
if (!fs70.existsSync(fullPath)) {
|
|
85234
|
-
fullPath =
|
|
85483
|
+
fullPath = path95.join(cwd, file3);
|
|
85235
85484
|
}
|
|
85236
85485
|
const complexity = getComplexityForFile2(fullPath);
|
|
85237
85486
|
if (complexity !== null) {
|
|
@@ -85400,12 +85649,12 @@ ${body2}`);
|
|
|
85400
85649
|
// src/council/council-evidence-writer.ts
|
|
85401
85650
|
import {
|
|
85402
85651
|
appendFileSync as appendFileSync9,
|
|
85403
|
-
existsSync as
|
|
85652
|
+
existsSync as existsSync51,
|
|
85404
85653
|
mkdirSync as mkdirSync22,
|
|
85405
|
-
readFileSync as
|
|
85654
|
+
readFileSync as readFileSync42,
|
|
85406
85655
|
writeFileSync as writeFileSync15
|
|
85407
85656
|
} from "node:fs";
|
|
85408
|
-
import { join as
|
|
85657
|
+
import { join as join81 } from "node:path";
|
|
85409
85658
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
85410
85659
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
85411
85660
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -85439,13 +85688,13 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85439
85688
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
85440
85689
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
85441
85690
|
}
|
|
85442
|
-
const dir =
|
|
85691
|
+
const dir = join81(workingDir, EVIDENCE_DIR2);
|
|
85443
85692
|
mkdirSync22(dir, { recursive: true });
|
|
85444
|
-
const filePath =
|
|
85693
|
+
const filePath = join81(dir, `${synthesis.taskId}.json`);
|
|
85445
85694
|
const existingRoot = Object.create(null);
|
|
85446
|
-
if (
|
|
85695
|
+
if (existsSync51(filePath)) {
|
|
85447
85696
|
try {
|
|
85448
|
-
const parsed = JSON.parse(
|
|
85697
|
+
const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
|
|
85449
85698
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
85450
85699
|
safeAssignOwnProps(existingRoot, parsed);
|
|
85451
85700
|
}
|
|
@@ -85475,7 +85724,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85475
85724
|
updated.required_gates = [];
|
|
85476
85725
|
writeFileSync15(filePath, JSON.stringify(updated, null, 2));
|
|
85477
85726
|
try {
|
|
85478
|
-
const councilDir =
|
|
85727
|
+
const councilDir = join81(workingDir, ".swarm", "council");
|
|
85479
85728
|
mkdirSync22(councilDir, { recursive: true });
|
|
85480
85729
|
const auditLine = JSON.stringify({
|
|
85481
85730
|
round: synthesis.roundNumber,
|
|
@@ -85483,7 +85732,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85483
85732
|
timestamp: synthesis.timestamp,
|
|
85484
85733
|
vetoedBy: synthesis.vetoedBy
|
|
85485
85734
|
});
|
|
85486
|
-
appendFileSync9(
|
|
85735
|
+
appendFileSync9(join81(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
85487
85736
|
`);
|
|
85488
85737
|
} catch (auditError) {
|
|
85489
85738
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -85805,25 +86054,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
85805
86054
|
}
|
|
85806
86055
|
|
|
85807
86056
|
// src/council/criteria-store.ts
|
|
85808
|
-
import { existsSync as
|
|
85809
|
-
import { join as
|
|
86057
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync23, readFileSync as readFileSync43, writeFileSync as writeFileSync16 } from "node:fs";
|
|
86058
|
+
import { join as join82 } from "node:path";
|
|
85810
86059
|
var COUNCIL_DIR = ".swarm/council";
|
|
85811
86060
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
85812
|
-
const dir =
|
|
86061
|
+
const dir = join82(workingDir, COUNCIL_DIR);
|
|
85813
86062
|
mkdirSync23(dir, { recursive: true });
|
|
85814
86063
|
const payload = {
|
|
85815
86064
|
taskId,
|
|
85816
86065
|
criteria,
|
|
85817
86066
|
declaredAt: new Date().toISOString()
|
|
85818
86067
|
};
|
|
85819
|
-
writeFileSync16(
|
|
86068
|
+
writeFileSync16(join82(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
85820
86069
|
}
|
|
85821
86070
|
function readCriteria(workingDir, taskId) {
|
|
85822
|
-
const filePath =
|
|
85823
|
-
if (!
|
|
86071
|
+
const filePath = join82(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
86072
|
+
if (!existsSync52(filePath))
|
|
85824
86073
|
return null;
|
|
85825
86074
|
try {
|
|
85826
|
-
const parsed = JSON.parse(
|
|
86075
|
+
const parsed = JSON.parse(readFileSync43(filePath, "utf-8"));
|
|
85827
86076
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
85828
86077
|
return parsed;
|
|
85829
86078
|
}
|
|
@@ -85972,7 +86221,7 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
85972
86221
|
init_zod();
|
|
85973
86222
|
init_loader();
|
|
85974
86223
|
import * as fs71 from "node:fs";
|
|
85975
|
-
import * as
|
|
86224
|
+
import * as path96 from "node:path";
|
|
85976
86225
|
|
|
85977
86226
|
// src/council/general-council-advisory.ts
|
|
85978
86227
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -86400,10 +86649,10 @@ var convene_general_council = createSwarmTool({
|
|
|
86400
86649
|
const round1 = input.round1Responses;
|
|
86401
86650
|
const round2 = input.round2Responses ?? [];
|
|
86402
86651
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
86403
|
-
const evidenceDir =
|
|
86652
|
+
const evidenceDir = path96.join(workingDir, ".swarm", "council", "general");
|
|
86404
86653
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
86405
86654
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
86406
|
-
const evidencePath =
|
|
86655
|
+
const evidencePath = path96.join(evidenceDir, evidenceFile);
|
|
86407
86656
|
try {
|
|
86408
86657
|
await fs71.promises.mkdir(evidenceDir, { recursive: true });
|
|
86409
86658
|
await fs71.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
@@ -86648,7 +86897,7 @@ init_state();
|
|
|
86648
86897
|
init_task_id();
|
|
86649
86898
|
init_create_tool();
|
|
86650
86899
|
import * as fs72 from "node:fs";
|
|
86651
|
-
import * as
|
|
86900
|
+
import * as path97 from "node:path";
|
|
86652
86901
|
function validateTaskIdFormat2(taskId) {
|
|
86653
86902
|
return validateTaskIdFormat(taskId);
|
|
86654
86903
|
}
|
|
@@ -86722,8 +86971,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86722
86971
|
};
|
|
86723
86972
|
}
|
|
86724
86973
|
}
|
|
86725
|
-
normalizedDir =
|
|
86726
|
-
const pathParts = normalizedDir.split(
|
|
86974
|
+
normalizedDir = path97.normalize(args2.working_directory);
|
|
86975
|
+
const pathParts = normalizedDir.split(path97.sep);
|
|
86727
86976
|
if (pathParts.includes("..")) {
|
|
86728
86977
|
return {
|
|
86729
86978
|
success: false,
|
|
@@ -86733,10 +86982,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86733
86982
|
]
|
|
86734
86983
|
};
|
|
86735
86984
|
}
|
|
86736
|
-
const resolvedDir =
|
|
86985
|
+
const resolvedDir = path97.resolve(normalizedDir);
|
|
86737
86986
|
try {
|
|
86738
86987
|
const realPath = fs72.realpathSync(resolvedDir);
|
|
86739
|
-
const planPath2 =
|
|
86988
|
+
const planPath2 = path97.join(realPath, ".swarm", "plan.json");
|
|
86740
86989
|
if (!fs72.existsSync(planPath2)) {
|
|
86741
86990
|
return {
|
|
86742
86991
|
success: false,
|
|
@@ -86760,7 +87009,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86760
87009
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
86761
87010
|
}
|
|
86762
87011
|
const directory = normalizedDir || fallbackDir;
|
|
86763
|
-
const planPath =
|
|
87012
|
+
const planPath = path97.resolve(directory, ".swarm", "plan.json");
|
|
86764
87013
|
if (!fs72.existsSync(planPath)) {
|
|
86765
87014
|
return {
|
|
86766
87015
|
success: false,
|
|
@@ -86800,8 +87049,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
86800
87049
|
const normalizeErrors = [];
|
|
86801
87050
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
86802
87051
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
86803
|
-
if (
|
|
86804
|
-
const relativePath =
|
|
87052
|
+
if (path97.isAbsolute(file3)) {
|
|
87053
|
+
const relativePath = path97.relative(dir, file3).replace(/\\/g, "/");
|
|
86805
87054
|
if (relativePath.startsWith("..")) {
|
|
86806
87055
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
86807
87056
|
return file3;
|
|
@@ -86862,7 +87111,7 @@ var declare_scope = createSwarmTool({
|
|
|
86862
87111
|
init_zod();
|
|
86863
87112
|
import * as child_process7 from "node:child_process";
|
|
86864
87113
|
import * as fs73 from "node:fs";
|
|
86865
|
-
import * as
|
|
87114
|
+
import * as path98 from "node:path";
|
|
86866
87115
|
init_create_tool();
|
|
86867
87116
|
var MAX_DIFF_LINES = 500;
|
|
86868
87117
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -86891,20 +87140,20 @@ function validateBase(base) {
|
|
|
86891
87140
|
function validatePaths(paths) {
|
|
86892
87141
|
if (!paths)
|
|
86893
87142
|
return null;
|
|
86894
|
-
for (const
|
|
86895
|
-
if (!
|
|
87143
|
+
for (const path99 of paths) {
|
|
87144
|
+
if (!path99 || path99.length === 0) {
|
|
86896
87145
|
return "empty path not allowed";
|
|
86897
87146
|
}
|
|
86898
|
-
if (
|
|
87147
|
+
if (path99.length > MAX_PATH_LENGTH) {
|
|
86899
87148
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
86900
87149
|
}
|
|
86901
|
-
if (SHELL_METACHARACTERS2.test(
|
|
87150
|
+
if (SHELL_METACHARACTERS2.test(path99)) {
|
|
86902
87151
|
return "path contains shell metacharacters";
|
|
86903
87152
|
}
|
|
86904
|
-
if (
|
|
87153
|
+
if (path99.startsWith("-")) {
|
|
86905
87154
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
86906
87155
|
}
|
|
86907
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
87156
|
+
if (CONTROL_CHAR_PATTERN2.test(path99)) {
|
|
86908
87157
|
return "path contains control characters";
|
|
86909
87158
|
}
|
|
86910
87159
|
}
|
|
@@ -87012,8 +87261,8 @@ var diff = createSwarmTool({
|
|
|
87012
87261
|
if (parts2.length >= 3) {
|
|
87013
87262
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
87014
87263
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
87015
|
-
const
|
|
87016
|
-
files.push({ path:
|
|
87264
|
+
const path99 = parts2[2];
|
|
87265
|
+
files.push({ path: path99, additions, deletions });
|
|
87017
87266
|
}
|
|
87018
87267
|
}
|
|
87019
87268
|
const contractChanges = [];
|
|
@@ -87053,7 +87302,7 @@ var diff = createSwarmTool({
|
|
|
87053
87302
|
} else if (base === "unstaged") {
|
|
87054
87303
|
const oldRef = `:${file3.path}`;
|
|
87055
87304
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
87056
|
-
newContent = fs73.readFileSync(
|
|
87305
|
+
newContent = fs73.readFileSync(path98.join(directory, file3.path), "utf-8");
|
|
87057
87306
|
} else {
|
|
87058
87307
|
const oldRef = `${base}:${file3.path}`;
|
|
87059
87308
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -87128,7 +87377,7 @@ var diff = createSwarmTool({
|
|
|
87128
87377
|
init_zod();
|
|
87129
87378
|
import * as child_process8 from "node:child_process";
|
|
87130
87379
|
import * as fs74 from "node:fs";
|
|
87131
|
-
import * as
|
|
87380
|
+
import * as path99 from "node:path";
|
|
87132
87381
|
init_create_tool();
|
|
87133
87382
|
var diff_summary = createSwarmTool({
|
|
87134
87383
|
description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
|
|
@@ -87176,7 +87425,7 @@ var diff_summary = createSwarmTool({
|
|
|
87176
87425
|
}
|
|
87177
87426
|
try {
|
|
87178
87427
|
let oldContent;
|
|
87179
|
-
const newContent = fs74.readFileSync(
|
|
87428
|
+
const newContent = fs74.readFileSync(path99.join(workingDir, filePath), "utf-8");
|
|
87180
87429
|
if (fileExistsInHead) {
|
|
87181
87430
|
oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
87182
87431
|
encoding: "utf-8",
|
|
@@ -87405,7 +87654,7 @@ init_zod();
|
|
|
87405
87654
|
init_create_tool();
|
|
87406
87655
|
init_path_security();
|
|
87407
87656
|
import * as fs75 from "node:fs";
|
|
87408
|
-
import * as
|
|
87657
|
+
import * as path100 from "node:path";
|
|
87409
87658
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
87410
87659
|
var MAX_EVIDENCE_FILES = 1000;
|
|
87411
87660
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -87432,9 +87681,9 @@ function validateRequiredTypes(input) {
|
|
|
87432
87681
|
return null;
|
|
87433
87682
|
}
|
|
87434
87683
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
87435
|
-
const normalizedCwd =
|
|
87436
|
-
const swarmPath =
|
|
87437
|
-
const normalizedPath =
|
|
87684
|
+
const normalizedCwd = path100.resolve(cwd);
|
|
87685
|
+
const swarmPath = path100.join(normalizedCwd, ".swarm");
|
|
87686
|
+
const normalizedPath = path100.resolve(filePath);
|
|
87438
87687
|
return normalizedPath.startsWith(swarmPath);
|
|
87439
87688
|
}
|
|
87440
87689
|
function parseCompletedTasks(planContent) {
|
|
@@ -87464,10 +87713,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
87464
87713
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
87465
87714
|
continue;
|
|
87466
87715
|
}
|
|
87467
|
-
const filePath =
|
|
87716
|
+
const filePath = path100.join(evidenceDir, filename);
|
|
87468
87717
|
try {
|
|
87469
|
-
const resolvedPath =
|
|
87470
|
-
const evidenceDirResolved =
|
|
87718
|
+
const resolvedPath = path100.resolve(filePath);
|
|
87719
|
+
const evidenceDirResolved = path100.resolve(evidenceDir);
|
|
87471
87720
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
87472
87721
|
continue;
|
|
87473
87722
|
}
|
|
@@ -87585,7 +87834,7 @@ var evidence_check = createSwarmTool({
|
|
|
87585
87834
|
return JSON.stringify(errorResult, null, 2);
|
|
87586
87835
|
}
|
|
87587
87836
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
87588
|
-
const planPath =
|
|
87837
|
+
const planPath = path100.join(cwd, PLAN_FILE);
|
|
87589
87838
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
87590
87839
|
const errorResult = {
|
|
87591
87840
|
error: "plan file path validation failed",
|
|
@@ -87617,7 +87866,7 @@ var evidence_check = createSwarmTool({
|
|
|
87617
87866
|
};
|
|
87618
87867
|
return JSON.stringify(result2, null, 2);
|
|
87619
87868
|
}
|
|
87620
|
-
const evidenceDir =
|
|
87869
|
+
const evidenceDir = path100.join(cwd, EVIDENCE_DIR3);
|
|
87621
87870
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
87622
87871
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
87623
87872
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -87635,7 +87884,7 @@ var evidence_check = createSwarmTool({
|
|
|
87635
87884
|
init_zod();
|
|
87636
87885
|
init_create_tool();
|
|
87637
87886
|
import * as fs76 from "node:fs";
|
|
87638
|
-
import * as
|
|
87887
|
+
import * as path101 from "node:path";
|
|
87639
87888
|
var EXT_MAP = {
|
|
87640
87889
|
python: ".py",
|
|
87641
87890
|
py: ".py",
|
|
@@ -87716,12 +87965,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
87716
87965
|
if (prefix) {
|
|
87717
87966
|
filename = `${prefix}_${filename}`;
|
|
87718
87967
|
}
|
|
87719
|
-
let filepath =
|
|
87720
|
-
const base =
|
|
87721
|
-
const ext =
|
|
87968
|
+
let filepath = path101.join(targetDir, filename);
|
|
87969
|
+
const base = path101.basename(filepath, path101.extname(filepath));
|
|
87970
|
+
const ext = path101.extname(filepath);
|
|
87722
87971
|
let counter = 1;
|
|
87723
87972
|
while (fs76.existsSync(filepath)) {
|
|
87724
|
-
filepath =
|
|
87973
|
+
filepath = path101.join(targetDir, `${base}_${counter}${ext}`);
|
|
87725
87974
|
counter++;
|
|
87726
87975
|
}
|
|
87727
87976
|
try {
|
|
@@ -87979,7 +88228,7 @@ init_zod();
|
|
|
87979
88228
|
init_create_tool();
|
|
87980
88229
|
init_path_security();
|
|
87981
88230
|
import * as fs77 from "node:fs";
|
|
87982
|
-
import * as
|
|
88231
|
+
import * as path102 from "node:path";
|
|
87983
88232
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
87984
88233
|
var MAX_SYMBOL_LENGTH = 256;
|
|
87985
88234
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -88027,7 +88276,7 @@ function validateSymbolInput(symbol3) {
|
|
|
88027
88276
|
return null;
|
|
88028
88277
|
}
|
|
88029
88278
|
function isBinaryFile2(filePath, buffer) {
|
|
88030
|
-
const ext =
|
|
88279
|
+
const ext = path102.extname(filePath).toLowerCase();
|
|
88031
88280
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
88032
88281
|
return false;
|
|
88033
88282
|
}
|
|
@@ -88051,15 +88300,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88051
88300
|
const imports = [];
|
|
88052
88301
|
let _resolvedTarget;
|
|
88053
88302
|
try {
|
|
88054
|
-
_resolvedTarget =
|
|
88303
|
+
_resolvedTarget = path102.resolve(targetFile);
|
|
88055
88304
|
} catch {
|
|
88056
88305
|
_resolvedTarget = targetFile;
|
|
88057
88306
|
}
|
|
88058
|
-
const targetBasename =
|
|
88307
|
+
const targetBasename = path102.basename(targetFile, path102.extname(targetFile));
|
|
88059
88308
|
const targetWithExt = targetFile;
|
|
88060
88309
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
88061
|
-
const normalizedTargetWithExt =
|
|
88062
|
-
const normalizedTargetWithoutExt =
|
|
88310
|
+
const normalizedTargetWithExt = path102.normalize(targetWithExt).replace(/\\/g, "/");
|
|
88311
|
+
const normalizedTargetWithoutExt = path102.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
88063
88312
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
88064
88313
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
88065
88314
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -88082,9 +88331,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88082
88331
|
}
|
|
88083
88332
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
88084
88333
|
let isMatch = false;
|
|
88085
|
-
const _targetDir =
|
|
88086
|
-
const targetExt =
|
|
88087
|
-
const targetBasenameNoExt =
|
|
88334
|
+
const _targetDir = path102.dirname(targetFile);
|
|
88335
|
+
const targetExt = path102.extname(targetFile);
|
|
88336
|
+
const targetBasenameNoExt = path102.basename(targetFile, targetExt);
|
|
88088
88337
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
88089
88338
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
88090
88339
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -88152,10 +88401,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88152
88401
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
88153
88402
|
for (const entry of entries) {
|
|
88154
88403
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
88155
|
-
stats.skippedDirs.push(
|
|
88404
|
+
stats.skippedDirs.push(path102.join(dir, entry));
|
|
88156
88405
|
continue;
|
|
88157
88406
|
}
|
|
88158
|
-
const fullPath =
|
|
88407
|
+
const fullPath = path102.join(dir, entry);
|
|
88159
88408
|
let stat8;
|
|
88160
88409
|
try {
|
|
88161
88410
|
stat8 = fs77.statSync(fullPath);
|
|
@@ -88169,7 +88418,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88169
88418
|
if (stat8.isDirectory()) {
|
|
88170
88419
|
findSourceFiles2(fullPath, files, stats);
|
|
88171
88420
|
} else if (stat8.isFile()) {
|
|
88172
|
-
const ext =
|
|
88421
|
+
const ext = path102.extname(fullPath).toLowerCase();
|
|
88173
88422
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
88174
88423
|
files.push(fullPath);
|
|
88175
88424
|
}
|
|
@@ -88226,7 +88475,7 @@ var imports = createSwarmTool({
|
|
|
88226
88475
|
return JSON.stringify(errorResult, null, 2);
|
|
88227
88476
|
}
|
|
88228
88477
|
try {
|
|
88229
|
-
const targetFile =
|
|
88478
|
+
const targetFile = path102.resolve(file3);
|
|
88230
88479
|
if (!fs77.existsSync(targetFile)) {
|
|
88231
88480
|
const errorResult = {
|
|
88232
88481
|
error: `target file not found: ${file3}`,
|
|
@@ -88248,7 +88497,7 @@ var imports = createSwarmTool({
|
|
|
88248
88497
|
};
|
|
88249
88498
|
return JSON.stringify(errorResult, null, 2);
|
|
88250
88499
|
}
|
|
88251
|
-
const baseDir =
|
|
88500
|
+
const baseDir = path102.dirname(targetFile);
|
|
88252
88501
|
const scanStats = {
|
|
88253
88502
|
skippedDirs: [],
|
|
88254
88503
|
skippedFiles: 0,
|
|
@@ -88539,7 +88788,7 @@ init_zod();
|
|
|
88539
88788
|
init_config();
|
|
88540
88789
|
init_knowledge_store();
|
|
88541
88790
|
init_create_tool();
|
|
88542
|
-
import { existsSync as
|
|
88791
|
+
import { existsSync as existsSync57 } from "node:fs";
|
|
88543
88792
|
var DEFAULT_LIMIT = 10;
|
|
88544
88793
|
var MAX_LESSON_LENGTH = 200;
|
|
88545
88794
|
var VALID_CATEGORIES3 = [
|
|
@@ -88609,14 +88858,14 @@ function validateLimit(limit) {
|
|
|
88609
88858
|
}
|
|
88610
88859
|
async function readSwarmKnowledge(directory) {
|
|
88611
88860
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
88612
|
-
if (!
|
|
88861
|
+
if (!existsSync57(swarmPath)) {
|
|
88613
88862
|
return [];
|
|
88614
88863
|
}
|
|
88615
88864
|
return readKnowledge(swarmPath);
|
|
88616
88865
|
}
|
|
88617
88866
|
async function readHiveKnowledge() {
|
|
88618
88867
|
const hivePath = resolveHiveKnowledgePath();
|
|
88619
|
-
if (!
|
|
88868
|
+
if (!existsSync57(hivePath)) {
|
|
88620
88869
|
return [];
|
|
88621
88870
|
}
|
|
88622
88871
|
return readKnowledge(hivePath);
|
|
@@ -88851,22 +89100,22 @@ init_schema();
|
|
|
88851
89100
|
init_qa_gate_profile();
|
|
88852
89101
|
init_manager2();
|
|
88853
89102
|
import * as fs82 from "node:fs";
|
|
88854
|
-
import * as
|
|
89103
|
+
import * as path107 from "node:path";
|
|
88855
89104
|
|
|
88856
89105
|
// src/full-auto/phase-approval.ts
|
|
88857
89106
|
init_utils2();
|
|
88858
89107
|
init_logger();
|
|
88859
89108
|
init_state2();
|
|
88860
89109
|
import * as fs78 from "node:fs";
|
|
88861
|
-
import * as
|
|
89110
|
+
import * as path103 from "node:path";
|
|
88862
89111
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
88863
89112
|
function readEvidenceDir(directory, phase) {
|
|
88864
89113
|
try {
|
|
88865
|
-
const dirPath = validateSwarmPath(directory,
|
|
89114
|
+
const dirPath = validateSwarmPath(directory, path103.posix.join("evidence", String(phase)));
|
|
88866
89115
|
if (!fs78.existsSync(dirPath))
|
|
88867
89116
|
return [];
|
|
88868
89117
|
const entries = fs78.readdirSync(dirPath);
|
|
88869
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
89118
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path103.join(dirPath, e));
|
|
88870
89119
|
} catch {
|
|
88871
89120
|
return [];
|
|
88872
89121
|
}
|
|
@@ -89005,16 +89254,16 @@ init_plan_schema();
|
|
|
89005
89254
|
init_ledger();
|
|
89006
89255
|
init_manager();
|
|
89007
89256
|
import * as fs79 from "node:fs";
|
|
89008
|
-
import * as
|
|
89257
|
+
import * as path104 from "node:path";
|
|
89009
89258
|
async function writeCheckpoint(directory) {
|
|
89010
89259
|
try {
|
|
89011
89260
|
const plan = await loadPlan(directory);
|
|
89012
89261
|
if (!plan)
|
|
89013
89262
|
return;
|
|
89014
|
-
const swarmDir =
|
|
89263
|
+
const swarmDir = path104.join(directory, ".swarm");
|
|
89015
89264
|
fs79.mkdirSync(swarmDir, { recursive: true });
|
|
89016
|
-
const jsonPath =
|
|
89017
|
-
const mdPath =
|
|
89265
|
+
const jsonPath = path104.join(swarmDir, "SWARM_PLAN.json");
|
|
89266
|
+
const mdPath = path104.join(swarmDir, "SWARM_PLAN.md");
|
|
89018
89267
|
fs79.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
89019
89268
|
const md = derivePlanMarkdown(plan);
|
|
89020
89269
|
fs79.writeFileSync(mdPath, md, "utf8");
|
|
@@ -89033,15 +89282,15 @@ init_telemetry();
|
|
|
89033
89282
|
// src/turbo/lean/phase-ready.ts
|
|
89034
89283
|
init_file_locks();
|
|
89035
89284
|
import * as fs81 from "node:fs";
|
|
89036
|
-
import * as
|
|
89285
|
+
import * as path106 from "node:path";
|
|
89037
89286
|
|
|
89038
89287
|
// src/turbo/lean/evidence.ts
|
|
89039
89288
|
init_bun_compat();
|
|
89040
89289
|
import { rmSync as rmSync5 } from "node:fs";
|
|
89041
89290
|
import * as fs80 from "node:fs/promises";
|
|
89042
|
-
import * as
|
|
89291
|
+
import * as path105 from "node:path";
|
|
89043
89292
|
function leanTurboEvidenceDir(directory, phase) {
|
|
89044
|
-
return
|
|
89293
|
+
return path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89045
89294
|
}
|
|
89046
89295
|
function validateLaneId(laneId) {
|
|
89047
89296
|
if (laneId.length === 0) {
|
|
@@ -89063,16 +89312,16 @@ function validateLaneId(laneId) {
|
|
|
89063
89312
|
function laneEvidencePath(directory, phase, laneId) {
|
|
89064
89313
|
validateLaneId(laneId);
|
|
89065
89314
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
89066
|
-
const resolvedPath =
|
|
89067
|
-
const resolvedDir =
|
|
89068
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
89315
|
+
const resolvedPath = path105.resolve(path105.join(expectedDir, `${laneId}.json`));
|
|
89316
|
+
const resolvedDir = path105.resolve(expectedDir);
|
|
89317
|
+
if (!resolvedPath.startsWith(resolvedDir + path105.sep) && resolvedPath !== resolvedDir) {
|
|
89069
89318
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
89070
89319
|
}
|
|
89071
89320
|
return resolvedPath;
|
|
89072
89321
|
}
|
|
89073
89322
|
async function atomicWriteJson(filePath, data) {
|
|
89074
89323
|
const content = JSON.stringify(data, null, 2);
|
|
89075
|
-
const dir =
|
|
89324
|
+
const dir = path105.dirname(filePath);
|
|
89076
89325
|
await fs80.mkdir(dir, { recursive: true });
|
|
89077
89326
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
89078
89327
|
try {
|
|
@@ -89086,7 +89335,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
89086
89335
|
}
|
|
89087
89336
|
}
|
|
89088
89337
|
function phaseEvidencePath(directory, phase) {
|
|
89089
|
-
return
|
|
89338
|
+
return path105.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
89090
89339
|
}
|
|
89091
89340
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
89092
89341
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -89130,7 +89379,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
89130
89379
|
if (entry === "lean-turbo-phase.json") {
|
|
89131
89380
|
continue;
|
|
89132
89381
|
}
|
|
89133
|
-
const filePath =
|
|
89382
|
+
const filePath = path105.join(evidenceDir, entry);
|
|
89134
89383
|
let content;
|
|
89135
89384
|
try {
|
|
89136
89385
|
content = await fs80.readFile(filePath, "utf-8");
|
|
@@ -89154,7 +89403,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
89154
89403
|
};
|
|
89155
89404
|
function defaultReadPlanJson(dir) {
|
|
89156
89405
|
try {
|
|
89157
|
-
const planPath =
|
|
89406
|
+
const planPath = path106.join(dir, ".swarm", "plan.json");
|
|
89158
89407
|
if (!fs81.existsSync(planPath))
|
|
89159
89408
|
return null;
|
|
89160
89409
|
const raw = fs81.readFileSync(planPath, "utf-8");
|
|
@@ -89169,7 +89418,7 @@ function defaultReadPlanJson(dir) {
|
|
|
89169
89418
|
}
|
|
89170
89419
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
89171
89420
|
try {
|
|
89172
|
-
const evidencePath =
|
|
89421
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
89173
89422
|
if (!fs81.existsSync(evidencePath)) {
|
|
89174
89423
|
return null;
|
|
89175
89424
|
}
|
|
@@ -89189,7 +89438,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
89189
89438
|
}
|
|
89190
89439
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
89191
89440
|
try {
|
|
89192
|
-
const evidencePath =
|
|
89441
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
89193
89442
|
if (!fs81.existsSync(evidencePath)) {
|
|
89194
89443
|
return null;
|
|
89195
89444
|
}
|
|
@@ -89208,7 +89457,7 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
89208
89457
|
}
|
|
89209
89458
|
}
|
|
89210
89459
|
function listLaneEvidenceSync(directory, phase) {
|
|
89211
|
-
const evidenceDir =
|
|
89460
|
+
const evidenceDir = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89212
89461
|
let entries;
|
|
89213
89462
|
try {
|
|
89214
89463
|
entries = fs81.readdirSync(evidenceDir);
|
|
@@ -89278,7 +89527,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89278
89527
|
...DEFAULT_CONFIG2,
|
|
89279
89528
|
...actualConfig
|
|
89280
89529
|
};
|
|
89281
|
-
const statePath =
|
|
89530
|
+
const statePath = path106.join(directory, ".swarm", "turbo-state.json");
|
|
89282
89531
|
if (!fs81.existsSync(statePath)) {
|
|
89283
89532
|
return {
|
|
89284
89533
|
ok: false,
|
|
@@ -89466,7 +89715,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89466
89715
|
}
|
|
89467
89716
|
}
|
|
89468
89717
|
if (mergedConfig.integrated_diff_required) {
|
|
89469
|
-
const evidencePath =
|
|
89718
|
+
const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
89470
89719
|
let hasDiff = false;
|
|
89471
89720
|
try {
|
|
89472
89721
|
const content = fs81.readFileSync(evidencePath, "utf-8");
|
|
@@ -89739,7 +89988,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89739
89988
|
let driftCheckEnabled = true;
|
|
89740
89989
|
let driftHasSpecMd = false;
|
|
89741
89990
|
try {
|
|
89742
|
-
const specMdPath =
|
|
89991
|
+
const specMdPath = path107.join(dir, ".swarm", "spec.md");
|
|
89743
89992
|
driftHasSpecMd = fs82.existsSync(specMdPath);
|
|
89744
89993
|
const gatePlan = await loadPlan(dir);
|
|
89745
89994
|
if (gatePlan) {
|
|
@@ -89761,7 +90010,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89761
90010
|
} else {
|
|
89762
90011
|
let phaseType;
|
|
89763
90012
|
try {
|
|
89764
|
-
const planPath =
|
|
90013
|
+
const planPath = path107.join(dir, ".swarm", "plan.json");
|
|
89765
90014
|
if (fs82.existsSync(planPath)) {
|
|
89766
90015
|
const planRaw = fs82.readFileSync(planPath, "utf-8");
|
|
89767
90016
|
const plan = JSON.parse(planRaw);
|
|
@@ -89774,7 +90023,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89774
90023
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
89775
90024
|
} else {
|
|
89776
90025
|
try {
|
|
89777
|
-
const driftEvidencePath =
|
|
90026
|
+
const driftEvidencePath = path107.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
89778
90027
|
let driftVerdictFound = false;
|
|
89779
90028
|
let driftVerdictApproved = false;
|
|
89780
90029
|
try {
|
|
@@ -89812,7 +90061,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89812
90061
|
let incompleteTaskCount = 0;
|
|
89813
90062
|
let planParseable = false;
|
|
89814
90063
|
try {
|
|
89815
|
-
const planPath =
|
|
90064
|
+
const planPath = path107.join(dir, ".swarm", "plan.json");
|
|
89816
90065
|
if (fs82.existsSync(planPath)) {
|
|
89817
90066
|
const planRaw = fs82.readFileSync(planPath, "utf-8");
|
|
89818
90067
|
const plan = JSON.parse(planRaw);
|
|
@@ -89879,7 +90128,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89879
90128
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
89880
90129
|
const effective = getEffectiveGates(profile, overrides);
|
|
89881
90130
|
if (effective.hallucination_guard === true) {
|
|
89882
|
-
const hgPath =
|
|
90131
|
+
const hgPath = path107.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
89883
90132
|
let hgVerdictFound = false;
|
|
89884
90133
|
let hgVerdictApproved = false;
|
|
89885
90134
|
try {
|
|
@@ -89951,7 +90200,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
89951
90200
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
89952
90201
|
const effective = getEffectiveGates(profile, overrides);
|
|
89953
90202
|
if (effective.mutation_test === true) {
|
|
89954
|
-
const mgPath =
|
|
90203
|
+
const mgPath = path107.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
89955
90204
|
let mgVerdictFound = false;
|
|
89956
90205
|
let mgVerdict;
|
|
89957
90206
|
try {
|
|
@@ -90025,7 +90274,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90025
90274
|
const effective = getEffectiveGates(profile, overrides);
|
|
90026
90275
|
if (effective.council_mode === true) {
|
|
90027
90276
|
councilModeEnabled = true;
|
|
90028
|
-
const pcPath =
|
|
90277
|
+
const pcPath = path107.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
90029
90278
|
let pcVerdictFound = false;
|
|
90030
90279
|
let _pcVerdict;
|
|
90031
90280
|
let pcQuorumSize;
|
|
@@ -90233,7 +90482,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90233
90482
|
const effective = getEffectiveGates(profile, overrides);
|
|
90234
90483
|
if (effective.final_council === true) {
|
|
90235
90484
|
finalCouncilEnabled = true;
|
|
90236
|
-
const fcPath =
|
|
90485
|
+
const fcPath = path107.join(dir, ".swarm", "evidence", "final-council.json");
|
|
90237
90486
|
let fcVerdictFound = false;
|
|
90238
90487
|
let _fcVerdict;
|
|
90239
90488
|
try {
|
|
@@ -90421,7 +90670,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90421
90670
|
}
|
|
90422
90671
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
90423
90672
|
try {
|
|
90424
|
-
const projectName =
|
|
90673
|
+
const projectName = path107.basename(dir);
|
|
90425
90674
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
90426
90675
|
if (curationResult) {
|
|
90427
90676
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -90672,7 +90921,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90672
90921
|
const phaseObj = rebuilt.phases.find((p) => p.id === phase);
|
|
90673
90922
|
if (phaseObj) {
|
|
90674
90923
|
phaseObj.status = "complete";
|
|
90675
|
-
await
|
|
90924
|
+
await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
|
|
90676
90925
|
try {
|
|
90677
90926
|
await takeSnapshotEvent(dir, rebuilt).catch(() => {});
|
|
90678
90927
|
} catch {}
|
|
@@ -90714,7 +90963,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90714
90963
|
const phaseObj = rebuilt.phases.find((p) => p.id === phase);
|
|
90715
90964
|
if (phaseObj) {
|
|
90716
90965
|
phaseObj.status = "complete";
|
|
90717
|
-
await
|
|
90966
|
+
await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
|
|
90718
90967
|
try {
|
|
90719
90968
|
await takeSnapshotEvent(dir, rebuilt).catch(() => {});
|
|
90720
90969
|
} catch {}
|
|
@@ -90791,7 +91040,7 @@ init_utils();
|
|
|
90791
91040
|
init_bun_compat();
|
|
90792
91041
|
init_create_tool();
|
|
90793
91042
|
import * as fs83 from "node:fs";
|
|
90794
|
-
import * as
|
|
91043
|
+
import * as path108 from "node:path";
|
|
90795
91044
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
90796
91045
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
90797
91046
|
function isValidEcosystem(value) {
|
|
@@ -90819,16 +91068,16 @@ function validateArgs3(args2) {
|
|
|
90819
91068
|
function detectEcosystems(directory) {
|
|
90820
91069
|
const ecosystems = [];
|
|
90821
91070
|
const cwd = directory;
|
|
90822
|
-
if (fs83.existsSync(
|
|
91071
|
+
if (fs83.existsSync(path108.join(cwd, "package.json"))) {
|
|
90823
91072
|
ecosystems.push("npm");
|
|
90824
91073
|
}
|
|
90825
|
-
if (fs83.existsSync(
|
|
91074
|
+
if (fs83.existsSync(path108.join(cwd, "pyproject.toml")) || fs83.existsSync(path108.join(cwd, "requirements.txt"))) {
|
|
90826
91075
|
ecosystems.push("pip");
|
|
90827
91076
|
}
|
|
90828
|
-
if (fs83.existsSync(
|
|
91077
|
+
if (fs83.existsSync(path108.join(cwd, "Cargo.toml"))) {
|
|
90829
91078
|
ecosystems.push("cargo");
|
|
90830
91079
|
}
|
|
90831
|
-
if (fs83.existsSync(
|
|
91080
|
+
if (fs83.existsSync(path108.join(cwd, "go.mod"))) {
|
|
90832
91081
|
ecosystems.push("go");
|
|
90833
91082
|
}
|
|
90834
91083
|
try {
|
|
@@ -90837,13 +91086,13 @@ function detectEcosystems(directory) {
|
|
|
90837
91086
|
ecosystems.push("dotnet");
|
|
90838
91087
|
}
|
|
90839
91088
|
} catch {}
|
|
90840
|
-
if (fs83.existsSync(
|
|
91089
|
+
if (fs83.existsSync(path108.join(cwd, "Gemfile")) || fs83.existsSync(path108.join(cwd, "Gemfile.lock"))) {
|
|
90841
91090
|
ecosystems.push("ruby");
|
|
90842
91091
|
}
|
|
90843
|
-
if (fs83.existsSync(
|
|
91092
|
+
if (fs83.existsSync(path108.join(cwd, "pubspec.yaml"))) {
|
|
90844
91093
|
ecosystems.push("dart");
|
|
90845
91094
|
}
|
|
90846
|
-
if (fs83.existsSync(
|
|
91095
|
+
if (fs83.existsSync(path108.join(cwd, "composer.lock"))) {
|
|
90847
91096
|
ecosystems.push("composer");
|
|
90848
91097
|
}
|
|
90849
91098
|
return ecosystems;
|
|
@@ -91979,7 +92228,7 @@ var pkg_audit = createSwarmTool({
|
|
|
91979
92228
|
init_zod();
|
|
91980
92229
|
init_manager2();
|
|
91981
92230
|
import * as fs84 from "node:fs";
|
|
91982
|
-
import * as
|
|
92231
|
+
import * as path109 from "node:path";
|
|
91983
92232
|
init_utils();
|
|
91984
92233
|
init_create_tool();
|
|
91985
92234
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -92102,7 +92351,7 @@ function isScaffoldFile(filePath) {
|
|
|
92102
92351
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
92103
92352
|
return true;
|
|
92104
92353
|
}
|
|
92105
|
-
const filename =
|
|
92354
|
+
const filename = path109.basename(filePath);
|
|
92106
92355
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
92107
92356
|
return true;
|
|
92108
92357
|
}
|
|
@@ -92119,7 +92368,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92119
92368
|
if (regex.test(normalizedPath)) {
|
|
92120
92369
|
return true;
|
|
92121
92370
|
}
|
|
92122
|
-
const filename =
|
|
92371
|
+
const filename = path109.basename(filePath);
|
|
92123
92372
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
92124
92373
|
if (filenameRegex.test(filename)) {
|
|
92125
92374
|
return true;
|
|
@@ -92128,7 +92377,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92128
92377
|
return false;
|
|
92129
92378
|
}
|
|
92130
92379
|
function isParserSupported(filePath) {
|
|
92131
|
-
const ext =
|
|
92380
|
+
const ext = path109.extname(filePath).toLowerCase();
|
|
92132
92381
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
92133
92382
|
}
|
|
92134
92383
|
function isPlanFile(filePath) {
|
|
@@ -92375,9 +92624,9 @@ async function placeholderScan(input, directory) {
|
|
|
92375
92624
|
let filesScanned = 0;
|
|
92376
92625
|
const filesWithFindings = new Set;
|
|
92377
92626
|
for (const filePath of changed_files) {
|
|
92378
|
-
const fullPath =
|
|
92379
|
-
const resolvedDirectory =
|
|
92380
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
92627
|
+
const fullPath = path109.isAbsolute(filePath) ? filePath : path109.resolve(directory, filePath);
|
|
92628
|
+
const resolvedDirectory = path109.resolve(directory);
|
|
92629
|
+
if (!fullPath.startsWith(resolvedDirectory + path109.sep) && fullPath !== resolvedDirectory) {
|
|
92381
92630
|
continue;
|
|
92382
92631
|
}
|
|
92383
92632
|
if (!fs84.existsSync(fullPath)) {
|
|
@@ -92386,7 +92635,7 @@ async function placeholderScan(input, directory) {
|
|
|
92386
92635
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
92387
92636
|
continue;
|
|
92388
92637
|
}
|
|
92389
|
-
const relativeFilePath =
|
|
92638
|
+
const relativeFilePath = path109.relative(directory, fullPath).replace(/\\/g, "/");
|
|
92390
92639
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
92391
92640
|
continue;
|
|
92392
92641
|
}
|
|
@@ -92458,7 +92707,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
92458
92707
|
});
|
|
92459
92708
|
// src/tools/pre-check-batch.ts
|
|
92460
92709
|
import * as fs88 from "node:fs";
|
|
92461
|
-
import * as
|
|
92710
|
+
import * as path113 from "node:path";
|
|
92462
92711
|
init_zod();
|
|
92463
92712
|
init_manager2();
|
|
92464
92713
|
init_utils();
|
|
@@ -92599,7 +92848,7 @@ init_zod();
|
|
|
92599
92848
|
init_manager2();
|
|
92600
92849
|
init_detector();
|
|
92601
92850
|
import * as fs87 from "node:fs";
|
|
92602
|
-
import * as
|
|
92851
|
+
import * as path112 from "node:path";
|
|
92603
92852
|
import { extname as extname19 } from "node:path";
|
|
92604
92853
|
|
|
92605
92854
|
// src/sast/rules/c.ts
|
|
@@ -93315,7 +93564,7 @@ function executeRulesSync(filePath, content, language) {
|
|
|
93315
93564
|
// src/sast/semgrep.ts
|
|
93316
93565
|
import * as child_process9 from "node:child_process";
|
|
93317
93566
|
import * as fs85 from "node:fs";
|
|
93318
|
-
import * as
|
|
93567
|
+
import * as path110 from "node:path";
|
|
93319
93568
|
var semgrepAvailableCache = null;
|
|
93320
93569
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
93321
93570
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
@@ -93502,7 +93751,7 @@ async function runSemgrep(options) {
|
|
|
93502
93751
|
}
|
|
93503
93752
|
function getRulesDirectory(projectRoot) {
|
|
93504
93753
|
if (projectRoot) {
|
|
93505
|
-
return
|
|
93754
|
+
return path110.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
93506
93755
|
}
|
|
93507
93756
|
return DEFAULT_RULES_DIR;
|
|
93508
93757
|
}
|
|
@@ -93523,24 +93772,24 @@ init_create_tool();
|
|
|
93523
93772
|
init_utils2();
|
|
93524
93773
|
import * as crypto9 from "node:crypto";
|
|
93525
93774
|
import * as fs86 from "node:fs";
|
|
93526
|
-
import * as
|
|
93775
|
+
import * as path111 from "node:path";
|
|
93527
93776
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
93528
93777
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
93529
93778
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
93530
93779
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
93531
93780
|
function normalizeFindingPath(directory, file3) {
|
|
93532
|
-
const resolved =
|
|
93533
|
-
const rel =
|
|
93781
|
+
const resolved = path111.isAbsolute(file3) ? file3 : path111.resolve(directory, file3);
|
|
93782
|
+
const rel = path111.relative(path111.resolve(directory), resolved);
|
|
93534
93783
|
return rel.replace(/\\/g, "/");
|
|
93535
93784
|
}
|
|
93536
93785
|
function baselineRelPath(phase) {
|
|
93537
|
-
return
|
|
93786
|
+
return path111.join("evidence", String(phase), "sast-baseline.json");
|
|
93538
93787
|
}
|
|
93539
93788
|
function tempRelPath(phase) {
|
|
93540
|
-
return
|
|
93789
|
+
return path111.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
93541
93790
|
}
|
|
93542
93791
|
function lockRelPath(phase) {
|
|
93543
|
-
return
|
|
93792
|
+
return path111.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
93544
93793
|
}
|
|
93545
93794
|
function getLine(lines, idx) {
|
|
93546
93795
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -93661,8 +93910,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
93661
93910
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
93662
93911
|
};
|
|
93663
93912
|
}
|
|
93664
|
-
fs86.mkdirSync(
|
|
93665
|
-
fs86.mkdirSync(
|
|
93913
|
+
fs86.mkdirSync(path111.dirname(baselinePath), { recursive: true });
|
|
93914
|
+
fs86.mkdirSync(path111.dirname(tempPath), { recursive: true });
|
|
93666
93915
|
const releaseLock = await acquireLock2(lockPath);
|
|
93667
93916
|
try {
|
|
93668
93917
|
let existing = null;
|
|
@@ -93935,9 +94184,9 @@ async function sastScan(input, directory, config3) {
|
|
|
93935
94184
|
_filesSkipped++;
|
|
93936
94185
|
continue;
|
|
93937
94186
|
}
|
|
93938
|
-
const resolvedPath =
|
|
93939
|
-
const resolvedDirectory =
|
|
93940
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
94187
|
+
const resolvedPath = path112.isAbsolute(filePath) ? filePath : path112.resolve(directory, filePath);
|
|
94188
|
+
const resolvedDirectory = path112.resolve(directory);
|
|
94189
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path112.sep) && resolvedPath !== resolvedDirectory) {
|
|
93941
94190
|
_filesSkipped++;
|
|
93942
94191
|
continue;
|
|
93943
94192
|
}
|
|
@@ -94252,18 +94501,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
94252
94501
|
let resolved;
|
|
94253
94502
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
94254
94503
|
if (isWinAbs) {
|
|
94255
|
-
resolved =
|
|
94256
|
-
} else if (
|
|
94257
|
-
resolved =
|
|
94504
|
+
resolved = path113.win32.resolve(inputPath);
|
|
94505
|
+
} else if (path113.isAbsolute(inputPath)) {
|
|
94506
|
+
resolved = path113.resolve(inputPath);
|
|
94258
94507
|
} else {
|
|
94259
|
-
resolved =
|
|
94508
|
+
resolved = path113.resolve(baseDir, inputPath);
|
|
94260
94509
|
}
|
|
94261
|
-
const workspaceResolved =
|
|
94510
|
+
const workspaceResolved = path113.resolve(workspaceDir);
|
|
94262
94511
|
let relative24;
|
|
94263
94512
|
if (isWinAbs) {
|
|
94264
|
-
relative24 =
|
|
94513
|
+
relative24 = path113.win32.relative(workspaceResolved, resolved);
|
|
94265
94514
|
} else {
|
|
94266
|
-
relative24 =
|
|
94515
|
+
relative24 = path113.relative(workspaceResolved, resolved);
|
|
94267
94516
|
}
|
|
94268
94517
|
if (relative24.startsWith("..")) {
|
|
94269
94518
|
return "path traversal detected";
|
|
@@ -94328,7 +94577,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
94328
94577
|
if (typeof file3 !== "string") {
|
|
94329
94578
|
continue;
|
|
94330
94579
|
}
|
|
94331
|
-
const resolvedPath =
|
|
94580
|
+
const resolvedPath = path113.resolve(file3);
|
|
94332
94581
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
94333
94582
|
if (validationError) {
|
|
94334
94583
|
continue;
|
|
@@ -94485,7 +94734,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
94485
94734
|
skippedFiles++;
|
|
94486
94735
|
continue;
|
|
94487
94736
|
}
|
|
94488
|
-
const resolvedPath =
|
|
94737
|
+
const resolvedPath = path113.resolve(file3);
|
|
94489
94738
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
94490
94739
|
if (validationError) {
|
|
94491
94740
|
skippedFiles++;
|
|
@@ -94503,7 +94752,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
94503
94752
|
};
|
|
94504
94753
|
}
|
|
94505
94754
|
for (const file3 of validatedFiles) {
|
|
94506
|
-
const ext =
|
|
94755
|
+
const ext = path113.extname(file3).toLowerCase();
|
|
94507
94756
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
94508
94757
|
skippedFiles++;
|
|
94509
94758
|
continue;
|
|
@@ -94722,7 +94971,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
94722
94971
|
const preexistingFindings = [];
|
|
94723
94972
|
for (const finding of findings) {
|
|
94724
94973
|
const filePath = finding.location.file;
|
|
94725
|
-
const normalised =
|
|
94974
|
+
const normalised = path113.relative(directory, filePath).replace(/\\/g, "/");
|
|
94726
94975
|
const changedLines = changedLineRanges.get(normalised);
|
|
94727
94976
|
if (changedLines?.has(finding.location.line)) {
|
|
94728
94977
|
newFindings.push(finding);
|
|
@@ -94773,7 +95022,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
94773
95022
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
94774
95023
|
continue;
|
|
94775
95024
|
}
|
|
94776
|
-
changedFiles.push(
|
|
95025
|
+
changedFiles.push(path113.resolve(directory, file3));
|
|
94777
95026
|
}
|
|
94778
95027
|
if (changedFiles.length === 0) {
|
|
94779
95028
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -94974,7 +95223,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
94974
95223
|
};
|
|
94975
95224
|
return JSON.stringify(errorResult, null, 2);
|
|
94976
95225
|
}
|
|
94977
|
-
const resolvedDirectory =
|
|
95226
|
+
const resolvedDirectory = path113.resolve(typedArgs.directory);
|
|
94978
95227
|
const workspaceAnchor = resolvedDirectory;
|
|
94979
95228
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
94980
95229
|
if (dirError) {
|
|
@@ -95015,7 +95264,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
95015
95264
|
});
|
|
95016
95265
|
// src/tools/repo-map.ts
|
|
95017
95266
|
init_zod();
|
|
95018
|
-
import * as
|
|
95267
|
+
import * as path114 from "node:path";
|
|
95019
95268
|
init_path_security();
|
|
95020
95269
|
init_create_tool();
|
|
95021
95270
|
var VALID_ACTIONS = [
|
|
@@ -95040,7 +95289,7 @@ function validateFile(p) {
|
|
|
95040
95289
|
return "file contains control characters";
|
|
95041
95290
|
if (containsPathTraversal(p))
|
|
95042
95291
|
return "file contains path traversal";
|
|
95043
|
-
if (
|
|
95292
|
+
if (path114.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
95044
95293
|
return "file must be a workspace-relative path, not absolute";
|
|
95045
95294
|
}
|
|
95046
95295
|
return null;
|
|
@@ -95063,8 +95312,8 @@ function ok(action, payload) {
|
|
|
95063
95312
|
}
|
|
95064
95313
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
95065
95314
|
const normalized = input.replace(/\\/g, "/");
|
|
95066
|
-
if (
|
|
95067
|
-
const rel =
|
|
95315
|
+
if (path114.isAbsolute(normalized)) {
|
|
95316
|
+
const rel = path114.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
95068
95317
|
return normalizeGraphPath2(rel);
|
|
95069
95318
|
}
|
|
95070
95319
|
return normalizeGraphPath2(normalized);
|
|
@@ -95209,7 +95458,7 @@ var repo_map = createSwarmTool({
|
|
|
95209
95458
|
init_zod();
|
|
95210
95459
|
init_create_tool();
|
|
95211
95460
|
import * as fs89 from "node:fs";
|
|
95212
|
-
import * as
|
|
95461
|
+
import * as path115 from "node:path";
|
|
95213
95462
|
var SPEC_FILE = ".swarm/spec.md";
|
|
95214
95463
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
95215
95464
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -95278,7 +95527,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95278
95527
|
return [];
|
|
95279
95528
|
}
|
|
95280
95529
|
for (const entry of entries) {
|
|
95281
|
-
const entryPath =
|
|
95530
|
+
const entryPath = path115.join(evidenceDir, entry);
|
|
95282
95531
|
try {
|
|
95283
95532
|
const stat8 = fs89.statSync(entryPath);
|
|
95284
95533
|
if (!stat8.isDirectory()) {
|
|
@@ -95294,11 +95543,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95294
95543
|
if (entryPhase !== String(phase)) {
|
|
95295
95544
|
continue;
|
|
95296
95545
|
}
|
|
95297
|
-
const evidenceFilePath =
|
|
95546
|
+
const evidenceFilePath = path115.join(entryPath, "evidence.json");
|
|
95298
95547
|
try {
|
|
95299
|
-
const resolvedPath =
|
|
95300
|
-
const evidenceDirResolved =
|
|
95301
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
95548
|
+
const resolvedPath = path115.resolve(evidenceFilePath);
|
|
95549
|
+
const evidenceDirResolved = path115.resolve(evidenceDir);
|
|
95550
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path115.sep)) {
|
|
95302
95551
|
continue;
|
|
95303
95552
|
}
|
|
95304
95553
|
const stat8 = fs89.lstatSync(evidenceFilePath);
|
|
@@ -95332,7 +95581,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95332
95581
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
95333
95582
|
for (const file3 of diffEntry.files_changed) {
|
|
95334
95583
|
if (typeof file3 === "string") {
|
|
95335
|
-
touchedFiles.add(
|
|
95584
|
+
touchedFiles.add(path115.resolve(cwd, file3));
|
|
95336
95585
|
}
|
|
95337
95586
|
}
|
|
95338
95587
|
}
|
|
@@ -95345,8 +95594,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95345
95594
|
}
|
|
95346
95595
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
95347
95596
|
try {
|
|
95348
|
-
const resolvedPath =
|
|
95349
|
-
const cwdResolved =
|
|
95597
|
+
const resolvedPath = path115.resolve(filePath);
|
|
95598
|
+
const cwdResolved = path115.resolve(cwd);
|
|
95350
95599
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
95351
95600
|
return false;
|
|
95352
95601
|
}
|
|
@@ -95480,7 +95729,7 @@ var req_coverage = createSwarmTool({
|
|
|
95480
95729
|
}, null, 2);
|
|
95481
95730
|
}
|
|
95482
95731
|
const cwd = inputDirectory || directory;
|
|
95483
|
-
const specPath =
|
|
95732
|
+
const specPath = path115.join(cwd, SPEC_FILE);
|
|
95484
95733
|
let specContent;
|
|
95485
95734
|
try {
|
|
95486
95735
|
specContent = fs89.readFileSync(specPath, "utf-8");
|
|
@@ -95507,7 +95756,7 @@ var req_coverage = createSwarmTool({
|
|
|
95507
95756
|
message: "No FR requirements found in spec.md"
|
|
95508
95757
|
}, null, 2);
|
|
95509
95758
|
}
|
|
95510
|
-
const evidenceDir =
|
|
95759
|
+
const evidenceDir = path115.join(cwd, EVIDENCE_DIR4);
|
|
95511
95760
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
95512
95761
|
const analyzedRequirements = [];
|
|
95513
95762
|
let coveredCount = 0;
|
|
@@ -95533,7 +95782,7 @@ var req_coverage = createSwarmTool({
|
|
|
95533
95782
|
requirements: analyzedRequirements
|
|
95534
95783
|
};
|
|
95535
95784
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
95536
|
-
const reportPath =
|
|
95785
|
+
const reportPath = path115.join(evidenceDir, reportFilename);
|
|
95537
95786
|
try {
|
|
95538
95787
|
if (!fs89.existsSync(evidenceDir)) {
|
|
95539
95788
|
fs89.mkdirSync(evidenceDir, { recursive: true });
|
|
@@ -95621,7 +95870,7 @@ init_qa_gate_profile();
|
|
|
95621
95870
|
init_file_locks();
|
|
95622
95871
|
import * as crypto10 from "node:crypto";
|
|
95623
95872
|
import * as fs90 from "node:fs";
|
|
95624
|
-
import * as
|
|
95873
|
+
import * as path116 from "node:path";
|
|
95625
95874
|
init_ledger();
|
|
95626
95875
|
init_manager();
|
|
95627
95876
|
init_state();
|
|
@@ -95699,8 +95948,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95699
95948
|
};
|
|
95700
95949
|
}
|
|
95701
95950
|
if (args2.working_directory && fallbackDir) {
|
|
95702
|
-
const resolvedTarget =
|
|
95703
|
-
const resolvedRoot =
|
|
95951
|
+
const resolvedTarget = path116.resolve(args2.working_directory);
|
|
95952
|
+
const resolvedRoot = path116.resolve(fallbackDir);
|
|
95704
95953
|
let fallbackExists = false;
|
|
95705
95954
|
try {
|
|
95706
95955
|
fs90.accessSync(resolvedRoot, fs90.constants.F_OK);
|
|
@@ -95709,7 +95958,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95709
95958
|
fallbackExists = false;
|
|
95710
95959
|
}
|
|
95711
95960
|
if (fallbackExists) {
|
|
95712
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
95961
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path116.sep);
|
|
95713
95962
|
if (isSubdirectory) {
|
|
95714
95963
|
return {
|
|
95715
95964
|
success: false,
|
|
@@ -95725,7 +95974,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95725
95974
|
let specMtime;
|
|
95726
95975
|
let specHash;
|
|
95727
95976
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
95728
|
-
const specPath =
|
|
95977
|
+
const specPath = path116.join(targetWorkspace, ".swarm", "spec.md");
|
|
95729
95978
|
try {
|
|
95730
95979
|
const stat8 = await fs90.promises.stat(specPath);
|
|
95731
95980
|
specMtime = stat8.mtime.toISOString();
|
|
@@ -95741,7 +95990,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95741
95990
|
}
|
|
95742
95991
|
}
|
|
95743
95992
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
95744
|
-
const contextPath =
|
|
95993
|
+
const contextPath = path116.join(targetWorkspace, ".swarm", "context.md");
|
|
95745
95994
|
let contextContent = "";
|
|
95746
95995
|
try {
|
|
95747
95996
|
contextContent = await fs90.promises.readFile(contextPath, "utf8");
|
|
@@ -95771,6 +96020,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95771
96020
|
}
|
|
95772
96021
|
const dir = targetWorkspace;
|
|
95773
96022
|
const existingStatusMap = new Map;
|
|
96023
|
+
const priorTaskIds = new Set;
|
|
95774
96024
|
let preservedExecutionProfile;
|
|
95775
96025
|
{
|
|
95776
96026
|
let existing = null;
|
|
@@ -95778,6 +96028,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95778
96028
|
existing = await loadPlanJsonOnly(dir);
|
|
95779
96029
|
} catch {}
|
|
95780
96030
|
if (existing) {
|
|
96031
|
+
for (const phase of existing.phases) {
|
|
96032
|
+
for (const task of phase.tasks)
|
|
96033
|
+
priorTaskIds.add(task.id);
|
|
96034
|
+
}
|
|
95781
96035
|
if (!args2.reset_statuses) {
|
|
95782
96036
|
for (const phase of existing.phases) {
|
|
95783
96037
|
for (const task of phase.tasks) {
|
|
@@ -95819,6 +96073,98 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95819
96073
|
}
|
|
95820
96074
|
resolvedProfile = parsed.data;
|
|
95821
96075
|
}
|
|
96076
|
+
const incomingTaskIds = new Set;
|
|
96077
|
+
for (const phase of args2.phases) {
|
|
96078
|
+
for (const task of phase.tasks)
|
|
96079
|
+
incomingTaskIds.add(task.id);
|
|
96080
|
+
}
|
|
96081
|
+
const missingTaskIds = [];
|
|
96082
|
+
for (const id of priorTaskIds) {
|
|
96083
|
+
if (!incomingTaskIds.has(id))
|
|
96084
|
+
missingTaskIds.push(id);
|
|
96085
|
+
}
|
|
96086
|
+
const rawRemovedIds = args2.removed_task_ids ?? [];
|
|
96087
|
+
if (rawRemovedIds.length > 0) {
|
|
96088
|
+
const seen = new Set;
|
|
96089
|
+
for (const id of rawRemovedIds) {
|
|
96090
|
+
if (seen.has(id)) {
|
|
96091
|
+
return {
|
|
96092
|
+
success: false,
|
|
96093
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains duplicate entries",
|
|
96094
|
+
errors: [`Duplicate id in removed_task_ids: "${id}"`],
|
|
96095
|
+
recovery_guidance: "Deduplicate removed_task_ids and retry save_plan."
|
|
96096
|
+
};
|
|
96097
|
+
}
|
|
96098
|
+
seen.add(id);
|
|
96099
|
+
}
|
|
96100
|
+
for (const id of rawRemovedIds) {
|
|
96101
|
+
if (incomingTaskIds.has(id)) {
|
|
96102
|
+
return {
|
|
96103
|
+
success: false,
|
|
96104
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains a task that also appears in args.phases",
|
|
96105
|
+
errors: [
|
|
96106
|
+
`Task "${id}" appears in both removed_task_ids and args.phases — these are contradictory`
|
|
96107
|
+
],
|
|
96108
|
+
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."
|
|
96109
|
+
};
|
|
96110
|
+
}
|
|
96111
|
+
}
|
|
96112
|
+
for (const id of rawRemovedIds) {
|
|
96113
|
+
if (!priorTaskIds.has(id)) {
|
|
96114
|
+
return {
|
|
96115
|
+
success: false,
|
|
96116
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains an id that was not in the prior plan",
|
|
96117
|
+
errors: [
|
|
96118
|
+
`Task "${id}" is in removed_task_ids but not present in the prior plan`
|
|
96119
|
+
],
|
|
96120
|
+
recovery_guidance: "Re-read the prior plan and update removed_task_ids to only list tasks that actually existed."
|
|
96121
|
+
};
|
|
96122
|
+
}
|
|
96123
|
+
}
|
|
96124
|
+
}
|
|
96125
|
+
let resolvedRemovedIds = [...rawRemovedIds];
|
|
96126
|
+
let resolvedRemovalReason = args2.removal_reason;
|
|
96127
|
+
if (args2.reset_statuses === true && missingTaskIds.length > 0) {
|
|
96128
|
+
if (args2.confirm_destructive_reset !== true) {
|
|
96129
|
+
return {
|
|
96130
|
+
success: false,
|
|
96131
|
+
message: "PLAN_DESTRUCTIVE_RESET_NOT_CONFIRMED: reset_statuses with missing tasks requires confirm_destructive_reset: true",
|
|
96132
|
+
errors: [
|
|
96133
|
+
`reset_statuses: true would drop ${missingTaskIds.length} task(s) from the prior plan: ${missingTaskIds.join(", ")}`
|
|
96134
|
+
],
|
|
96135
|
+
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."
|
|
96136
|
+
};
|
|
96137
|
+
}
|
|
96138
|
+
if (rawRemovedIds.length === 0) {
|
|
96139
|
+
resolvedRemovedIds = [...missingTaskIds];
|
|
96140
|
+
resolvedRemovalReason = "destructive reset acknowledged";
|
|
96141
|
+
}
|
|
96142
|
+
}
|
|
96143
|
+
if (resolvedRemovedIds.length > 0) {
|
|
96144
|
+
const reason = (resolvedRemovalReason ?? "").trim();
|
|
96145
|
+
if (reason.length === 0) {
|
|
96146
|
+
return {
|
|
96147
|
+
success: false,
|
|
96148
|
+
message: "PLAN_TASK_REMOVAL_INVALID: removal_reason is required when removed_task_ids is non-empty",
|
|
96149
|
+
errors: ["removal_reason must be a non-empty, non-whitespace string"],
|
|
96150
|
+
recovery_guidance: "Provide a removal_reason describing why these tasks are being dropped."
|
|
96151
|
+
};
|
|
96152
|
+
}
|
|
96153
|
+
}
|
|
96154
|
+
if (missingTaskIds.length > 0) {
|
|
96155
|
+
const ackSet = new Set(resolvedRemovedIds);
|
|
96156
|
+
const unacked = missingTaskIds.filter((id) => !ackSet.has(id));
|
|
96157
|
+
if (unacked.length > 0) {
|
|
96158
|
+
return {
|
|
96159
|
+
success: false,
|
|
96160
|
+
message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
|
|
96161
|
+
errors: [
|
|
96162
|
+
`The following prior tasks are missing from the new save and were not listed in removed_task_ids: ${unacked.join(", ")}`
|
|
96163
|
+
],
|
|
96164
|
+
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."
|
|
96165
|
+
};
|
|
96166
|
+
}
|
|
96167
|
+
}
|
|
95822
96168
|
const plan = {
|
|
95823
96169
|
schema_version: "1.0.0",
|
|
95824
96170
|
title: args2.title,
|
|
@@ -95865,7 +96211,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95865
96211
|
}
|
|
95866
96212
|
try {
|
|
95867
96213
|
await savePlan(dir, plan, {
|
|
95868
|
-
preserveCompletedStatuses: !args2.reset_statuses
|
|
96214
|
+
preserveCompletedStatuses: !args2.reset_statuses,
|
|
96215
|
+
...resolvedRemovedIds.length > 0 ? {
|
|
96216
|
+
acknowledged_removals: {
|
|
96217
|
+
ids: resolvedRemovedIds,
|
|
96218
|
+
reason: (resolvedRemovalReason ?? "").trim(),
|
|
96219
|
+
source: "save_plan_tool"
|
|
96220
|
+
}
|
|
96221
|
+
} : {}
|
|
95869
96222
|
});
|
|
95870
96223
|
const savedPlan = await loadPlanJsonOnly(dir);
|
|
95871
96224
|
if (savedPlan) {
|
|
@@ -95894,7 +96247,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95894
96247
|
}
|
|
95895
96248
|
await writeCheckpoint(dir).catch(() => {});
|
|
95896
96249
|
try {
|
|
95897
|
-
const markerPath =
|
|
96250
|
+
const markerPath = path116.join(dir, ".swarm", ".plan-write-marker");
|
|
95898
96251
|
const marker = JSON.stringify({
|
|
95899
96252
|
source: "save_plan",
|
|
95900
96253
|
timestamp: new Date().toISOString(),
|
|
@@ -95917,7 +96270,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95917
96270
|
return {
|
|
95918
96271
|
success: true,
|
|
95919
96272
|
message: "Plan saved successfully",
|
|
95920
|
-
plan_path:
|
|
96273
|
+
plan_path: path116.join(dir, ".swarm", "plan.json"),
|
|
95921
96274
|
phases_count: plan.phases.length,
|
|
95922
96275
|
tasks_count: tasksCount,
|
|
95923
96276
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -95929,6 +96282,15 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
95929
96282
|
}
|
|
95930
96283
|
}
|
|
95931
96284
|
} catch (error93) {
|
|
96285
|
+
if (error93 instanceof PlanTaskRemovalNotAcknowledgedError) {
|
|
96286
|
+
const ids = error93.missingTasks.map((t) => t.id);
|
|
96287
|
+
return {
|
|
96288
|
+
success: false,
|
|
96289
|
+
message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
|
|
96290
|
+
errors: [error93.message],
|
|
96291
|
+
recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(ids)} and a non-empty removal_reason.`
|
|
96292
|
+
};
|
|
96293
|
+
}
|
|
95932
96294
|
return {
|
|
95933
96295
|
success: false,
|
|
95934
96296
|
message: "Failed to save plan: retry with save_plan after resolving the error above",
|
|
@@ -95955,6 +96317,9 @@ var save_plan = createSwarmTool({
|
|
|
95955
96317
|
})).min(1).describe("Implementation phases"),
|
|
95956
96318
|
working_directory: exports_external.string().optional().describe("Working directory (explicit path, required - no fallback)"),
|
|
95957
96319
|
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)."),
|
|
96320
|
+
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."),
|
|
96321
|
+
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."),
|
|
96322
|
+
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
96323
|
execution_profile: exports_external.object({
|
|
95959
96324
|
parallelization_enabled: exports_external.boolean().optional().describe("When true, enables parallel task dispatch for this plan. Default false (serial)."),
|
|
95960
96325
|
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 +96335,7 @@ var save_plan = createSwarmTool({
|
|
|
95970
96335
|
init_zod();
|
|
95971
96336
|
init_manager2();
|
|
95972
96337
|
import * as fs91 from "node:fs";
|
|
95973
|
-
import * as
|
|
96338
|
+
import * as path117 from "node:path";
|
|
95974
96339
|
|
|
95975
96340
|
// src/sbom/detectors/index.ts
|
|
95976
96341
|
init_utils();
|
|
@@ -96820,7 +97185,7 @@ function findManifestFiles(rootDir) {
|
|
|
96820
97185
|
try {
|
|
96821
97186
|
const entries = fs91.readdirSync(dir, { withFileTypes: true });
|
|
96822
97187
|
for (const entry of entries) {
|
|
96823
|
-
const fullPath =
|
|
97188
|
+
const fullPath = path117.join(dir, entry.name);
|
|
96824
97189
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
96825
97190
|
continue;
|
|
96826
97191
|
}
|
|
@@ -96829,7 +97194,7 @@ function findManifestFiles(rootDir) {
|
|
|
96829
97194
|
} else if (entry.isFile()) {
|
|
96830
97195
|
for (const pattern of patterns) {
|
|
96831
97196
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
96832
|
-
manifestFiles.push(
|
|
97197
|
+
manifestFiles.push(path117.relative(rootDir, fullPath));
|
|
96833
97198
|
break;
|
|
96834
97199
|
}
|
|
96835
97200
|
}
|
|
@@ -96847,11 +97212,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
96847
97212
|
try {
|
|
96848
97213
|
const entries = fs91.readdirSync(dir, { withFileTypes: true });
|
|
96849
97214
|
for (const entry of entries) {
|
|
96850
|
-
const fullPath =
|
|
97215
|
+
const fullPath = path117.join(dir, entry.name);
|
|
96851
97216
|
if (entry.isFile()) {
|
|
96852
97217
|
for (const pattern of patterns) {
|
|
96853
97218
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
96854
|
-
found.push(
|
|
97219
|
+
found.push(path117.relative(workingDir, fullPath));
|
|
96855
97220
|
break;
|
|
96856
97221
|
}
|
|
96857
97222
|
}
|
|
@@ -96864,11 +97229,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
96864
97229
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
96865
97230
|
const dirs = new Set;
|
|
96866
97231
|
for (const file3 of changedFiles) {
|
|
96867
|
-
let currentDir =
|
|
97232
|
+
let currentDir = path117.dirname(file3);
|
|
96868
97233
|
while (true) {
|
|
96869
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
96870
|
-
dirs.add(
|
|
96871
|
-
const parent =
|
|
97234
|
+
if (currentDir && currentDir !== "." && currentDir !== path117.sep) {
|
|
97235
|
+
dirs.add(path117.join(workingDir, currentDir));
|
|
97236
|
+
const parent = path117.dirname(currentDir);
|
|
96872
97237
|
if (parent === currentDir)
|
|
96873
97238
|
break;
|
|
96874
97239
|
currentDir = parent;
|
|
@@ -96952,7 +97317,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96952
97317
|
const changedFiles = obj.changed_files;
|
|
96953
97318
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
96954
97319
|
const workingDir = directory;
|
|
96955
|
-
const outputDir =
|
|
97320
|
+
const outputDir = path117.isAbsolute(relativeOutputDir) ? relativeOutputDir : path117.join(workingDir, relativeOutputDir);
|
|
96956
97321
|
let manifestFiles = [];
|
|
96957
97322
|
if (scope === "all") {
|
|
96958
97323
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -96975,7 +97340,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96975
97340
|
const processedFiles = [];
|
|
96976
97341
|
for (const manifestFile of manifestFiles) {
|
|
96977
97342
|
try {
|
|
96978
|
-
const fullPath =
|
|
97343
|
+
const fullPath = path117.isAbsolute(manifestFile) ? manifestFile : path117.join(workingDir, manifestFile);
|
|
96979
97344
|
if (!fs91.existsSync(fullPath)) {
|
|
96980
97345
|
continue;
|
|
96981
97346
|
}
|
|
@@ -96992,7 +97357,7 @@ var sbom_generate = createSwarmTool({
|
|
|
96992
97357
|
const bom = generateCycloneDX(allComponents);
|
|
96993
97358
|
const bomJson = serializeCycloneDX(bom);
|
|
96994
97359
|
const filename = generateSbomFilename();
|
|
96995
|
-
const outputPath =
|
|
97360
|
+
const outputPath = path117.join(outputDir, filename);
|
|
96996
97361
|
fs91.writeFileSync(outputPath, bomJson, "utf-8");
|
|
96997
97362
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
96998
97363
|
try {
|
|
@@ -97036,7 +97401,7 @@ var sbom_generate = createSwarmTool({
|
|
|
97036
97401
|
init_zod();
|
|
97037
97402
|
init_create_tool();
|
|
97038
97403
|
import * as fs92 from "node:fs";
|
|
97039
|
-
import * as
|
|
97404
|
+
import * as path118 from "node:path";
|
|
97040
97405
|
var SPEC_CANDIDATES = [
|
|
97041
97406
|
"openapi.json",
|
|
97042
97407
|
"openapi.yaml",
|
|
@@ -97068,12 +97433,12 @@ function normalizePath4(p) {
|
|
|
97068
97433
|
}
|
|
97069
97434
|
function discoverSpecFile(cwd, specFileArg) {
|
|
97070
97435
|
if (specFileArg) {
|
|
97071
|
-
const resolvedPath =
|
|
97072
|
-
const normalizedCwd = cwd.endsWith(
|
|
97436
|
+
const resolvedPath = path118.resolve(cwd, specFileArg);
|
|
97437
|
+
const normalizedCwd = cwd.endsWith(path118.sep) ? cwd : cwd + path118.sep;
|
|
97073
97438
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
97074
97439
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
97075
97440
|
}
|
|
97076
|
-
const ext =
|
|
97441
|
+
const ext = path118.extname(resolvedPath).toLowerCase();
|
|
97077
97442
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
97078
97443
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
97079
97444
|
}
|
|
@@ -97087,7 +97452,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
97087
97452
|
return resolvedPath;
|
|
97088
97453
|
}
|
|
97089
97454
|
for (const candidate of SPEC_CANDIDATES) {
|
|
97090
|
-
const candidatePath =
|
|
97455
|
+
const candidatePath = path118.resolve(cwd, candidate);
|
|
97091
97456
|
if (fs92.existsSync(candidatePath)) {
|
|
97092
97457
|
const stats = fs92.statSync(candidatePath);
|
|
97093
97458
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -97099,7 +97464,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
97099
97464
|
}
|
|
97100
97465
|
function parseSpec(specFile) {
|
|
97101
97466
|
const content = fs92.readFileSync(specFile, "utf-8");
|
|
97102
|
-
const ext =
|
|
97467
|
+
const ext = path118.extname(specFile).toLowerCase();
|
|
97103
97468
|
if (ext === ".json") {
|
|
97104
97469
|
return parseJsonSpec(content);
|
|
97105
97470
|
}
|
|
@@ -97175,7 +97540,7 @@ function extractRoutes(cwd) {
|
|
|
97175
97540
|
return;
|
|
97176
97541
|
}
|
|
97177
97542
|
for (const entry of entries) {
|
|
97178
|
-
const fullPath =
|
|
97543
|
+
const fullPath = path118.join(dir, entry.name);
|
|
97179
97544
|
if (entry.isSymbolicLink()) {
|
|
97180
97545
|
continue;
|
|
97181
97546
|
}
|
|
@@ -97185,7 +97550,7 @@ function extractRoutes(cwd) {
|
|
|
97185
97550
|
}
|
|
97186
97551
|
walkDir(fullPath);
|
|
97187
97552
|
} else if (entry.isFile()) {
|
|
97188
|
-
const ext =
|
|
97553
|
+
const ext = path118.extname(entry.name).toLowerCase();
|
|
97189
97554
|
const baseName = entry.name.toLowerCase();
|
|
97190
97555
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
97191
97556
|
continue;
|
|
@@ -97353,7 +97718,7 @@ init_bun_compat();
|
|
|
97353
97718
|
init_path_security();
|
|
97354
97719
|
init_create_tool();
|
|
97355
97720
|
import * as fs93 from "node:fs";
|
|
97356
|
-
import * as
|
|
97721
|
+
import * as path119 from "node:path";
|
|
97357
97722
|
var DEFAULT_MAX_RESULTS = 100;
|
|
97358
97723
|
var DEFAULT_MAX_LINES = 200;
|
|
97359
97724
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -97389,11 +97754,11 @@ function containsWindowsAttacks3(str) {
|
|
|
97389
97754
|
}
|
|
97390
97755
|
function isPathInWorkspace3(filePath, workspace) {
|
|
97391
97756
|
try {
|
|
97392
|
-
const resolvedPath =
|
|
97757
|
+
const resolvedPath = path119.resolve(workspace, filePath);
|
|
97393
97758
|
const realWorkspace = fs93.realpathSync(workspace);
|
|
97394
97759
|
const realResolvedPath = fs93.realpathSync(resolvedPath);
|
|
97395
|
-
const relativePath =
|
|
97396
|
-
if (relativePath.startsWith("..") ||
|
|
97760
|
+
const relativePath = path119.relative(realWorkspace, realResolvedPath);
|
|
97761
|
+
if (relativePath.startsWith("..") || path119.isAbsolute(relativePath)) {
|
|
97397
97762
|
return false;
|
|
97398
97763
|
}
|
|
97399
97764
|
return true;
|
|
@@ -97406,11 +97771,11 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
97406
97771
|
}
|
|
97407
97772
|
function findRgInEnvPath() {
|
|
97408
97773
|
const searchPath = process.env.PATH ?? "";
|
|
97409
|
-
for (const dir of searchPath.split(
|
|
97774
|
+
for (const dir of searchPath.split(path119.delimiter)) {
|
|
97410
97775
|
if (!dir)
|
|
97411
97776
|
continue;
|
|
97412
97777
|
const isWindows = process.platform === "win32";
|
|
97413
|
-
const candidate =
|
|
97778
|
+
const candidate = path119.join(dir, isWindows ? "rg.exe" : "rg");
|
|
97414
97779
|
if (fs93.existsSync(candidate))
|
|
97415
97780
|
return candidate;
|
|
97416
97781
|
}
|
|
@@ -97540,8 +97905,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
97540
97905
|
try {
|
|
97541
97906
|
const entries = fs93.readdirSync(dir, { withFileTypes: true });
|
|
97542
97907
|
for (const entry of entries) {
|
|
97543
|
-
const fullPath =
|
|
97544
|
-
const relativePath =
|
|
97908
|
+
const fullPath = path119.join(dir, entry.name);
|
|
97909
|
+
const relativePath = path119.relative(workspace, fullPath);
|
|
97545
97910
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
97546
97911
|
continue;
|
|
97547
97912
|
}
|
|
@@ -97582,7 +97947,7 @@ async function fallbackSearch(opts) {
|
|
|
97582
97947
|
const matches = [];
|
|
97583
97948
|
let total = 0;
|
|
97584
97949
|
for (const file3 of files) {
|
|
97585
|
-
const fullPath =
|
|
97950
|
+
const fullPath = path119.join(opts.workspace, file3);
|
|
97586
97951
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
97587
97952
|
continue;
|
|
97588
97953
|
}
|
|
@@ -97950,7 +98315,7 @@ init_config();
|
|
|
97950
98315
|
init_schema();
|
|
97951
98316
|
init_create_tool();
|
|
97952
98317
|
import { mkdir as mkdir19, rename as rename8, writeFile as writeFile15 } from "node:fs/promises";
|
|
97953
|
-
import * as
|
|
98318
|
+
import * as path120 from "node:path";
|
|
97954
98319
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
97955
98320
|
var spec_write = createSwarmTool({
|
|
97956
98321
|
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 +98356,8 @@ var spec_write = createSwarmTool({
|
|
|
97991
98356
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
97992
98357
|
}, null, 2);
|
|
97993
98358
|
}
|
|
97994
|
-
const target =
|
|
97995
|
-
await mkdir19(
|
|
98359
|
+
const target = path120.join(directory, ".swarm", "spec.md");
|
|
98360
|
+
await mkdir19(path120.dirname(target), { recursive: true });
|
|
97996
98361
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
97997
98362
|
let finalContent = content;
|
|
97998
98363
|
if (mode === "append") {
|
|
@@ -98020,14 +98385,14 @@ ${content}
|
|
|
98020
98385
|
init_zod();
|
|
98021
98386
|
init_loader();
|
|
98022
98387
|
import {
|
|
98023
|
-
existsSync as
|
|
98388
|
+
existsSync as existsSync70,
|
|
98024
98389
|
mkdirSync as mkdirSync29,
|
|
98025
|
-
readFileSync as
|
|
98390
|
+
readFileSync as readFileSync61,
|
|
98026
98391
|
renameSync as renameSync19,
|
|
98027
98392
|
unlinkSync as unlinkSync15,
|
|
98028
98393
|
writeFileSync as writeFileSync23
|
|
98029
98394
|
} from "node:fs";
|
|
98030
|
-
import
|
|
98395
|
+
import path121 from "node:path";
|
|
98031
98396
|
init_create_tool();
|
|
98032
98397
|
init_resolve_working_directory();
|
|
98033
98398
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -98157,9 +98522,9 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
98157
98522
|
}
|
|
98158
98523
|
});
|
|
98159
98524
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
98160
|
-
const mutationGatePath =
|
|
98525
|
+
const mutationGatePath = path121.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
98161
98526
|
try {
|
|
98162
|
-
const raw =
|
|
98527
|
+
const raw = readFileSync61(mutationGatePath, "utf-8");
|
|
98163
98528
|
const parsed = JSON.parse(raw);
|
|
98164
98529
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
98165
98530
|
if (!gateEntry) {
|
|
@@ -98219,9 +98584,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
98219
98584
|
}
|
|
98220
98585
|
}
|
|
98221
98586
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
98222
|
-
const evidenceDir =
|
|
98587
|
+
const evidenceDir = path121.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
98223
98588
|
mkdirSync29(evidenceDir, { recursive: true });
|
|
98224
|
-
const evidenceFile =
|
|
98589
|
+
const evidenceFile = path121.join(evidenceDir, "phase-council.json");
|
|
98225
98590
|
const evidenceBundle = {
|
|
98226
98591
|
entries: [
|
|
98227
98592
|
{
|
|
@@ -98257,7 +98622,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
98257
98622
|
writeFileSync23(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
98258
98623
|
renameSync19(tempFile, evidenceFile);
|
|
98259
98624
|
} finally {
|
|
98260
|
-
if (
|
|
98625
|
+
if (existsSync70(tempFile)) {
|
|
98261
98626
|
unlinkSync15(tempFile);
|
|
98262
98627
|
}
|
|
98263
98628
|
}
|
|
@@ -98307,7 +98672,7 @@ init_zod();
|
|
|
98307
98672
|
init_path_security();
|
|
98308
98673
|
init_create_tool();
|
|
98309
98674
|
import * as fs94 from "node:fs";
|
|
98310
|
-
import * as
|
|
98675
|
+
import * as path122 from "node:path";
|
|
98311
98676
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
98312
98677
|
function containsWindowsAttacks4(str) {
|
|
98313
98678
|
if (/:[^\\/]/.test(str))
|
|
@@ -98321,14 +98686,14 @@ function containsWindowsAttacks4(str) {
|
|
|
98321
98686
|
}
|
|
98322
98687
|
function isPathInWorkspace4(filePath, workspace) {
|
|
98323
98688
|
try {
|
|
98324
|
-
const resolvedPath =
|
|
98689
|
+
const resolvedPath = path122.resolve(workspace, filePath);
|
|
98325
98690
|
if (!fs94.existsSync(resolvedPath)) {
|
|
98326
98691
|
return true;
|
|
98327
98692
|
}
|
|
98328
98693
|
const realWorkspace = fs94.realpathSync(workspace);
|
|
98329
98694
|
const realResolvedPath = fs94.realpathSync(resolvedPath);
|
|
98330
|
-
const relativePath =
|
|
98331
|
-
if (relativePath.startsWith("..") ||
|
|
98695
|
+
const relativePath = path122.relative(realWorkspace, realResolvedPath);
|
|
98696
|
+
if (relativePath.startsWith("..") || path122.isAbsolute(relativePath)) {
|
|
98332
98697
|
return false;
|
|
98333
98698
|
}
|
|
98334
98699
|
return true;
|
|
@@ -98536,7 +98901,7 @@ var suggestPatch = createSwarmTool({
|
|
|
98536
98901
|
});
|
|
98537
98902
|
continue;
|
|
98538
98903
|
}
|
|
98539
|
-
const fullPath =
|
|
98904
|
+
const fullPath = path122.resolve(directory, change.file);
|
|
98540
98905
|
if (!fs94.existsSync(fullPath)) {
|
|
98541
98906
|
errors5.push({
|
|
98542
98907
|
success: false,
|
|
@@ -98840,11 +99205,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
98840
99205
|
init_zod();
|
|
98841
99206
|
init_constants();
|
|
98842
99207
|
import * as fs96 from "node:fs";
|
|
98843
|
-
import * as
|
|
99208
|
+
import * as path124 from "node:path";
|
|
98844
99209
|
|
|
98845
99210
|
// src/turbo/lean/conflicts.ts
|
|
98846
99211
|
import * as fs95 from "node:fs";
|
|
98847
|
-
import * as
|
|
99212
|
+
import * as path123 from "node:path";
|
|
98848
99213
|
var DEFAULT_GLOBAL_FILES = [
|
|
98849
99214
|
"package.json",
|
|
98850
99215
|
"package-lock.json",
|
|
@@ -98971,7 +99336,7 @@ function isProtectedPath2(normalizedPath) {
|
|
|
98971
99336
|
return false;
|
|
98972
99337
|
}
|
|
98973
99338
|
function readTaskScopes(directory, taskId) {
|
|
98974
|
-
const scopePath =
|
|
99339
|
+
const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
98975
99340
|
try {
|
|
98976
99341
|
if (!fs95.existsSync(scopePath)) {
|
|
98977
99342
|
return null;
|
|
@@ -99359,7 +99724,7 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
99359
99724
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
99360
99725
|
init_create_tool();
|
|
99361
99726
|
function readPlanJson(directory) {
|
|
99362
|
-
const planPath =
|
|
99727
|
+
const planPath = path124.join(directory, ".swarm", "plan.json");
|
|
99363
99728
|
if (!fs96.existsSync(planPath)) {
|
|
99364
99729
|
return null;
|
|
99365
99730
|
}
|
|
@@ -99414,7 +99779,7 @@ init_config();
|
|
|
99414
99779
|
// src/turbo/lean/reviewer.ts
|
|
99415
99780
|
init_state();
|
|
99416
99781
|
import * as fs97 from "node:fs/promises";
|
|
99417
|
-
import * as
|
|
99782
|
+
import * as path125 from "node:path";
|
|
99418
99783
|
init_state3();
|
|
99419
99784
|
var DEFAULT_CONFIG3 = {
|
|
99420
99785
|
reviewerAgent: "",
|
|
@@ -99530,9 +99895,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
99530
99895
|
return { verdict, reason };
|
|
99531
99896
|
}
|
|
99532
99897
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
99533
|
-
const evidenceDir =
|
|
99898
|
+
const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
|
|
99534
99899
|
await fs97.mkdir(evidenceDir, { recursive: true });
|
|
99535
|
-
const evidencePath =
|
|
99900
|
+
const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
99536
99901
|
const content = JSON.stringify({
|
|
99537
99902
|
phase,
|
|
99538
99903
|
verdict,
|
|
@@ -100337,7 +100702,7 @@ var lean_turbo_status = createSwarmTool({
|
|
|
100337
100702
|
init_spec_schema();
|
|
100338
100703
|
init_create_tool();
|
|
100339
100704
|
import * as fs98 from "node:fs";
|
|
100340
|
-
import * as
|
|
100705
|
+
import * as path126 from "node:path";
|
|
100341
100706
|
var SPEC_FILE_NAME = "spec.md";
|
|
100342
100707
|
var SWARM_DIR2 = ".swarm";
|
|
100343
100708
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -100390,7 +100755,7 @@ var lint_spec = createSwarmTool({
|
|
|
100390
100755
|
async execute(_args, directory) {
|
|
100391
100756
|
const errors5 = [];
|
|
100392
100757
|
const warnings = [];
|
|
100393
|
-
const specPath =
|
|
100758
|
+
const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
100394
100759
|
if (!fs98.existsSync(specPath)) {
|
|
100395
100760
|
const result2 = {
|
|
100396
100761
|
valid: false,
|
|
@@ -100461,12 +100826,12 @@ var lint_spec = createSwarmTool({
|
|
|
100461
100826
|
// src/tools/mutation-test.ts
|
|
100462
100827
|
init_zod();
|
|
100463
100828
|
import * as fs99 from "node:fs";
|
|
100464
|
-
import * as
|
|
100829
|
+
import * as path128 from "node:path";
|
|
100465
100830
|
|
|
100466
100831
|
// src/mutation/engine.ts
|
|
100467
100832
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
100468
100833
|
import { unlinkSync as unlinkSync16, writeFileSync as writeFileSync24 } from "node:fs";
|
|
100469
|
-
import * as
|
|
100834
|
+
import * as path127 from "node:path";
|
|
100470
100835
|
|
|
100471
100836
|
// src/mutation/equivalence.ts
|
|
100472
100837
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -100606,7 +100971,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
100606
100971
|
let patchFile;
|
|
100607
100972
|
try {
|
|
100608
100973
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
100609
|
-
patchFile =
|
|
100974
|
+
patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
100610
100975
|
try {
|
|
100611
100976
|
writeFileSync24(patchFile, patch.patch);
|
|
100612
100977
|
} catch (writeErr) {
|
|
@@ -101005,7 +101370,7 @@ var mutation_test = createSwarmTool({
|
|
|
101005
101370
|
];
|
|
101006
101371
|
for (const filePath of uniquePaths) {
|
|
101007
101372
|
try {
|
|
101008
|
-
const resolvedPath =
|
|
101373
|
+
const resolvedPath = path128.resolve(cwd, filePath);
|
|
101009
101374
|
sourceFiles.set(filePath, fs99.readFileSync(resolvedPath, "utf-8"));
|
|
101010
101375
|
} catch {}
|
|
101011
101376
|
}
|
|
@@ -101025,7 +101390,7 @@ init_zod();
|
|
|
101025
101390
|
init_manager2();
|
|
101026
101391
|
init_detector();
|
|
101027
101392
|
import * as fs100 from "node:fs";
|
|
101028
|
-
import * as
|
|
101393
|
+
import * as path129 from "node:path";
|
|
101029
101394
|
init_create_tool();
|
|
101030
101395
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
101031
101396
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -101091,7 +101456,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101091
101456
|
if (languages?.length) {
|
|
101092
101457
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
101093
101458
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
101094
|
-
const ext =
|
|
101459
|
+
const ext = path129.extname(file3.path).toLowerCase();
|
|
101095
101460
|
const langDef = getLanguageForExtension(ext);
|
|
101096
101461
|
const fileProfile = getProfileForFile(file3.path);
|
|
101097
101462
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -101104,7 +101469,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101104
101469
|
let skippedCount = 0;
|
|
101105
101470
|
for (const fileInfo of filesToCheck) {
|
|
101106
101471
|
const { path: filePath } = fileInfo;
|
|
101107
|
-
const fullPath =
|
|
101472
|
+
const fullPath = path129.isAbsolute(filePath) ? filePath : path129.join(directory, filePath);
|
|
101108
101473
|
const result = {
|
|
101109
101474
|
path: filePath,
|
|
101110
101475
|
language: "",
|
|
@@ -101153,7 +101518,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101153
101518
|
results.push(result);
|
|
101154
101519
|
continue;
|
|
101155
101520
|
}
|
|
101156
|
-
const ext =
|
|
101521
|
+
const ext = path129.extname(filePath).toLowerCase();
|
|
101157
101522
|
const langDef = getLanguageForExtension(ext);
|
|
101158
101523
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
101159
101524
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -101246,7 +101611,7 @@ init_utils();
|
|
|
101246
101611
|
init_create_tool();
|
|
101247
101612
|
init_path_security();
|
|
101248
101613
|
import * as fs101 from "node:fs";
|
|
101249
|
-
import * as
|
|
101614
|
+
import * as path130 from "node:path";
|
|
101250
101615
|
var MAX_TEXT_LENGTH = 200;
|
|
101251
101616
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
101252
101617
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -101312,9 +101677,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
101312
101677
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
101313
101678
|
}
|
|
101314
101679
|
try {
|
|
101315
|
-
const resolvedPath =
|
|
101316
|
-
const normalizedCwd =
|
|
101317
|
-
const normalizedResolved =
|
|
101680
|
+
const resolvedPath = path130.resolve(paths);
|
|
101681
|
+
const normalizedCwd = path130.resolve(cwd);
|
|
101682
|
+
const normalizedResolved = path130.resolve(resolvedPath);
|
|
101318
101683
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
101319
101684
|
return {
|
|
101320
101685
|
error: "paths must be within the current working directory",
|
|
@@ -101330,7 +101695,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
101330
101695
|
}
|
|
101331
101696
|
}
|
|
101332
101697
|
function isSupportedExtension(filePath) {
|
|
101333
|
-
const ext =
|
|
101698
|
+
const ext = path130.extname(filePath).toLowerCase();
|
|
101334
101699
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
101335
101700
|
}
|
|
101336
101701
|
function findSourceFiles3(dir, files = []) {
|
|
@@ -101345,7 +101710,7 @@ function findSourceFiles3(dir, files = []) {
|
|
|
101345
101710
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
101346
101711
|
continue;
|
|
101347
101712
|
}
|
|
101348
|
-
const fullPath =
|
|
101713
|
+
const fullPath = path130.join(dir, entry);
|
|
101349
101714
|
let stat8;
|
|
101350
101715
|
try {
|
|
101351
101716
|
stat8 = fs101.statSync(fullPath);
|
|
@@ -101457,7 +101822,7 @@ var todo_extract = createSwarmTool({
|
|
|
101457
101822
|
filesToScan.push(scanPath);
|
|
101458
101823
|
} else {
|
|
101459
101824
|
const errorResult = {
|
|
101460
|
-
error: `unsupported file extension: ${
|
|
101825
|
+
error: `unsupported file extension: ${path130.extname(scanPath)}`,
|
|
101461
101826
|
total: 0,
|
|
101462
101827
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
101463
101828
|
entries: []
|
|
@@ -101506,17 +101871,17 @@ init_schema();
|
|
|
101506
101871
|
init_qa_gate_profile();
|
|
101507
101872
|
init_gate_evidence();
|
|
101508
101873
|
import * as fs105 from "node:fs";
|
|
101509
|
-
import * as
|
|
101874
|
+
import * as path134 from "node:path";
|
|
101510
101875
|
|
|
101511
101876
|
// src/hooks/diff-scope.ts
|
|
101512
101877
|
init_bun_compat();
|
|
101513
101878
|
import * as fs103 from "node:fs";
|
|
101514
|
-
import * as
|
|
101879
|
+
import * as path132 from "node:path";
|
|
101515
101880
|
|
|
101516
101881
|
// src/utils/gitignore-warning.ts
|
|
101517
101882
|
init_bun_compat();
|
|
101518
101883
|
import * as fs102 from "node:fs";
|
|
101519
|
-
import * as
|
|
101884
|
+
import * as path131 from "node:path";
|
|
101520
101885
|
var _internals48 = { bunSpawn };
|
|
101521
101886
|
var _swarmGitExcludedChecked = false;
|
|
101522
101887
|
function fileCoversSwarm(content) {
|
|
@@ -101590,10 +101955,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
101590
101955
|
const excludeRelPath = excludePathRaw.trim();
|
|
101591
101956
|
if (!excludeRelPath)
|
|
101592
101957
|
return;
|
|
101593
|
-
const excludePath =
|
|
101958
|
+
const excludePath = path131.isAbsolute(excludeRelPath) ? excludeRelPath : path131.join(directory, excludeRelPath);
|
|
101594
101959
|
if (checkIgnoreExitCode !== 0) {
|
|
101595
101960
|
try {
|
|
101596
|
-
fs102.mkdirSync(
|
|
101961
|
+
fs102.mkdirSync(path131.dirname(excludePath), { recursive: true });
|
|
101597
101962
|
let existing = "";
|
|
101598
101963
|
try {
|
|
101599
101964
|
existing = fs102.readFileSync(excludePath, "utf8");
|
|
@@ -101637,7 +102002,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
101637
102002
|
var _internals49 = { bunSpawn };
|
|
101638
102003
|
function getDeclaredScope(taskId, directory) {
|
|
101639
102004
|
try {
|
|
101640
|
-
const planPath =
|
|
102005
|
+
const planPath = path132.join(directory, ".swarm", "plan.json");
|
|
101641
102006
|
if (!fs103.existsSync(planPath))
|
|
101642
102007
|
return null;
|
|
101643
102008
|
const raw = fs103.readFileSync(planPath, "utf-8");
|
|
@@ -101743,7 +102108,7 @@ init_telemetry();
|
|
|
101743
102108
|
// src/turbo/lean/task-completion.ts
|
|
101744
102109
|
init_file_locks();
|
|
101745
102110
|
import * as fs104 from "node:fs";
|
|
101746
|
-
import * as
|
|
102111
|
+
import * as path133 from "node:path";
|
|
101747
102112
|
var _internals50 = {
|
|
101748
102113
|
listActiveLocks,
|
|
101749
102114
|
verifyLeanTurboTaskCompletion
|
|
@@ -101762,7 +102127,7 @@ var TIER_3_PATTERNS = [
|
|
|
101762
102127
|
];
|
|
101763
102128
|
function matchesTier3Pattern(files) {
|
|
101764
102129
|
for (const file3 of files) {
|
|
101765
|
-
const fileName =
|
|
102130
|
+
const fileName = path133.basename(file3);
|
|
101766
102131
|
for (const pattern of TIER_3_PATTERNS) {
|
|
101767
102132
|
if (pattern.test(fileName)) {
|
|
101768
102133
|
return true;
|
|
@@ -101774,7 +102139,7 @@ function matchesTier3Pattern(files) {
|
|
|
101774
102139
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
101775
102140
|
let persisted = null;
|
|
101776
102141
|
try {
|
|
101777
|
-
const statePath =
|
|
102142
|
+
const statePath = path133.join(directory, ".swarm", "turbo-state.json");
|
|
101778
102143
|
if (!fs104.existsSync(statePath)) {
|
|
101779
102144
|
return {
|
|
101780
102145
|
ok: false,
|
|
@@ -101858,11 +102223,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
101858
102223
|
};
|
|
101859
102224
|
}
|
|
101860
102225
|
const phase = runState.phase ?? 0;
|
|
101861
|
-
const evidencePath =
|
|
101862
|
-
const expectedDir =
|
|
101863
|
-
const resolvedPath =
|
|
101864
|
-
const resolvedDir =
|
|
101865
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
102226
|
+
const evidencePath = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
102227
|
+
const expectedDir = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
102228
|
+
const resolvedPath = path133.resolve(evidencePath);
|
|
102229
|
+
const resolvedDir = path133.resolve(expectedDir);
|
|
102230
|
+
if (!resolvedPath.startsWith(resolvedDir + path133.sep) && resolvedPath !== resolvedDir) {
|
|
101866
102231
|
return {
|
|
101867
102232
|
ok: false,
|
|
101868
102233
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -101902,7 +102267,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
101902
102267
|
}
|
|
101903
102268
|
let filesTouched = [];
|
|
101904
102269
|
try {
|
|
101905
|
-
const planPath =
|
|
102270
|
+
const planPath = path133.join(directory, ".swarm", "plan.json");
|
|
101906
102271
|
const planRaw = fs104.readFileSync(planPath, "utf-8");
|
|
101907
102272
|
const plan = JSON.parse(planRaw);
|
|
101908
102273
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -101985,7 +102350,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
101985
102350
|
];
|
|
101986
102351
|
function matchesTier3Pattern2(files) {
|
|
101987
102352
|
for (const file3 of files) {
|
|
101988
|
-
const fileName =
|
|
102353
|
+
const fileName = path134.basename(file3);
|
|
101989
102354
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
101990
102355
|
if (pattern.test(fileName)) {
|
|
101991
102356
|
return true;
|
|
@@ -102017,7 +102382,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102017
102382
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
102018
102383
|
const resolvedDir2 = workingDirectory;
|
|
102019
102384
|
try {
|
|
102020
|
-
const planPath =
|
|
102385
|
+
const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
|
|
102021
102386
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102022
102387
|
const plan = JSON.parse(planRaw);
|
|
102023
102388
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -102084,7 +102449,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102084
102449
|
}
|
|
102085
102450
|
try {
|
|
102086
102451
|
const resolvedDir2 = workingDirectory;
|
|
102087
|
-
const planPath =
|
|
102452
|
+
const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
|
|
102088
102453
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102089
102454
|
const plan = JSON.parse(planRaw);
|
|
102090
102455
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -102269,8 +102634,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102269
102634
|
};
|
|
102270
102635
|
}
|
|
102271
102636
|
}
|
|
102272
|
-
normalizedDir =
|
|
102273
|
-
const pathParts = normalizedDir.split(
|
|
102637
|
+
normalizedDir = path134.normalize(args2.working_directory);
|
|
102638
|
+
const pathParts = normalizedDir.split(path134.sep);
|
|
102274
102639
|
if (pathParts.includes("..")) {
|
|
102275
102640
|
return {
|
|
102276
102641
|
success: false,
|
|
@@ -102280,10 +102645,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102280
102645
|
]
|
|
102281
102646
|
};
|
|
102282
102647
|
}
|
|
102283
|
-
const resolvedDir =
|
|
102648
|
+
const resolvedDir = path134.resolve(normalizedDir);
|
|
102284
102649
|
try {
|
|
102285
102650
|
const realPath = fs105.realpathSync(resolvedDir);
|
|
102286
|
-
const planPath =
|
|
102651
|
+
const planPath = path134.join(realPath, ".swarm", "plan.json");
|
|
102287
102652
|
if (!fs105.existsSync(planPath)) {
|
|
102288
102653
|
return {
|
|
102289
102654
|
success: false,
|
|
@@ -102315,8 +102680,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102315
102680
|
}
|
|
102316
102681
|
if (args2.status === "in_progress") {
|
|
102317
102682
|
try {
|
|
102318
|
-
const evidencePath =
|
|
102319
|
-
fs105.mkdirSync(
|
|
102683
|
+
const evidencePath = path134.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
102684
|
+
fs105.mkdirSync(path134.dirname(evidencePath), { recursive: true });
|
|
102320
102685
|
const fd = fs105.openSync(evidencePath, "wx");
|
|
102321
102686
|
let writeOk = false;
|
|
102322
102687
|
try {
|
|
@@ -102340,7 +102705,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102340
102705
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
102341
102706
|
let phaseRequiresReviewer = true;
|
|
102342
102707
|
try {
|
|
102343
|
-
const planPath =
|
|
102708
|
+
const planPath = path134.join(directory, ".swarm", "plan.json");
|
|
102344
102709
|
const planRaw = fs105.readFileSync(planPath, "utf-8");
|
|
102345
102710
|
const plan = JSON.parse(planRaw);
|
|
102346
102711
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
@@ -102652,7 +103017,7 @@ init_ledger();
|
|
|
102652
103017
|
init_manager();
|
|
102653
103018
|
init_create_tool();
|
|
102654
103019
|
import fs106 from "node:fs";
|
|
102655
|
-
import
|
|
103020
|
+
import path135 from "node:path";
|
|
102656
103021
|
function normalizeVerdict(verdict) {
|
|
102657
103022
|
switch (verdict) {
|
|
102658
103023
|
case "APPROVED":
|
|
@@ -102700,7 +103065,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
102700
103065
|
entries: [evidenceEntry]
|
|
102701
103066
|
};
|
|
102702
103067
|
const filename = "drift-verifier.json";
|
|
102703
|
-
const relativePath =
|
|
103068
|
+
const relativePath = path135.join("evidence", String(phase), filename);
|
|
102704
103069
|
let validatedPath;
|
|
102705
103070
|
try {
|
|
102706
103071
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -102711,10 +103076,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
102711
103076
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
102712
103077
|
}, null, 2);
|
|
102713
103078
|
}
|
|
102714
|
-
const evidenceDir =
|
|
103079
|
+
const evidenceDir = path135.dirname(validatedPath);
|
|
102715
103080
|
try {
|
|
102716
103081
|
await fs106.promises.mkdir(evidenceDir, { recursive: true });
|
|
102717
|
-
const tempPath =
|
|
103082
|
+
const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
|
|
102718
103083
|
await fs106.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
102719
103084
|
await fs106.promises.rename(tempPath, validatedPath);
|
|
102720
103085
|
let snapshotInfo;
|
|
@@ -102810,7 +103175,7 @@ var write_drift_evidence = createSwarmTool({
|
|
|
102810
103175
|
init_zod();
|
|
102811
103176
|
init_loader();
|
|
102812
103177
|
import fs107 from "node:fs";
|
|
102813
|
-
import
|
|
103178
|
+
import path136 from "node:path";
|
|
102814
103179
|
init_utils2();
|
|
102815
103180
|
init_manager();
|
|
102816
103181
|
init_create_tool();
|
|
@@ -102898,7 +103263,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
102898
103263
|
timestamp: synthesis.timestamp
|
|
102899
103264
|
};
|
|
102900
103265
|
const filename = "final-council.json";
|
|
102901
|
-
const relativePath =
|
|
103266
|
+
const relativePath = path136.join("evidence", filename);
|
|
102902
103267
|
let validatedPath;
|
|
102903
103268
|
try {
|
|
102904
103269
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -102912,10 +103277,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
102912
103277
|
const evidenceContent = {
|
|
102913
103278
|
entries: [evidenceEntry]
|
|
102914
103279
|
};
|
|
102915
|
-
const evidenceDir =
|
|
103280
|
+
const evidenceDir = path136.dirname(validatedPath);
|
|
102916
103281
|
try {
|
|
102917
103282
|
await fs107.promises.mkdir(evidenceDir, { recursive: true });
|
|
102918
|
-
const tempPath =
|
|
103283
|
+
const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
|
|
102919
103284
|
await fs107.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
102920
103285
|
await fs107.promises.rename(tempPath, validatedPath);
|
|
102921
103286
|
return JSON.stringify({
|
|
@@ -102974,7 +103339,7 @@ init_zod();
|
|
|
102974
103339
|
init_utils2();
|
|
102975
103340
|
init_create_tool();
|
|
102976
103341
|
import fs108 from "node:fs";
|
|
102977
|
-
import
|
|
103342
|
+
import path137 from "node:path";
|
|
102978
103343
|
function normalizeVerdict2(verdict) {
|
|
102979
103344
|
switch (verdict) {
|
|
102980
103345
|
case "APPROVED":
|
|
@@ -103022,7 +103387,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103022
103387
|
entries: [evidenceEntry]
|
|
103023
103388
|
};
|
|
103024
103389
|
const filename = "hallucination-guard.json";
|
|
103025
|
-
const relativePath =
|
|
103390
|
+
const relativePath = path137.join("evidence", String(phase), filename);
|
|
103026
103391
|
let validatedPath;
|
|
103027
103392
|
try {
|
|
103028
103393
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103033,10 +103398,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103033
103398
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103034
103399
|
}, null, 2);
|
|
103035
103400
|
}
|
|
103036
|
-
const evidenceDir =
|
|
103401
|
+
const evidenceDir = path137.dirname(validatedPath);
|
|
103037
103402
|
try {
|
|
103038
103403
|
await fs108.promises.mkdir(evidenceDir, { recursive: true });
|
|
103039
|
-
const tempPath =
|
|
103404
|
+
const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
|
|
103040
103405
|
await fs108.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
103041
103406
|
await fs108.promises.rename(tempPath, validatedPath);
|
|
103042
103407
|
return JSON.stringify({
|
|
@@ -103085,7 +103450,7 @@ init_zod();
|
|
|
103085
103450
|
init_utils2();
|
|
103086
103451
|
init_create_tool();
|
|
103087
103452
|
import fs109 from "node:fs";
|
|
103088
|
-
import
|
|
103453
|
+
import path138 from "node:path";
|
|
103089
103454
|
function normalizeVerdict3(verdict) {
|
|
103090
103455
|
switch (verdict) {
|
|
103091
103456
|
case "PASS":
|
|
@@ -103159,7 +103524,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103159
103524
|
entries: [evidenceEntry]
|
|
103160
103525
|
};
|
|
103161
103526
|
const filename = "mutation-gate.json";
|
|
103162
|
-
const relativePath =
|
|
103527
|
+
const relativePath = path138.join("evidence", String(phase), filename);
|
|
103163
103528
|
let validatedPath;
|
|
103164
103529
|
try {
|
|
103165
103530
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103170,10 +103535,10 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103170
103535
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103171
103536
|
}, null, 2);
|
|
103172
103537
|
}
|
|
103173
|
-
const evidenceDir =
|
|
103538
|
+
const evidenceDir = path138.dirname(validatedPath);
|
|
103174
103539
|
try {
|
|
103175
103540
|
await fs109.promises.mkdir(evidenceDir, { recursive: true });
|
|
103176
|
-
const tempPath =
|
|
103541
|
+
const tempPath = path138.join(evidenceDir, `.${filename}.tmp`);
|
|
103177
103542
|
await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
103178
103543
|
await fs109.promises.rename(tempPath, validatedPath);
|
|
103179
103544
|
return JSON.stringify({
|
|
@@ -103518,7 +103883,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
103518
103883
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
103519
103884
|
preflightTriggerManager = new PTM(automationConfig);
|
|
103520
103885
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
103521
|
-
const swarmDir =
|
|
103886
|
+
const swarmDir = path140.resolve(ctx.directory, ".swarm");
|
|
103522
103887
|
statusArtifact = new ASA(swarmDir);
|
|
103523
103888
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
103524
103889
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|