opencode-swarm 6.50.0 → 6.52.0
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/README.md +1 -0
- package/dist/agents/critic.d.ts +7 -0
- package/dist/cli/index.js +63 -3
- package/dist/commands/full-auto-registration.test.d.ts +5 -0
- package/dist/commands/full-auto-sessionid.test.d.ts +5 -0
- package/dist/commands/full-auto.d.ts +10 -0
- package/dist/commands/full-auto.regression.test.d.ts +10 -0
- package/dist/commands/full-auto.test.d.ts +6 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/registry.d.ts +4 -0
- package/dist/config/constants.d.ts +5 -3
- package/dist/config/schema.d.ts +10 -0
- package/dist/hooks/full-auto-intercept.d.ts +77 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +1738 -916
- package/dist/session/snapshot-writer.d.ts +8 -0
- package/dist/state.d.ts +17 -0
- package/dist/telemetry.d.ts +2 -1
- package/package.json +1 -1
- package/dist/agents/architect.turbo-banner.test.d.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -117,10 +117,37 @@ function isLowCapabilityModel(modelId) {
|
|
|
117
117
|
const lower = modelId.toLowerCase();
|
|
118
118
|
return LOW_CAPABILITY_MODELS.some((substr) => lower.includes(substr));
|
|
119
119
|
}
|
|
120
|
-
var QA_AGENTS, PIPELINE_AGENTS, ORCHESTRATOR_NAME = "architect", ALL_SUBAGENT_NAMES, ALL_AGENT_NAMES, AGENT_TOOL_MAP, WRITE_TOOL_NAMES, TOOL_DESCRIPTIONS, DEFAULT_MODELS, DEFAULT_SCORING_CONFIG, LOW_CAPABILITY_MODELS
|
|
120
|
+
var QA_AGENTS, PIPELINE_AGENTS, ORCHESTRATOR_NAME = "architect", ALL_SUBAGENT_NAMES, ALL_AGENT_NAMES, AGENT_TOOL_MAP, WRITE_TOOL_NAMES, TOOL_DESCRIPTIONS, DEFAULT_MODELS, DEFAULT_SCORING_CONFIG, LOW_CAPABILITY_MODELS, TURBO_MODE_BANNER = `## \uD83D\uDE80 TURBO MODE ACTIVE
|
|
121
|
+
|
|
122
|
+
**Speed optimization enabled for this session.**
|
|
123
|
+
|
|
124
|
+
While Turbo Mode is active:
|
|
125
|
+
- **Stage A gates** (lint, imports, pre_check_batch) are still REQUIRED for ALL tasks
|
|
126
|
+
- **Tier 3 tasks** (security-sensitive files matching: architect*.ts, delegation*.ts, guardrails*.ts, adversarial*.ts, sanitiz*.ts, auth*, permission*, crypto*, secret*, security) still require FULL review (Stage B)
|
|
127
|
+
- **Tier 0-2 tasks** can skip Stage B (reviewer, test_engineer) to speed up execution
|
|
128
|
+
- **Phase completion gates** (completion-verify and drift verification gate) are automatically bypassed \u2014 phase_complete will succeed without drift verification evidence when turbo is active. Note: turbo bypass is session-scoped; one session's turbo does not affect other sessions.
|
|
129
|
+
|
|
130
|
+
Classification still determines the pipeline:
|
|
131
|
+
- TIER 0 (metadata): lint + diff only \u2014 no change
|
|
132
|
+
- TIER 1 (docs): Stage A + reviewer \u2014 no change
|
|
133
|
+
- TIER 2 (standard code): Stage A + reviewer + test_engineer \u2014 CAN SKIP Stage B with turboMode
|
|
134
|
+
- TIER 3 (critical): Stage A + 2x reviewer + 2x test_engineer \u2014 Stage B REQUIRED (no turbo bypass)
|
|
135
|
+
|
|
136
|
+
Do NOT skip Stage A gates. Do NOT skip Stage B for TIER 3.
|
|
137
|
+
`, FULL_AUTO_BANNER = `## \u26A1 FULL-AUTO MODE ACTIVE
|
|
138
|
+
|
|
139
|
+
You are operating without a human in the loop. All escalations route to the Autonomous Oversight Critic instead of a user.
|
|
140
|
+
|
|
141
|
+
Behavioral changes:
|
|
142
|
+
- TIER 3 escalations go to the critic, not a human. Frame your questions technically, not conversationally.
|
|
143
|
+
- Phase completion approval comes from the critic. Ensure all evidence is written before requesting.
|
|
144
|
+
- The critic defaults to REJECT. Do not attempt to pressure, negotiate, or shortcut. Complete the evidence trail.
|
|
145
|
+
- If the critic returns ESCALATE_TO_HUMAN, the session will pause or terminate. Only the critic can trigger this.
|
|
146
|
+
- Do NOT ask "Ready for Phase N+1?" \u2014 call phase_complete directly. The critic reviews automatically.
|
|
147
|
+
`;
|
|
121
148
|
var init_constants = __esm(() => {
|
|
122
149
|
init_tool_names();
|
|
123
|
-
QA_AGENTS = ["reviewer", "critic"];
|
|
150
|
+
QA_AGENTS = ["reviewer", "critic", "critic_oversight"];
|
|
124
151
|
PIPELINE_AGENTS = ["explorer", "coder", "test_engineer"];
|
|
125
152
|
ALL_SUBAGENT_NAMES = [
|
|
126
153
|
"sme",
|
|
@@ -276,6 +303,14 @@ var init_constants = __esm(() => {
|
|
|
276
303
|
"symbols",
|
|
277
304
|
"knowledgeRecall"
|
|
278
305
|
],
|
|
306
|
+
critic_oversight: [
|
|
307
|
+
"complexity_hotspots",
|
|
308
|
+
"detect_domains",
|
|
309
|
+
"imports",
|
|
310
|
+
"retrieve_summary",
|
|
311
|
+
"symbols",
|
|
312
|
+
"knowledgeRecall"
|
|
313
|
+
],
|
|
279
314
|
docs: [
|
|
280
315
|
"detect_domains",
|
|
281
316
|
"extract_code_blocks",
|
|
@@ -366,6 +401,7 @@ var init_constants = __esm(() => {
|
|
|
366
401
|
critic: "opencode/trinity-large-preview-free",
|
|
367
402
|
critic_sounding_board: "opencode/trinity-large-preview-free",
|
|
368
403
|
critic_drift_verifier: "opencode/trinity-large-preview-free",
|
|
404
|
+
critic_oversight: "opencode/trinity-large-preview-free",
|
|
369
405
|
docs: "opencode/trinity-large-preview-free",
|
|
370
406
|
designer: "opencode/trinity-large-preview-free",
|
|
371
407
|
curator_init: "opencode/trinity-large-preview-free",
|
|
@@ -15107,7 +15143,19 @@ var init_schema = __esm(() => {
|
|
|
15107
15143
|
}).optional(),
|
|
15108
15144
|
incremental_verify: IncrementalVerifyConfigSchema.optional(),
|
|
15109
15145
|
compaction_service: CompactionConfigSchema.optional(),
|
|
15110
|
-
turbo_mode: exports_external.boolean().default(false).optional()
|
|
15146
|
+
turbo_mode: exports_external.boolean().default(false).optional(),
|
|
15147
|
+
full_auto: exports_external.object({
|
|
15148
|
+
enabled: exports_external.boolean().default(false),
|
|
15149
|
+
critic_model: exports_external.string().optional(),
|
|
15150
|
+
max_interactions_per_phase: exports_external.number().int().min(5).max(200).default(50),
|
|
15151
|
+
deadlock_threshold: exports_external.number().int().min(2).max(10).default(3),
|
|
15152
|
+
escalation_mode: exports_external.enum(["pause", "terminate"]).default("pause")
|
|
15153
|
+
}).optional().default({
|
|
15154
|
+
enabled: false,
|
|
15155
|
+
max_interactions_per_phase: 50,
|
|
15156
|
+
deadlock_threshold: 3,
|
|
15157
|
+
escalation_mode: "pause"
|
|
15158
|
+
})
|
|
15111
15159
|
});
|
|
15112
15160
|
});
|
|
15113
15161
|
|
|
@@ -15873,7 +15921,533 @@ var init_telemetry = __esm(() => {
|
|
|
15873
15921
|
},
|
|
15874
15922
|
turboModeChanged(sessionId, enabled, agentName) {
|
|
15875
15923
|
emit("turbo_mode_changed", { sessionId, enabled, agentName });
|
|
15924
|
+
},
|
|
15925
|
+
autoOversightEscalation(sessionId, reason, interactionCount, deadlockCount, phase) {
|
|
15926
|
+
emit("auto_oversight_escalation", {
|
|
15927
|
+
sessionId,
|
|
15928
|
+
reason,
|
|
15929
|
+
interactionCount,
|
|
15930
|
+
deadlockCount,
|
|
15931
|
+
phase
|
|
15932
|
+
});
|
|
15933
|
+
}
|
|
15934
|
+
};
|
|
15935
|
+
});
|
|
15936
|
+
|
|
15937
|
+
// src/state.ts
|
|
15938
|
+
var exports_state = {};
|
|
15939
|
+
__export(exports_state, {
|
|
15940
|
+
updateAgentEventTime: () => updateAgentEventTime,
|
|
15941
|
+
swarmState: () => swarmState,
|
|
15942
|
+
startAgentSession: () => startAgentSession,
|
|
15943
|
+
resetSwarmState: () => resetSwarmState,
|
|
15944
|
+
rehydrateSessionFromDisk: () => rehydrateSessionFromDisk,
|
|
15945
|
+
recordPhaseAgentDispatch: () => recordPhaseAgentDispatch,
|
|
15946
|
+
pruneOldWindows: () => pruneOldWindows,
|
|
15947
|
+
hasActiveTurboMode: () => hasActiveTurboMode,
|
|
15948
|
+
hasActiveFullAuto: () => hasActiveFullAuto,
|
|
15949
|
+
getTaskState: () => getTaskState,
|
|
15950
|
+
getAgentSession: () => getAgentSession,
|
|
15951
|
+
getActiveWindow: () => getActiveWindow,
|
|
15952
|
+
ensureAgentSession: () => ensureAgentSession,
|
|
15953
|
+
endAgentSession: () => endAgentSession,
|
|
15954
|
+
buildRehydrationCache: () => buildRehydrationCache,
|
|
15955
|
+
beginInvocation: () => beginInvocation,
|
|
15956
|
+
applyRehydrationCache: () => applyRehydrationCache,
|
|
15957
|
+
advanceTaskState: () => advanceTaskState
|
|
15958
|
+
});
|
|
15959
|
+
import * as fs5 from "fs/promises";
|
|
15960
|
+
import * as path5 from "path";
|
|
15961
|
+
function resetSwarmState() {
|
|
15962
|
+
swarmState.activeToolCalls.clear();
|
|
15963
|
+
swarmState.toolAggregates.clear();
|
|
15964
|
+
swarmState.activeAgent.clear();
|
|
15965
|
+
swarmState.delegationChains.clear();
|
|
15966
|
+
swarmState.pendingEvents = 0;
|
|
15967
|
+
swarmState.lastBudgetPct = 0;
|
|
15968
|
+
swarmState.agentSessions.clear();
|
|
15969
|
+
swarmState.pendingRehydrations.clear();
|
|
15970
|
+
swarmState.opencodeClient = null;
|
|
15971
|
+
swarmState.curatorInitAgentNames = [];
|
|
15972
|
+
swarmState.curatorPhaseAgentNames = [];
|
|
15973
|
+
_rehydrationCache = null;
|
|
15974
|
+
swarmState.fullAutoEnabledInConfig = false;
|
|
15975
|
+
}
|
|
15976
|
+
function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, directory) {
|
|
15977
|
+
const now = Date.now();
|
|
15978
|
+
const staleIds = [];
|
|
15979
|
+
for (const [id, session] of swarmState.agentSessions) {
|
|
15980
|
+
if (now - session.lastToolCallTime > staleDurationMs) {
|
|
15981
|
+
staleIds.push(id);
|
|
15876
15982
|
}
|
|
15983
|
+
}
|
|
15984
|
+
for (const id of staleIds) {
|
|
15985
|
+
swarmState.agentSessions.delete(id);
|
|
15986
|
+
}
|
|
15987
|
+
const sessionState = {
|
|
15988
|
+
agentName,
|
|
15989
|
+
lastToolCallTime: now,
|
|
15990
|
+
lastAgentEventTime: now,
|
|
15991
|
+
delegationActive: false,
|
|
15992
|
+
activeInvocationId: 0,
|
|
15993
|
+
lastInvocationIdByAgent: {},
|
|
15994
|
+
windows: {},
|
|
15995
|
+
lastCompactionHint: 0,
|
|
15996
|
+
architectWriteCount: 0,
|
|
15997
|
+
lastCoderDelegationTaskId: null,
|
|
15998
|
+
currentTaskId: null,
|
|
15999
|
+
gateLog: new Map,
|
|
16000
|
+
reviewerCallCount: new Map,
|
|
16001
|
+
lastGateFailure: null,
|
|
16002
|
+
partialGateWarningsIssuedForTask: new Set,
|
|
16003
|
+
selfFixAttempted: false,
|
|
16004
|
+
selfCodingWarnedAtCount: 0,
|
|
16005
|
+
catastrophicPhaseWarnings: new Set,
|
|
16006
|
+
lastPhaseCompleteTimestamp: 0,
|
|
16007
|
+
lastPhaseCompletePhase: 0,
|
|
16008
|
+
phaseAgentsDispatched: new Set,
|
|
16009
|
+
lastCompletedPhaseAgentsDispatched: new Set,
|
|
16010
|
+
qaSkipCount: 0,
|
|
16011
|
+
qaSkipTaskIds: [],
|
|
16012
|
+
taskWorkflowStates: new Map,
|
|
16013
|
+
lastGateOutcome: null,
|
|
16014
|
+
declaredCoderScope: null,
|
|
16015
|
+
lastScopeViolation: null,
|
|
16016
|
+
scopeViolationDetected: false,
|
|
16017
|
+
modifiedFilesThisCoderTask: [],
|
|
16018
|
+
turboMode: false,
|
|
16019
|
+
fullAutoMode: false,
|
|
16020
|
+
fullAutoInteractionCount: 0,
|
|
16021
|
+
fullAutoDeadlockCount: 0,
|
|
16022
|
+
fullAutoLastQuestionHash: null,
|
|
16023
|
+
model_fallback_index: 0,
|
|
16024
|
+
modelFallbackExhausted: false,
|
|
16025
|
+
coderRevisions: 0,
|
|
16026
|
+
revisionLimitHit: false,
|
|
16027
|
+
loopDetectionWindow: [],
|
|
16028
|
+
pendingAdvisoryMessages: [],
|
|
16029
|
+
sessionRehydratedAt: 0
|
|
16030
|
+
};
|
|
16031
|
+
swarmState.agentSessions.set(sessionId, sessionState);
|
|
16032
|
+
telemetry.sessionStarted(sessionId, agentName);
|
|
16033
|
+
swarmState.activeAgent.set(sessionId, agentName);
|
|
16034
|
+
applyRehydrationCache(sessionState);
|
|
16035
|
+
if (directory) {
|
|
16036
|
+
let rehydrationPromise;
|
|
16037
|
+
rehydrationPromise = rehydrateSessionFromDisk(directory, sessionState).catch((err2) => {
|
|
16038
|
+
console.warn("[state] Rehydration failed:", err2 instanceof Error ? err2.message : String(err2));
|
|
16039
|
+
}).finally(() => {
|
|
16040
|
+
swarmState.pendingRehydrations.delete(rehydrationPromise);
|
|
16041
|
+
});
|
|
16042
|
+
swarmState.pendingRehydrations.add(rehydrationPromise);
|
|
16043
|
+
}
|
|
16044
|
+
}
|
|
16045
|
+
function endAgentSession(sessionId) {
|
|
16046
|
+
swarmState.agentSessions.delete(sessionId);
|
|
16047
|
+
}
|
|
16048
|
+
function getAgentSession(sessionId) {
|
|
16049
|
+
return swarmState.agentSessions.get(sessionId);
|
|
16050
|
+
}
|
|
16051
|
+
function ensureAgentSession(sessionId, agentName, directory) {
|
|
16052
|
+
const now = Date.now();
|
|
16053
|
+
let session = swarmState.agentSessions.get(sessionId);
|
|
16054
|
+
if (session) {
|
|
16055
|
+
if (agentName && agentName !== session.agentName) {
|
|
16056
|
+
const oldName = session.agentName;
|
|
16057
|
+
session.agentName = agentName;
|
|
16058
|
+
telemetry.agentActivated(sessionId, agentName, oldName);
|
|
16059
|
+
session.delegationActive = false;
|
|
16060
|
+
session.lastAgentEventTime = now;
|
|
16061
|
+
if (!session.windows) {
|
|
16062
|
+
session.activeInvocationId = 0;
|
|
16063
|
+
session.lastInvocationIdByAgent = {};
|
|
16064
|
+
session.windows = {};
|
|
16065
|
+
}
|
|
16066
|
+
}
|
|
16067
|
+
if (!session.windows) {
|
|
16068
|
+
session.activeInvocationId = 0;
|
|
16069
|
+
session.lastInvocationIdByAgent = {};
|
|
16070
|
+
session.windows = {};
|
|
16071
|
+
}
|
|
16072
|
+
if (session.lastCompactionHint === undefined) {
|
|
16073
|
+
session.lastCompactionHint = 0;
|
|
16074
|
+
}
|
|
16075
|
+
if (session.architectWriteCount === undefined) {
|
|
16076
|
+
session.architectWriteCount = 0;
|
|
16077
|
+
}
|
|
16078
|
+
if (session.lastCoderDelegationTaskId === undefined) {
|
|
16079
|
+
session.lastCoderDelegationTaskId = null;
|
|
16080
|
+
}
|
|
16081
|
+
if (session.currentTaskId === undefined) {
|
|
16082
|
+
session.currentTaskId = null;
|
|
16083
|
+
}
|
|
16084
|
+
if (!session.gateLog) {
|
|
16085
|
+
session.gateLog = new Map;
|
|
16086
|
+
}
|
|
16087
|
+
if (!session.reviewerCallCount) {
|
|
16088
|
+
session.reviewerCallCount = new Map;
|
|
16089
|
+
}
|
|
16090
|
+
if (session.lastGateFailure === undefined) {
|
|
16091
|
+
session.lastGateFailure = null;
|
|
16092
|
+
}
|
|
16093
|
+
if (!session.partialGateWarningsIssuedForTask) {
|
|
16094
|
+
session.partialGateWarningsIssuedForTask = new Set;
|
|
16095
|
+
}
|
|
16096
|
+
if (session.selfFixAttempted === undefined) {
|
|
16097
|
+
session.selfFixAttempted = false;
|
|
16098
|
+
}
|
|
16099
|
+
if (session.selfCodingWarnedAtCount === undefined) {
|
|
16100
|
+
session.selfCodingWarnedAtCount = 0;
|
|
16101
|
+
}
|
|
16102
|
+
if (!session.catastrophicPhaseWarnings) {
|
|
16103
|
+
session.catastrophicPhaseWarnings = new Set;
|
|
16104
|
+
}
|
|
16105
|
+
if (session.lastPhaseCompleteTimestamp === undefined) {
|
|
16106
|
+
session.lastPhaseCompleteTimestamp = 0;
|
|
16107
|
+
}
|
|
16108
|
+
if (session.lastPhaseCompletePhase === undefined) {
|
|
16109
|
+
session.lastPhaseCompletePhase = 0;
|
|
16110
|
+
}
|
|
16111
|
+
if (!session.phaseAgentsDispatched) {
|
|
16112
|
+
session.phaseAgentsDispatched = new Set;
|
|
16113
|
+
}
|
|
16114
|
+
if (!session.lastCompletedPhaseAgentsDispatched) {
|
|
16115
|
+
session.lastCompletedPhaseAgentsDispatched = new Set;
|
|
16116
|
+
}
|
|
16117
|
+
if (session.qaSkipCount === undefined) {
|
|
16118
|
+
session.qaSkipCount = 0;
|
|
16119
|
+
}
|
|
16120
|
+
if (!session.qaSkipTaskIds) {
|
|
16121
|
+
session.qaSkipTaskIds = [];
|
|
16122
|
+
}
|
|
16123
|
+
if (!session.taskWorkflowStates) {
|
|
16124
|
+
session.taskWorkflowStates = new Map;
|
|
16125
|
+
}
|
|
16126
|
+
if (session.lastGateOutcome === undefined) {
|
|
16127
|
+
session.lastGateOutcome = null;
|
|
16128
|
+
}
|
|
16129
|
+
if (session.declaredCoderScope === undefined) {
|
|
16130
|
+
session.declaredCoderScope = null;
|
|
16131
|
+
}
|
|
16132
|
+
if (session.lastScopeViolation === undefined) {
|
|
16133
|
+
session.lastScopeViolation = null;
|
|
16134
|
+
}
|
|
16135
|
+
if (session.modifiedFilesThisCoderTask === undefined) {
|
|
16136
|
+
session.modifiedFilesThisCoderTask = [];
|
|
16137
|
+
}
|
|
16138
|
+
if (session.scopeViolationDetected === undefined) {
|
|
16139
|
+
session.scopeViolationDetected = false;
|
|
16140
|
+
}
|
|
16141
|
+
if (session.turboMode === undefined) {
|
|
16142
|
+
session.turboMode = false;
|
|
16143
|
+
}
|
|
16144
|
+
if (session.model_fallback_index === undefined) {
|
|
16145
|
+
session.model_fallback_index = 0;
|
|
16146
|
+
}
|
|
16147
|
+
if (session.modelFallbackExhausted === undefined) {
|
|
16148
|
+
session.modelFallbackExhausted = false;
|
|
16149
|
+
}
|
|
16150
|
+
if (session.loopDetectionWindow === undefined) {
|
|
16151
|
+
session.loopDetectionWindow = [];
|
|
16152
|
+
}
|
|
16153
|
+
if (session.pendingAdvisoryMessages === undefined) {
|
|
16154
|
+
session.pendingAdvisoryMessages = [];
|
|
16155
|
+
}
|
|
16156
|
+
if (session.coderRevisions === undefined) {
|
|
16157
|
+
session.coderRevisions = 0;
|
|
16158
|
+
}
|
|
16159
|
+
if (session.revisionLimitHit === undefined) {
|
|
16160
|
+
session.revisionLimitHit = false;
|
|
16161
|
+
}
|
|
16162
|
+
if (session.sessionRehydratedAt === undefined) {
|
|
16163
|
+
session.sessionRehydratedAt = 0;
|
|
16164
|
+
}
|
|
16165
|
+
session.lastToolCallTime = now;
|
|
16166
|
+
return session;
|
|
16167
|
+
}
|
|
16168
|
+
startAgentSession(sessionId, agentName ?? "unknown", 7200000, directory);
|
|
16169
|
+
session = swarmState.agentSessions.get(sessionId);
|
|
16170
|
+
if (!session) {
|
|
16171
|
+
throw new Error(`Failed to create guardrail session for ${sessionId}`);
|
|
16172
|
+
}
|
|
16173
|
+
return session;
|
|
16174
|
+
}
|
|
16175
|
+
function updateAgentEventTime(sessionId) {
|
|
16176
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
16177
|
+
if (session) {
|
|
16178
|
+
session.lastAgentEventTime = Date.now();
|
|
16179
|
+
}
|
|
16180
|
+
}
|
|
16181
|
+
function beginInvocation(sessionId, agentName) {
|
|
16182
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
16183
|
+
if (!session) {
|
|
16184
|
+
throw new Error(`Cannot begin invocation: session ${sessionId} does not exist`);
|
|
16185
|
+
}
|
|
16186
|
+
const stripped = stripKnownSwarmPrefix(agentName);
|
|
16187
|
+
if (stripped === ORCHESTRATOR_NAME) {
|
|
16188
|
+
return null;
|
|
16189
|
+
}
|
|
16190
|
+
const lastId = session.lastInvocationIdByAgent[stripped] || 0;
|
|
16191
|
+
const newId = lastId + 1;
|
|
16192
|
+
session.lastInvocationIdByAgent[stripped] = newId;
|
|
16193
|
+
session.activeInvocationId = newId;
|
|
16194
|
+
const now = Date.now();
|
|
16195
|
+
const window2 = {
|
|
16196
|
+
id: newId,
|
|
16197
|
+
agentName: stripped,
|
|
16198
|
+
startedAtMs: now,
|
|
16199
|
+
toolCalls: 0,
|
|
16200
|
+
consecutiveErrors: 0,
|
|
16201
|
+
hardLimitHit: false,
|
|
16202
|
+
lastSuccessTimeMs: now,
|
|
16203
|
+
recentToolCalls: [],
|
|
16204
|
+
warningIssued: false,
|
|
16205
|
+
warningReason: ""
|
|
16206
|
+
};
|
|
16207
|
+
const key = `${stripped}:${newId}`;
|
|
16208
|
+
session.windows[key] = window2;
|
|
16209
|
+
pruneOldWindows(sessionId, 24 * 60 * 60 * 1000, 50);
|
|
16210
|
+
telemetry.delegationBegin(sessionId, stripped, session.currentTaskId ?? "unknown");
|
|
16211
|
+
return window2;
|
|
16212
|
+
}
|
|
16213
|
+
function getActiveWindow(sessionId) {
|
|
16214
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
16215
|
+
if (!session || !session.windows) {
|
|
16216
|
+
return;
|
|
16217
|
+
}
|
|
16218
|
+
const stripped = stripKnownSwarmPrefix(session.agentName);
|
|
16219
|
+
const key = `${stripped}:${session.activeInvocationId}`;
|
|
16220
|
+
return session.windows[key];
|
|
16221
|
+
}
|
|
16222
|
+
function pruneOldWindows(sessionId, maxAgeMs = 24 * 60 * 60 * 1000, maxWindows = 50) {
|
|
16223
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
16224
|
+
if (!session || !session.windows) {
|
|
16225
|
+
return;
|
|
16226
|
+
}
|
|
16227
|
+
const now = Date.now();
|
|
16228
|
+
const entries = Object.entries(session.windows);
|
|
16229
|
+
const validByAge = entries.filter(([_, window2]) => now - window2.startedAtMs < maxAgeMs);
|
|
16230
|
+
const sorted = validByAge.sort((a, b) => b[1].startedAtMs - a[1].startedAtMs);
|
|
16231
|
+
const toKeep = sorted.slice(0, maxWindows);
|
|
16232
|
+
session.windows = Object.fromEntries(toKeep);
|
|
16233
|
+
}
|
|
16234
|
+
function recordPhaseAgentDispatch(sessionId, agentName) {
|
|
16235
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
16236
|
+
if (!session) {
|
|
16237
|
+
return;
|
|
16238
|
+
}
|
|
16239
|
+
if (!session.phaseAgentsDispatched) {
|
|
16240
|
+
session.phaseAgentsDispatched = new Set;
|
|
16241
|
+
}
|
|
16242
|
+
const normalizedName = stripKnownSwarmPrefix(agentName);
|
|
16243
|
+
session.phaseAgentsDispatched.add(normalizedName);
|
|
16244
|
+
}
|
|
16245
|
+
function isValidTaskId(taskId) {
|
|
16246
|
+
if (taskId === null || taskId === undefined) {
|
|
16247
|
+
return false;
|
|
16248
|
+
}
|
|
16249
|
+
if (typeof taskId !== "string") {
|
|
16250
|
+
return false;
|
|
16251
|
+
}
|
|
16252
|
+
const trimmed = taskId.trim();
|
|
16253
|
+
return trimmed.length > 0;
|
|
16254
|
+
}
|
|
16255
|
+
function advanceTaskState(session, taskId, newState) {
|
|
16256
|
+
if (!isValidTaskId(taskId)) {
|
|
16257
|
+
return;
|
|
16258
|
+
}
|
|
16259
|
+
if (!session || !(session.taskWorkflowStates instanceof Map)) {
|
|
16260
|
+
throw new Error("INVALID_SESSION: session.taskWorkflowStates must be a Map instance");
|
|
16261
|
+
}
|
|
16262
|
+
const STATE_ORDER = [
|
|
16263
|
+
"idle",
|
|
16264
|
+
"coder_delegated",
|
|
16265
|
+
"pre_check_passed",
|
|
16266
|
+
"reviewer_run",
|
|
16267
|
+
"tests_run",
|
|
16268
|
+
"complete"
|
|
16269
|
+
];
|
|
16270
|
+
const current = session.taskWorkflowStates.get(taskId) ?? "idle";
|
|
16271
|
+
const currentIndex = STATE_ORDER.indexOf(current);
|
|
16272
|
+
const newIndex = STATE_ORDER.indexOf(newState);
|
|
16273
|
+
if (newIndex <= currentIndex) {
|
|
16274
|
+
throw new Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} ${current} \u2192 ${newState}`);
|
|
16275
|
+
}
|
|
16276
|
+
if (newState === "complete" && current !== "tests_run") {
|
|
16277
|
+
throw new Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} cannot reach complete from ${current} \u2014 must pass through tests_run first`);
|
|
16278
|
+
}
|
|
16279
|
+
session.taskWorkflowStates.set(taskId, newState);
|
|
16280
|
+
telemetry.taskStateChanged(session.agentName, taskId, newState, current);
|
|
16281
|
+
}
|
|
16282
|
+
function getTaskState(session, taskId) {
|
|
16283
|
+
if (!isValidTaskId(taskId)) {
|
|
16284
|
+
return "idle";
|
|
16285
|
+
}
|
|
16286
|
+
if (!session.taskWorkflowStates) {
|
|
16287
|
+
session.taskWorkflowStates = new Map;
|
|
16288
|
+
}
|
|
16289
|
+
return session.taskWorkflowStates.get(taskId) ?? "idle";
|
|
16290
|
+
}
|
|
16291
|
+
function planStatusToWorkflowState(status) {
|
|
16292
|
+
switch (status) {
|
|
16293
|
+
case "in_progress":
|
|
16294
|
+
return "coder_delegated";
|
|
16295
|
+
case "completed":
|
|
16296
|
+
return "complete";
|
|
16297
|
+
default:
|
|
16298
|
+
return "idle";
|
|
16299
|
+
}
|
|
16300
|
+
}
|
|
16301
|
+
function evidenceToWorkflowState(evidence) {
|
|
16302
|
+
const gates = evidence.gates ?? {};
|
|
16303
|
+
const requiredGates = evidence.required_gates ?? [];
|
|
16304
|
+
if (requiredGates.length > 0) {
|
|
16305
|
+
const allPassed = requiredGates.every((gate) => gates[gate] != null);
|
|
16306
|
+
if (allPassed) {
|
|
16307
|
+
return "complete";
|
|
16308
|
+
}
|
|
16309
|
+
}
|
|
16310
|
+
if (gates.test_engineer != null) {
|
|
16311
|
+
return "tests_run";
|
|
16312
|
+
}
|
|
16313
|
+
if (gates.reviewer != null) {
|
|
16314
|
+
return "reviewer_run";
|
|
16315
|
+
}
|
|
16316
|
+
if (Object.keys(gates).length > 0) {
|
|
16317
|
+
return "coder_delegated";
|
|
16318
|
+
}
|
|
16319
|
+
return "idle";
|
|
16320
|
+
}
|
|
16321
|
+
async function readPlanFromDisk(directory) {
|
|
16322
|
+
try {
|
|
16323
|
+
const planPath = path5.join(directory, ".swarm", "plan.json");
|
|
16324
|
+
const content = await fs5.readFile(planPath, "utf-8");
|
|
16325
|
+
const parsed = JSON.parse(content);
|
|
16326
|
+
return PlanSchema.parse(parsed);
|
|
16327
|
+
} catch {
|
|
16328
|
+
return null;
|
|
16329
|
+
}
|
|
16330
|
+
}
|
|
16331
|
+
async function readGateEvidenceFromDisk(directory) {
|
|
16332
|
+
const evidenceMap = new Map;
|
|
16333
|
+
try {
|
|
16334
|
+
const evidenceDir = path5.join(directory, ".swarm", "evidence");
|
|
16335
|
+
const entries = await fs5.readdir(evidenceDir, { withFileTypes: true });
|
|
16336
|
+
for (const entry of entries) {
|
|
16337
|
+
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
16338
|
+
continue;
|
|
16339
|
+
}
|
|
16340
|
+
const taskId = entry.name.replace(/\.json$/, "");
|
|
16341
|
+
if (!/^\d+\.\d+(\.\d+)*$/.test(taskId)) {
|
|
16342
|
+
continue;
|
|
16343
|
+
}
|
|
16344
|
+
try {
|
|
16345
|
+
const filePath = path5.join(evidenceDir, entry.name);
|
|
16346
|
+
const content = await fs5.readFile(filePath, "utf-8");
|
|
16347
|
+
const parsed = JSON.parse(content);
|
|
16348
|
+
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|
|
16349
|
+
evidenceMap.set(taskId, parsed);
|
|
16350
|
+
}
|
|
16351
|
+
} catch {}
|
|
16352
|
+
}
|
|
16353
|
+
} catch {}
|
|
16354
|
+
return evidenceMap;
|
|
16355
|
+
}
|
|
16356
|
+
async function buildRehydrationCache(directory) {
|
|
16357
|
+
const planTaskStates = new Map;
|
|
16358
|
+
const plan = await readPlanFromDisk(directory);
|
|
16359
|
+
if (plan) {
|
|
16360
|
+
for (const phase of plan.phases ?? []) {
|
|
16361
|
+
for (const task of phase.tasks ?? []) {
|
|
16362
|
+
planTaskStates.set(task.id, planStatusToWorkflowState(task.status));
|
|
16363
|
+
}
|
|
16364
|
+
}
|
|
16365
|
+
}
|
|
16366
|
+
const evidenceMap = await readGateEvidenceFromDisk(directory);
|
|
16367
|
+
_rehydrationCache = { planTaskStates, evidenceMap };
|
|
16368
|
+
}
|
|
16369
|
+
function applyRehydrationCache(session) {
|
|
16370
|
+
if (!_rehydrationCache) {
|
|
16371
|
+
return;
|
|
16372
|
+
}
|
|
16373
|
+
if (!session.taskWorkflowStates) {
|
|
16374
|
+
session.taskWorkflowStates = new Map;
|
|
16375
|
+
}
|
|
16376
|
+
const { planTaskStates, evidenceMap } = _rehydrationCache;
|
|
16377
|
+
const STATE_ORDER = [
|
|
16378
|
+
"idle",
|
|
16379
|
+
"coder_delegated",
|
|
16380
|
+
"pre_check_passed",
|
|
16381
|
+
"reviewer_run",
|
|
16382
|
+
"tests_run",
|
|
16383
|
+
"complete"
|
|
16384
|
+
];
|
|
16385
|
+
for (const [taskId, planState] of planTaskStates) {
|
|
16386
|
+
const existingState = session.taskWorkflowStates.get(taskId);
|
|
16387
|
+
const evidence = evidenceMap.get(taskId);
|
|
16388
|
+
if (evidence) {
|
|
16389
|
+
const derivedState = evidenceToWorkflowState(evidence);
|
|
16390
|
+
const existingIndex = existingState ? STATE_ORDER.indexOf(existingState) : -1;
|
|
16391
|
+
const derivedIndex = STATE_ORDER.indexOf(derivedState);
|
|
16392
|
+
if (derivedIndex > existingIndex) {
|
|
16393
|
+
session.taskWorkflowStates.set(taskId, derivedState);
|
|
16394
|
+
}
|
|
16395
|
+
} else {
|
|
16396
|
+
const existingIndex = existingState ? STATE_ORDER.indexOf(existingState) : -1;
|
|
16397
|
+
const derivedIndex = STATE_ORDER.indexOf(planState);
|
|
16398
|
+
if (derivedIndex > existingIndex) {
|
|
16399
|
+
session.taskWorkflowStates.set(taskId, planState);
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
}
|
|
16403
|
+
}
|
|
16404
|
+
async function rehydrateSessionFromDisk(directory, session) {
|
|
16405
|
+
await buildRehydrationCache(directory);
|
|
16406
|
+
applyRehydrationCache(session);
|
|
16407
|
+
}
|
|
16408
|
+
function hasActiveTurboMode(sessionID) {
|
|
16409
|
+
if (sessionID) {
|
|
16410
|
+
const session = swarmState.agentSessions.get(sessionID);
|
|
16411
|
+
return session?.turboMode === true;
|
|
16412
|
+
}
|
|
16413
|
+
for (const [_sessionId, session] of swarmState.agentSessions) {
|
|
16414
|
+
if (session.turboMode === true) {
|
|
16415
|
+
return true;
|
|
16416
|
+
}
|
|
16417
|
+
}
|
|
16418
|
+
return false;
|
|
16419
|
+
}
|
|
16420
|
+
function hasActiveFullAuto(sessionID) {
|
|
16421
|
+
if (sessionID) {
|
|
16422
|
+
const session = swarmState.agentSessions.get(sessionID);
|
|
16423
|
+
return session?.fullAutoMode === true;
|
|
16424
|
+
}
|
|
16425
|
+
for (const [_sessionId, session] of swarmState.agentSessions) {
|
|
16426
|
+
if (session.fullAutoMode === true) {
|
|
16427
|
+
return true;
|
|
16428
|
+
}
|
|
16429
|
+
}
|
|
16430
|
+
return false;
|
|
16431
|
+
}
|
|
16432
|
+
var _rehydrationCache = null, swarmState;
|
|
16433
|
+
var init_state = __esm(() => {
|
|
16434
|
+
init_constants();
|
|
16435
|
+
init_plan_schema();
|
|
16436
|
+
init_schema();
|
|
16437
|
+
init_telemetry();
|
|
16438
|
+
swarmState = {
|
|
16439
|
+
activeToolCalls: new Map,
|
|
16440
|
+
toolAggregates: new Map,
|
|
16441
|
+
activeAgent: new Map,
|
|
16442
|
+
delegationChains: new Map,
|
|
16443
|
+
pendingEvents: 0,
|
|
16444
|
+
opencodeClient: null,
|
|
16445
|
+
curatorInitAgentNames: [],
|
|
16446
|
+
curatorPhaseAgentNames: [],
|
|
16447
|
+
lastBudgetPct: 0,
|
|
16448
|
+
agentSessions: new Map,
|
|
16449
|
+
pendingRehydrations: new Set,
|
|
16450
|
+
fullAutoEnabledInConfig: false
|
|
15877
16451
|
};
|
|
15878
16452
|
});
|
|
15879
16453
|
|
|
@@ -37983,13 +38557,13 @@ __export(exports_review_receipt, {
|
|
|
37983
38557
|
buildApprovedReceipt: () => buildApprovedReceipt
|
|
37984
38558
|
});
|
|
37985
38559
|
import * as crypto5 from "crypto";
|
|
37986
|
-
import * as
|
|
37987
|
-
import * as
|
|
38560
|
+
import * as fs31 from "fs";
|
|
38561
|
+
import * as path41 from "path";
|
|
37988
38562
|
function resolveReceiptsDir(directory) {
|
|
37989
|
-
return
|
|
38563
|
+
return path41.join(directory, ".swarm", "review-receipts");
|
|
37990
38564
|
}
|
|
37991
38565
|
function resolveReceiptIndexPath(directory) {
|
|
37992
|
-
return
|
|
38566
|
+
return path41.join(resolveReceiptsDir(directory), "index.json");
|
|
37993
38567
|
}
|
|
37994
38568
|
function buildReceiptFilename(id, date9) {
|
|
37995
38569
|
const dateStr = date9.toISOString().slice(0, 10);
|
|
@@ -38012,11 +38586,11 @@ function isScopeStale(receipt, currentContent) {
|
|
|
38012
38586
|
}
|
|
38013
38587
|
async function readReceiptIndex(directory) {
|
|
38014
38588
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
38015
|
-
if (!
|
|
38589
|
+
if (!fs31.existsSync(indexPath)) {
|
|
38016
38590
|
return { schema_version: 1, entries: [] };
|
|
38017
38591
|
}
|
|
38018
38592
|
try {
|
|
38019
|
-
const content = await
|
|
38593
|
+
const content = await fs31.promises.readFile(indexPath, "utf-8");
|
|
38020
38594
|
const parsed = JSON.parse(content);
|
|
38021
38595
|
if (parsed.schema_version !== 1 || !Array.isArray(parsed.entries)) {
|
|
38022
38596
|
return { schema_version: 1, entries: [] };
|
|
@@ -38028,21 +38602,21 @@ async function readReceiptIndex(directory) {
|
|
|
38028
38602
|
}
|
|
38029
38603
|
async function writeReceiptIndex(directory, index) {
|
|
38030
38604
|
const indexPath = resolveReceiptIndexPath(directory);
|
|
38031
|
-
const dir =
|
|
38032
|
-
await
|
|
38605
|
+
const dir = path41.dirname(indexPath);
|
|
38606
|
+
await fs31.promises.mkdir(dir, { recursive: true });
|
|
38033
38607
|
const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
38034
|
-
await
|
|
38035
|
-
|
|
38608
|
+
await fs31.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
|
|
38609
|
+
fs31.renameSync(tmpPath, indexPath);
|
|
38036
38610
|
}
|
|
38037
38611
|
async function persistReviewReceipt(directory, receipt) {
|
|
38038
38612
|
const receiptsDir = resolveReceiptsDir(directory);
|
|
38039
|
-
await
|
|
38613
|
+
await fs31.promises.mkdir(receiptsDir, { recursive: true });
|
|
38040
38614
|
const now = new Date(receipt.reviewed_at);
|
|
38041
38615
|
const filename = buildReceiptFilename(receipt.id, now);
|
|
38042
|
-
const receiptPath =
|
|
38616
|
+
const receiptPath = path41.join(receiptsDir, filename);
|
|
38043
38617
|
const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
38044
|
-
await
|
|
38045
|
-
|
|
38618
|
+
await fs31.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
|
|
38619
|
+
fs31.renameSync(tmpPath, receiptPath);
|
|
38046
38620
|
const index = await readReceiptIndex(directory);
|
|
38047
38621
|
const entry = {
|
|
38048
38622
|
id: receipt.id,
|
|
@@ -38061,9 +38635,9 @@ async function readReceiptById(directory, receiptId) {
|
|
|
38061
38635
|
const entry = index.entries.find((e) => e.id === receiptId);
|
|
38062
38636
|
if (!entry)
|
|
38063
38637
|
return null;
|
|
38064
|
-
const receiptPath =
|
|
38638
|
+
const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
|
|
38065
38639
|
try {
|
|
38066
|
-
const content = await
|
|
38640
|
+
const content = await fs31.promises.readFile(receiptPath, "utf-8");
|
|
38067
38641
|
return JSON.parse(content);
|
|
38068
38642
|
} catch {
|
|
38069
38643
|
return null;
|
|
@@ -38074,9 +38648,9 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
|
|
|
38074
38648
|
const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
38075
38649
|
const receipts = [];
|
|
38076
38650
|
for (const entry of matching) {
|
|
38077
|
-
const receiptPath =
|
|
38651
|
+
const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
|
|
38078
38652
|
try {
|
|
38079
|
-
const content = await
|
|
38653
|
+
const content = await fs31.promises.readFile(receiptPath, "utf-8");
|
|
38080
38654
|
receipts.push(JSON.parse(content));
|
|
38081
38655
|
} catch {}
|
|
38082
38656
|
}
|
|
@@ -38087,9 +38661,9 @@ async function readAllReceipts(directory) {
|
|
|
38087
38661
|
const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
|
|
38088
38662
|
const receipts = [];
|
|
38089
38663
|
for (const entry of sorted) {
|
|
38090
|
-
const receiptPath =
|
|
38664
|
+
const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
|
|
38091
38665
|
try {
|
|
38092
|
-
const content = await
|
|
38666
|
+
const content = await fs31.promises.readFile(receiptPath, "utf-8");
|
|
38093
38667
|
receipts.push(JSON.parse(content));
|
|
38094
38668
|
} catch {}
|
|
38095
38669
|
}
|
|
@@ -38221,15 +38795,15 @@ __export(exports_doc_scan, {
|
|
|
38221
38795
|
doc_extract: () => doc_extract
|
|
38222
38796
|
});
|
|
38223
38797
|
import * as crypto6 from "crypto";
|
|
38224
|
-
import * as
|
|
38798
|
+
import * as fs34 from "fs";
|
|
38225
38799
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
38226
|
-
import * as
|
|
38800
|
+
import * as path45 from "path";
|
|
38227
38801
|
function normalizeSeparators(filePath) {
|
|
38228
38802
|
return filePath.replace(/\\/g, "/");
|
|
38229
38803
|
}
|
|
38230
38804
|
function matchesDocPattern(filePath, patterns) {
|
|
38231
38805
|
const normalizedPath = normalizeSeparators(filePath);
|
|
38232
|
-
const basename6 =
|
|
38806
|
+
const basename6 = path45.basename(filePath);
|
|
38233
38807
|
for (const pattern of patterns) {
|
|
38234
38808
|
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
38235
38809
|
if (basename6 === pattern) {
|
|
@@ -38285,7 +38859,7 @@ function stripMarkdown(text) {
|
|
|
38285
38859
|
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
38286
38860
|
}
|
|
38287
38861
|
async function scanDocIndex(directory) {
|
|
38288
|
-
const manifestPath =
|
|
38862
|
+
const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
|
|
38289
38863
|
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
38290
38864
|
const extraPatterns = [
|
|
38291
38865
|
"ARCHITECTURE.md",
|
|
@@ -38302,8 +38876,8 @@ async function scanDocIndex(directory) {
|
|
|
38302
38876
|
let cacheValid = true;
|
|
38303
38877
|
for (const file3 of existingManifest.files) {
|
|
38304
38878
|
try {
|
|
38305
|
-
const fullPath =
|
|
38306
|
-
const stat2 =
|
|
38879
|
+
const fullPath = path45.join(directory, file3.path);
|
|
38880
|
+
const stat2 = fs34.statSync(fullPath);
|
|
38307
38881
|
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
38308
38882
|
cacheValid = false;
|
|
38309
38883
|
break;
|
|
@@ -38321,7 +38895,7 @@ async function scanDocIndex(directory) {
|
|
|
38321
38895
|
const discoveredFiles = [];
|
|
38322
38896
|
let rawEntries;
|
|
38323
38897
|
try {
|
|
38324
|
-
rawEntries =
|
|
38898
|
+
rawEntries = fs34.readdirSync(directory, { recursive: true });
|
|
38325
38899
|
} catch {
|
|
38326
38900
|
const manifest2 = {
|
|
38327
38901
|
schema_version: 1,
|
|
@@ -38332,10 +38906,10 @@ async function scanDocIndex(directory) {
|
|
|
38332
38906
|
}
|
|
38333
38907
|
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
38334
38908
|
for (const entry of entries) {
|
|
38335
|
-
const fullPath =
|
|
38909
|
+
const fullPath = path45.join(directory, entry);
|
|
38336
38910
|
let stat2;
|
|
38337
38911
|
try {
|
|
38338
|
-
stat2 =
|
|
38912
|
+
stat2 = fs34.statSync(fullPath);
|
|
38339
38913
|
} catch {
|
|
38340
38914
|
continue;
|
|
38341
38915
|
}
|
|
@@ -38364,11 +38938,11 @@ async function scanDocIndex(directory) {
|
|
|
38364
38938
|
}
|
|
38365
38939
|
let content;
|
|
38366
38940
|
try {
|
|
38367
|
-
content =
|
|
38941
|
+
content = fs34.readFileSync(fullPath, "utf-8");
|
|
38368
38942
|
} catch {
|
|
38369
38943
|
continue;
|
|
38370
38944
|
}
|
|
38371
|
-
const { title, summary } = extractTitleAndSummary(content,
|
|
38945
|
+
const { title, summary } = extractTitleAndSummary(content, path45.basename(entry));
|
|
38372
38946
|
const lineCount = content.split(`
|
|
38373
38947
|
`).length;
|
|
38374
38948
|
discoveredFiles.push({
|
|
@@ -38394,7 +38968,7 @@ async function scanDocIndex(directory) {
|
|
|
38394
38968
|
files: discoveredFiles
|
|
38395
38969
|
};
|
|
38396
38970
|
try {
|
|
38397
|
-
await mkdir6(
|
|
38971
|
+
await mkdir6(path45.dirname(manifestPath), { recursive: true });
|
|
38398
38972
|
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
38399
38973
|
} catch {}
|
|
38400
38974
|
return { manifest, cached: false };
|
|
@@ -38433,7 +39007,7 @@ function extractConstraintsFromContent(content) {
|
|
|
38433
39007
|
return constraints;
|
|
38434
39008
|
}
|
|
38435
39009
|
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
38436
|
-
const manifestPath =
|
|
39010
|
+
const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
|
|
38437
39011
|
let manifest;
|
|
38438
39012
|
try {
|
|
38439
39013
|
const content = await readFile6(manifestPath, "utf-8");
|
|
@@ -38459,7 +39033,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38459
39033
|
}
|
|
38460
39034
|
let fullContent;
|
|
38461
39035
|
try {
|
|
38462
|
-
fullContent = await readFile6(
|
|
39036
|
+
fullContent = await readFile6(path45.join(directory, docFile.path), "utf-8");
|
|
38463
39037
|
} catch {
|
|
38464
39038
|
skippedCount++;
|
|
38465
39039
|
continue;
|
|
@@ -38482,7 +39056,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
|
38482
39056
|
tier: "swarm",
|
|
38483
39057
|
lesson: constraint,
|
|
38484
39058
|
category: "architecture",
|
|
38485
|
-
tags: ["doc-scan",
|
|
39059
|
+
tags: ["doc-scan", path45.basename(docFile.path)],
|
|
38486
39060
|
scope: "global",
|
|
38487
39061
|
confidence: 0.5,
|
|
38488
39062
|
status: "candidate",
|
|
@@ -38555,9 +39129,9 @@ var init_doc_scan = __esm(() => {
|
|
|
38555
39129
|
}
|
|
38556
39130
|
} catch {}
|
|
38557
39131
|
if (force) {
|
|
38558
|
-
const manifestPath =
|
|
39132
|
+
const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
|
|
38559
39133
|
try {
|
|
38560
|
-
|
|
39134
|
+
fs34.unlinkSync(manifestPath);
|
|
38561
39135
|
} catch {}
|
|
38562
39136
|
}
|
|
38563
39137
|
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
@@ -38609,11 +39183,11 @@ __export(exports_curator_drift, {
|
|
|
38609
39183
|
readPriorDriftReports: () => readPriorDriftReports,
|
|
38610
39184
|
buildDriftInjectionText: () => buildDriftInjectionText
|
|
38611
39185
|
});
|
|
38612
|
-
import * as
|
|
38613
|
-
import * as
|
|
39186
|
+
import * as fs37 from "fs";
|
|
39187
|
+
import * as path48 from "path";
|
|
38614
39188
|
async function readPriorDriftReports(directory) {
|
|
38615
|
-
const swarmDir =
|
|
38616
|
-
const entries = await
|
|
39189
|
+
const swarmDir = path48.join(directory, ".swarm");
|
|
39190
|
+
const entries = await fs37.promises.readdir(swarmDir).catch(() => null);
|
|
38617
39191
|
if (entries === null)
|
|
38618
39192
|
return [];
|
|
38619
39193
|
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
@@ -38639,10 +39213,10 @@ async function readPriorDriftReports(directory) {
|
|
|
38639
39213
|
async function writeDriftReport(directory, report) {
|
|
38640
39214
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
38641
39215
|
const filePath = validateSwarmPath(directory, filename);
|
|
38642
|
-
const swarmDir =
|
|
38643
|
-
await
|
|
39216
|
+
const swarmDir = path48.dirname(filePath);
|
|
39217
|
+
await fs37.promises.mkdir(swarmDir, { recursive: true });
|
|
38644
39218
|
try {
|
|
38645
|
-
await
|
|
39219
|
+
await fs37.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
38646
39220
|
} catch (err2) {
|
|
38647
39221
|
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
38648
39222
|
}
|
|
@@ -40209,8 +40783,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40209
40783
|
var moduleRtn;
|
|
40210
40784
|
var Module = moduleArg;
|
|
40211
40785
|
var readyPromiseResolve, readyPromiseReject;
|
|
40212
|
-
var readyPromise = new Promise((
|
|
40213
|
-
readyPromiseResolve =
|
|
40786
|
+
var readyPromise = new Promise((resolve21, reject) => {
|
|
40787
|
+
readyPromiseResolve = resolve21;
|
|
40214
40788
|
readyPromiseReject = reject;
|
|
40215
40789
|
});
|
|
40216
40790
|
var ENVIRONMENT_IS_WEB = typeof window == "object";
|
|
@@ -40232,11 +40806,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40232
40806
|
throw toThrow;
|
|
40233
40807
|
}, "quit_");
|
|
40234
40808
|
var scriptDirectory = "";
|
|
40235
|
-
function locateFile(
|
|
40809
|
+
function locateFile(path58) {
|
|
40236
40810
|
if (Module["locateFile"]) {
|
|
40237
|
-
return Module["locateFile"](
|
|
40811
|
+
return Module["locateFile"](path58, scriptDirectory);
|
|
40238
40812
|
}
|
|
40239
|
-
return scriptDirectory +
|
|
40813
|
+
return scriptDirectory + path58;
|
|
40240
40814
|
}
|
|
40241
40815
|
__name(locateFile, "locateFile");
|
|
40242
40816
|
var readAsync, readBinary;
|
|
@@ -40290,13 +40864,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40290
40864
|
}
|
|
40291
40865
|
readAsync = /* @__PURE__ */ __name(async (url3) => {
|
|
40292
40866
|
if (isFileURI(url3)) {
|
|
40293
|
-
return new Promise((
|
|
40867
|
+
return new Promise((resolve21, reject) => {
|
|
40294
40868
|
var xhr = new XMLHttpRequest;
|
|
40295
40869
|
xhr.open("GET", url3, true);
|
|
40296
40870
|
xhr.responseType = "arraybuffer";
|
|
40297
40871
|
xhr.onload = () => {
|
|
40298
40872
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
40299
|
-
|
|
40873
|
+
resolve21(xhr.response);
|
|
40300
40874
|
return;
|
|
40301
40875
|
}
|
|
40302
40876
|
reject(xhr.status);
|
|
@@ -40516,10 +41090,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
40516
41090
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
40517
41091
|
var info2 = getWasmImports();
|
|
40518
41092
|
if (Module["instantiateWasm"]) {
|
|
40519
|
-
return new Promise((
|
|
41093
|
+
return new Promise((resolve21, reject) => {
|
|
40520
41094
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
40521
41095
|
receiveInstance(mod, inst);
|
|
40522
|
-
|
|
41096
|
+
resolve21(mod.exports);
|
|
40523
41097
|
});
|
|
40524
41098
|
});
|
|
40525
41099
|
}
|
|
@@ -41985,13 +42559,13 @@ __export(exports_runtime, {
|
|
|
41985
42559
|
getInitializedLanguages: () => getInitializedLanguages,
|
|
41986
42560
|
clearParserCache: () => clearParserCache
|
|
41987
42561
|
});
|
|
41988
|
-
import * as
|
|
42562
|
+
import * as path58 from "path";
|
|
41989
42563
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41990
42564
|
async function initTreeSitter() {
|
|
41991
42565
|
if (treeSitterInitialized) {
|
|
41992
42566
|
return;
|
|
41993
42567
|
}
|
|
41994
|
-
const thisDir =
|
|
42568
|
+
const thisDir = path58.dirname(fileURLToPath2(import.meta.url));
|
|
41995
42569
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
41996
42570
|
if (isSource) {
|
|
41997
42571
|
await Parser.init();
|
|
@@ -41999,7 +42573,7 @@ async function initTreeSitter() {
|
|
|
41999
42573
|
const grammarsDir = getGrammarsDirAbsolute();
|
|
42000
42574
|
await Parser.init({
|
|
42001
42575
|
locateFile(scriptName) {
|
|
42002
|
-
return
|
|
42576
|
+
return path58.join(grammarsDir, scriptName);
|
|
42003
42577
|
}
|
|
42004
42578
|
});
|
|
42005
42579
|
}
|
|
@@ -42020,9 +42594,9 @@ function getWasmFileName(languageId) {
|
|
|
42020
42594
|
return `tree-sitter-${sanitized}.wasm`;
|
|
42021
42595
|
}
|
|
42022
42596
|
function getGrammarsDirAbsolute() {
|
|
42023
|
-
const thisDir =
|
|
42597
|
+
const thisDir = path58.dirname(fileURLToPath2(import.meta.url));
|
|
42024
42598
|
const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
|
|
42025
|
-
return isSource ?
|
|
42599
|
+
return isSource ? path58.join(thisDir, "grammars") : path58.join(thisDir, "lang", "grammars");
|
|
42026
42600
|
}
|
|
42027
42601
|
async function loadGrammar(languageId) {
|
|
42028
42602
|
if (typeof languageId !== "string" || languageId.length > 100) {
|
|
@@ -42038,9 +42612,9 @@ async function loadGrammar(languageId) {
|
|
|
42038
42612
|
await initTreeSitter();
|
|
42039
42613
|
const parser = new Parser;
|
|
42040
42614
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
42041
|
-
const wasmPath =
|
|
42042
|
-
const { existsSync:
|
|
42043
|
-
if (!
|
|
42615
|
+
const wasmPath = path58.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
42616
|
+
const { existsSync: existsSync36 } = await import("fs");
|
|
42617
|
+
if (!existsSync36(wasmPath)) {
|
|
42044
42618
|
throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
42045
42619
|
Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
|
|
42046
42620
|
}
|
|
@@ -42073,9 +42647,9 @@ async function isGrammarAvailable(languageId) {
|
|
|
42073
42647
|
}
|
|
42074
42648
|
try {
|
|
42075
42649
|
const wasmFileName = getWasmFileName(normalizedId);
|
|
42076
|
-
const wasmPath =
|
|
42077
|
-
const { statSync:
|
|
42078
|
-
|
|
42650
|
+
const wasmPath = path58.join(getGrammarsDirAbsolute(), wasmFileName);
|
|
42651
|
+
const { statSync: statSync15 } = await import("fs");
|
|
42652
|
+
statSync15(wasmPath);
|
|
42079
42653
|
return true;
|
|
42080
42654
|
} catch {
|
|
42081
42655
|
return false;
|
|
@@ -42260,467 +42834,7 @@ async function handleArchiveCommand(directory, args2) {
|
|
|
42260
42834
|
|
|
42261
42835
|
// src/commands/benchmark.ts
|
|
42262
42836
|
init_manager();
|
|
42263
|
-
|
|
42264
|
-
// src/state.ts
|
|
42265
|
-
init_constants();
|
|
42266
|
-
init_plan_schema();
|
|
42267
|
-
init_schema();
|
|
42268
|
-
init_telemetry();
|
|
42269
|
-
import * as fs5 from "fs/promises";
|
|
42270
|
-
import * as path5 from "path";
|
|
42271
|
-
var _rehydrationCache = null;
|
|
42272
|
-
var swarmState = {
|
|
42273
|
-
activeToolCalls: new Map,
|
|
42274
|
-
toolAggregates: new Map,
|
|
42275
|
-
activeAgent: new Map,
|
|
42276
|
-
delegationChains: new Map,
|
|
42277
|
-
pendingEvents: 0,
|
|
42278
|
-
opencodeClient: null,
|
|
42279
|
-
curatorInitAgentNames: [],
|
|
42280
|
-
curatorPhaseAgentNames: [],
|
|
42281
|
-
lastBudgetPct: 0,
|
|
42282
|
-
agentSessions: new Map,
|
|
42283
|
-
pendingRehydrations: new Set
|
|
42284
|
-
};
|
|
42285
|
-
function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, directory) {
|
|
42286
|
-
const now = Date.now();
|
|
42287
|
-
const staleIds = [];
|
|
42288
|
-
for (const [id, session] of swarmState.agentSessions) {
|
|
42289
|
-
if (now - session.lastToolCallTime > staleDurationMs) {
|
|
42290
|
-
staleIds.push(id);
|
|
42291
|
-
}
|
|
42292
|
-
}
|
|
42293
|
-
for (const id of staleIds) {
|
|
42294
|
-
swarmState.agentSessions.delete(id);
|
|
42295
|
-
}
|
|
42296
|
-
const sessionState = {
|
|
42297
|
-
agentName,
|
|
42298
|
-
lastToolCallTime: now,
|
|
42299
|
-
lastAgentEventTime: now,
|
|
42300
|
-
delegationActive: false,
|
|
42301
|
-
activeInvocationId: 0,
|
|
42302
|
-
lastInvocationIdByAgent: {},
|
|
42303
|
-
windows: {},
|
|
42304
|
-
lastCompactionHint: 0,
|
|
42305
|
-
architectWriteCount: 0,
|
|
42306
|
-
lastCoderDelegationTaskId: null,
|
|
42307
|
-
currentTaskId: null,
|
|
42308
|
-
gateLog: new Map,
|
|
42309
|
-
reviewerCallCount: new Map,
|
|
42310
|
-
lastGateFailure: null,
|
|
42311
|
-
partialGateWarningsIssuedForTask: new Set,
|
|
42312
|
-
selfFixAttempted: false,
|
|
42313
|
-
selfCodingWarnedAtCount: 0,
|
|
42314
|
-
catastrophicPhaseWarnings: new Set,
|
|
42315
|
-
lastPhaseCompleteTimestamp: 0,
|
|
42316
|
-
lastPhaseCompletePhase: 0,
|
|
42317
|
-
phaseAgentsDispatched: new Set,
|
|
42318
|
-
lastCompletedPhaseAgentsDispatched: new Set,
|
|
42319
|
-
qaSkipCount: 0,
|
|
42320
|
-
qaSkipTaskIds: [],
|
|
42321
|
-
taskWorkflowStates: new Map,
|
|
42322
|
-
lastGateOutcome: null,
|
|
42323
|
-
declaredCoderScope: null,
|
|
42324
|
-
lastScopeViolation: null,
|
|
42325
|
-
scopeViolationDetected: false,
|
|
42326
|
-
modifiedFilesThisCoderTask: [],
|
|
42327
|
-
turboMode: false,
|
|
42328
|
-
model_fallback_index: 0,
|
|
42329
|
-
modelFallbackExhausted: false,
|
|
42330
|
-
coderRevisions: 0,
|
|
42331
|
-
revisionLimitHit: false,
|
|
42332
|
-
loopDetectionWindow: [],
|
|
42333
|
-
pendingAdvisoryMessages: [],
|
|
42334
|
-
sessionRehydratedAt: 0
|
|
42335
|
-
};
|
|
42336
|
-
swarmState.agentSessions.set(sessionId, sessionState);
|
|
42337
|
-
telemetry.sessionStarted(sessionId, agentName);
|
|
42338
|
-
swarmState.activeAgent.set(sessionId, agentName);
|
|
42339
|
-
applyRehydrationCache(sessionState);
|
|
42340
|
-
if (directory) {
|
|
42341
|
-
let rehydrationPromise;
|
|
42342
|
-
rehydrationPromise = rehydrateSessionFromDisk(directory, sessionState).catch((err2) => {
|
|
42343
|
-
console.warn("[state] Rehydration failed:", err2 instanceof Error ? err2.message : String(err2));
|
|
42344
|
-
}).finally(() => {
|
|
42345
|
-
swarmState.pendingRehydrations.delete(rehydrationPromise);
|
|
42346
|
-
});
|
|
42347
|
-
swarmState.pendingRehydrations.add(rehydrationPromise);
|
|
42348
|
-
}
|
|
42349
|
-
}
|
|
42350
|
-
function getAgentSession(sessionId) {
|
|
42351
|
-
return swarmState.agentSessions.get(sessionId);
|
|
42352
|
-
}
|
|
42353
|
-
function ensureAgentSession(sessionId, agentName, directory) {
|
|
42354
|
-
const now = Date.now();
|
|
42355
|
-
let session = swarmState.agentSessions.get(sessionId);
|
|
42356
|
-
if (session) {
|
|
42357
|
-
if (agentName && agentName !== session.agentName) {
|
|
42358
|
-
const oldName = session.agentName;
|
|
42359
|
-
session.agentName = agentName;
|
|
42360
|
-
telemetry.agentActivated(sessionId, agentName, oldName);
|
|
42361
|
-
session.delegationActive = false;
|
|
42362
|
-
session.lastAgentEventTime = now;
|
|
42363
|
-
if (!session.windows) {
|
|
42364
|
-
session.activeInvocationId = 0;
|
|
42365
|
-
session.lastInvocationIdByAgent = {};
|
|
42366
|
-
session.windows = {};
|
|
42367
|
-
}
|
|
42368
|
-
}
|
|
42369
|
-
if (!session.windows) {
|
|
42370
|
-
session.activeInvocationId = 0;
|
|
42371
|
-
session.lastInvocationIdByAgent = {};
|
|
42372
|
-
session.windows = {};
|
|
42373
|
-
}
|
|
42374
|
-
if (session.lastCompactionHint === undefined) {
|
|
42375
|
-
session.lastCompactionHint = 0;
|
|
42376
|
-
}
|
|
42377
|
-
if (session.architectWriteCount === undefined) {
|
|
42378
|
-
session.architectWriteCount = 0;
|
|
42379
|
-
}
|
|
42380
|
-
if (session.lastCoderDelegationTaskId === undefined) {
|
|
42381
|
-
session.lastCoderDelegationTaskId = null;
|
|
42382
|
-
}
|
|
42383
|
-
if (session.currentTaskId === undefined) {
|
|
42384
|
-
session.currentTaskId = null;
|
|
42385
|
-
}
|
|
42386
|
-
if (!session.gateLog) {
|
|
42387
|
-
session.gateLog = new Map;
|
|
42388
|
-
}
|
|
42389
|
-
if (!session.reviewerCallCount) {
|
|
42390
|
-
session.reviewerCallCount = new Map;
|
|
42391
|
-
}
|
|
42392
|
-
if (session.lastGateFailure === undefined) {
|
|
42393
|
-
session.lastGateFailure = null;
|
|
42394
|
-
}
|
|
42395
|
-
if (!session.partialGateWarningsIssuedForTask) {
|
|
42396
|
-
session.partialGateWarningsIssuedForTask = new Set;
|
|
42397
|
-
}
|
|
42398
|
-
if (session.selfFixAttempted === undefined) {
|
|
42399
|
-
session.selfFixAttempted = false;
|
|
42400
|
-
}
|
|
42401
|
-
if (session.selfCodingWarnedAtCount === undefined) {
|
|
42402
|
-
session.selfCodingWarnedAtCount = 0;
|
|
42403
|
-
}
|
|
42404
|
-
if (!session.catastrophicPhaseWarnings) {
|
|
42405
|
-
session.catastrophicPhaseWarnings = new Set;
|
|
42406
|
-
}
|
|
42407
|
-
if (session.lastPhaseCompleteTimestamp === undefined) {
|
|
42408
|
-
session.lastPhaseCompleteTimestamp = 0;
|
|
42409
|
-
}
|
|
42410
|
-
if (session.lastPhaseCompletePhase === undefined) {
|
|
42411
|
-
session.lastPhaseCompletePhase = 0;
|
|
42412
|
-
}
|
|
42413
|
-
if (!session.phaseAgentsDispatched) {
|
|
42414
|
-
session.phaseAgentsDispatched = new Set;
|
|
42415
|
-
}
|
|
42416
|
-
if (!session.lastCompletedPhaseAgentsDispatched) {
|
|
42417
|
-
session.lastCompletedPhaseAgentsDispatched = new Set;
|
|
42418
|
-
}
|
|
42419
|
-
if (session.qaSkipCount === undefined) {
|
|
42420
|
-
session.qaSkipCount = 0;
|
|
42421
|
-
}
|
|
42422
|
-
if (!session.qaSkipTaskIds) {
|
|
42423
|
-
session.qaSkipTaskIds = [];
|
|
42424
|
-
}
|
|
42425
|
-
if (!session.taskWorkflowStates) {
|
|
42426
|
-
session.taskWorkflowStates = new Map;
|
|
42427
|
-
}
|
|
42428
|
-
if (session.lastGateOutcome === undefined) {
|
|
42429
|
-
session.lastGateOutcome = null;
|
|
42430
|
-
}
|
|
42431
|
-
if (session.declaredCoderScope === undefined) {
|
|
42432
|
-
session.declaredCoderScope = null;
|
|
42433
|
-
}
|
|
42434
|
-
if (session.lastScopeViolation === undefined) {
|
|
42435
|
-
session.lastScopeViolation = null;
|
|
42436
|
-
}
|
|
42437
|
-
if (session.modifiedFilesThisCoderTask === undefined) {
|
|
42438
|
-
session.modifiedFilesThisCoderTask = [];
|
|
42439
|
-
}
|
|
42440
|
-
if (session.scopeViolationDetected === undefined) {
|
|
42441
|
-
session.scopeViolationDetected = false;
|
|
42442
|
-
}
|
|
42443
|
-
if (session.turboMode === undefined) {
|
|
42444
|
-
session.turboMode = false;
|
|
42445
|
-
}
|
|
42446
|
-
if (session.model_fallback_index === undefined) {
|
|
42447
|
-
session.model_fallback_index = 0;
|
|
42448
|
-
}
|
|
42449
|
-
if (session.modelFallbackExhausted === undefined) {
|
|
42450
|
-
session.modelFallbackExhausted = false;
|
|
42451
|
-
}
|
|
42452
|
-
if (session.loopDetectionWindow === undefined) {
|
|
42453
|
-
session.loopDetectionWindow = [];
|
|
42454
|
-
}
|
|
42455
|
-
if (session.pendingAdvisoryMessages === undefined) {
|
|
42456
|
-
session.pendingAdvisoryMessages = [];
|
|
42457
|
-
}
|
|
42458
|
-
if (session.coderRevisions === undefined) {
|
|
42459
|
-
session.coderRevisions = 0;
|
|
42460
|
-
}
|
|
42461
|
-
if (session.revisionLimitHit === undefined) {
|
|
42462
|
-
session.revisionLimitHit = false;
|
|
42463
|
-
}
|
|
42464
|
-
if (session.sessionRehydratedAt === undefined) {
|
|
42465
|
-
session.sessionRehydratedAt = 0;
|
|
42466
|
-
}
|
|
42467
|
-
session.lastToolCallTime = now;
|
|
42468
|
-
return session;
|
|
42469
|
-
}
|
|
42470
|
-
startAgentSession(sessionId, agentName ?? "unknown", 7200000, directory);
|
|
42471
|
-
session = swarmState.agentSessions.get(sessionId);
|
|
42472
|
-
if (!session) {
|
|
42473
|
-
throw new Error(`Failed to create guardrail session for ${sessionId}`);
|
|
42474
|
-
}
|
|
42475
|
-
return session;
|
|
42476
|
-
}
|
|
42477
|
-
function updateAgentEventTime(sessionId) {
|
|
42478
|
-
const session = swarmState.agentSessions.get(sessionId);
|
|
42479
|
-
if (session) {
|
|
42480
|
-
session.lastAgentEventTime = Date.now();
|
|
42481
|
-
}
|
|
42482
|
-
}
|
|
42483
|
-
function beginInvocation(sessionId, agentName) {
|
|
42484
|
-
const session = swarmState.agentSessions.get(sessionId);
|
|
42485
|
-
if (!session) {
|
|
42486
|
-
throw new Error(`Cannot begin invocation: session ${sessionId} does not exist`);
|
|
42487
|
-
}
|
|
42488
|
-
const stripped = stripKnownSwarmPrefix(agentName);
|
|
42489
|
-
if (stripped === ORCHESTRATOR_NAME) {
|
|
42490
|
-
return null;
|
|
42491
|
-
}
|
|
42492
|
-
const lastId = session.lastInvocationIdByAgent[stripped] || 0;
|
|
42493
|
-
const newId = lastId + 1;
|
|
42494
|
-
session.lastInvocationIdByAgent[stripped] = newId;
|
|
42495
|
-
session.activeInvocationId = newId;
|
|
42496
|
-
const now = Date.now();
|
|
42497
|
-
const window2 = {
|
|
42498
|
-
id: newId,
|
|
42499
|
-
agentName: stripped,
|
|
42500
|
-
startedAtMs: now,
|
|
42501
|
-
toolCalls: 0,
|
|
42502
|
-
consecutiveErrors: 0,
|
|
42503
|
-
hardLimitHit: false,
|
|
42504
|
-
lastSuccessTimeMs: now,
|
|
42505
|
-
recentToolCalls: [],
|
|
42506
|
-
warningIssued: false,
|
|
42507
|
-
warningReason: ""
|
|
42508
|
-
};
|
|
42509
|
-
const key = `${stripped}:${newId}`;
|
|
42510
|
-
session.windows[key] = window2;
|
|
42511
|
-
pruneOldWindows(sessionId, 24 * 60 * 60 * 1000, 50);
|
|
42512
|
-
telemetry.delegationBegin(sessionId, stripped, session.currentTaskId ?? "unknown");
|
|
42513
|
-
return window2;
|
|
42514
|
-
}
|
|
42515
|
-
function getActiveWindow(sessionId) {
|
|
42516
|
-
const session = swarmState.agentSessions.get(sessionId);
|
|
42517
|
-
if (!session || !session.windows) {
|
|
42518
|
-
return;
|
|
42519
|
-
}
|
|
42520
|
-
const stripped = stripKnownSwarmPrefix(session.agentName);
|
|
42521
|
-
const key = `${stripped}:${session.activeInvocationId}`;
|
|
42522
|
-
return session.windows[key];
|
|
42523
|
-
}
|
|
42524
|
-
function pruneOldWindows(sessionId, maxAgeMs = 24 * 60 * 60 * 1000, maxWindows = 50) {
|
|
42525
|
-
const session = swarmState.agentSessions.get(sessionId);
|
|
42526
|
-
if (!session || !session.windows) {
|
|
42527
|
-
return;
|
|
42528
|
-
}
|
|
42529
|
-
const now = Date.now();
|
|
42530
|
-
const entries = Object.entries(session.windows);
|
|
42531
|
-
const validByAge = entries.filter(([_, window2]) => now - window2.startedAtMs < maxAgeMs);
|
|
42532
|
-
const sorted = validByAge.sort((a, b) => b[1].startedAtMs - a[1].startedAtMs);
|
|
42533
|
-
const toKeep = sorted.slice(0, maxWindows);
|
|
42534
|
-
session.windows = Object.fromEntries(toKeep);
|
|
42535
|
-
}
|
|
42536
|
-
function recordPhaseAgentDispatch(sessionId, agentName) {
|
|
42537
|
-
const session = swarmState.agentSessions.get(sessionId);
|
|
42538
|
-
if (!session) {
|
|
42539
|
-
return;
|
|
42540
|
-
}
|
|
42541
|
-
if (!session.phaseAgentsDispatched) {
|
|
42542
|
-
session.phaseAgentsDispatched = new Set;
|
|
42543
|
-
}
|
|
42544
|
-
const normalizedName = stripKnownSwarmPrefix(agentName);
|
|
42545
|
-
session.phaseAgentsDispatched.add(normalizedName);
|
|
42546
|
-
}
|
|
42547
|
-
function isValidTaskId(taskId) {
|
|
42548
|
-
if (taskId === null || taskId === undefined) {
|
|
42549
|
-
return false;
|
|
42550
|
-
}
|
|
42551
|
-
if (typeof taskId !== "string") {
|
|
42552
|
-
return false;
|
|
42553
|
-
}
|
|
42554
|
-
const trimmed = taskId.trim();
|
|
42555
|
-
return trimmed.length > 0;
|
|
42556
|
-
}
|
|
42557
|
-
function advanceTaskState(session, taskId, newState) {
|
|
42558
|
-
if (!isValidTaskId(taskId)) {
|
|
42559
|
-
return;
|
|
42560
|
-
}
|
|
42561
|
-
if (!session || !(session.taskWorkflowStates instanceof Map)) {
|
|
42562
|
-
throw new Error("INVALID_SESSION: session.taskWorkflowStates must be a Map instance");
|
|
42563
|
-
}
|
|
42564
|
-
const STATE_ORDER = [
|
|
42565
|
-
"idle",
|
|
42566
|
-
"coder_delegated",
|
|
42567
|
-
"pre_check_passed",
|
|
42568
|
-
"reviewer_run",
|
|
42569
|
-
"tests_run",
|
|
42570
|
-
"complete"
|
|
42571
|
-
];
|
|
42572
|
-
const current = session.taskWorkflowStates.get(taskId) ?? "idle";
|
|
42573
|
-
const currentIndex = STATE_ORDER.indexOf(current);
|
|
42574
|
-
const newIndex = STATE_ORDER.indexOf(newState);
|
|
42575
|
-
if (newIndex <= currentIndex) {
|
|
42576
|
-
throw new Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} ${current} \u2192 ${newState}`);
|
|
42577
|
-
}
|
|
42578
|
-
if (newState === "complete" && current !== "tests_run") {
|
|
42579
|
-
throw new Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} cannot reach complete from ${current} \u2014 must pass through tests_run first`);
|
|
42580
|
-
}
|
|
42581
|
-
session.taskWorkflowStates.set(taskId, newState);
|
|
42582
|
-
telemetry.taskStateChanged(session.agentName, taskId, newState, current);
|
|
42583
|
-
}
|
|
42584
|
-
function getTaskState(session, taskId) {
|
|
42585
|
-
if (!isValidTaskId(taskId)) {
|
|
42586
|
-
return "idle";
|
|
42587
|
-
}
|
|
42588
|
-
if (!session.taskWorkflowStates) {
|
|
42589
|
-
session.taskWorkflowStates = new Map;
|
|
42590
|
-
}
|
|
42591
|
-
return session.taskWorkflowStates.get(taskId) ?? "idle";
|
|
42592
|
-
}
|
|
42593
|
-
function planStatusToWorkflowState(status) {
|
|
42594
|
-
switch (status) {
|
|
42595
|
-
case "in_progress":
|
|
42596
|
-
return "coder_delegated";
|
|
42597
|
-
case "completed":
|
|
42598
|
-
return "complete";
|
|
42599
|
-
default:
|
|
42600
|
-
return "idle";
|
|
42601
|
-
}
|
|
42602
|
-
}
|
|
42603
|
-
function evidenceToWorkflowState(evidence) {
|
|
42604
|
-
const gates = evidence.gates ?? {};
|
|
42605
|
-
const requiredGates = evidence.required_gates ?? [];
|
|
42606
|
-
if (requiredGates.length > 0) {
|
|
42607
|
-
const allPassed = requiredGates.every((gate) => gates[gate] != null);
|
|
42608
|
-
if (allPassed) {
|
|
42609
|
-
return "complete";
|
|
42610
|
-
}
|
|
42611
|
-
}
|
|
42612
|
-
if (gates.test_engineer != null) {
|
|
42613
|
-
return "tests_run";
|
|
42614
|
-
}
|
|
42615
|
-
if (gates.reviewer != null) {
|
|
42616
|
-
return "reviewer_run";
|
|
42617
|
-
}
|
|
42618
|
-
if (Object.keys(gates).length > 0) {
|
|
42619
|
-
return "coder_delegated";
|
|
42620
|
-
}
|
|
42621
|
-
return "idle";
|
|
42622
|
-
}
|
|
42623
|
-
async function readPlanFromDisk(directory) {
|
|
42624
|
-
try {
|
|
42625
|
-
const planPath = path5.join(directory, ".swarm", "plan.json");
|
|
42626
|
-
const content = await fs5.readFile(planPath, "utf-8");
|
|
42627
|
-
const parsed = JSON.parse(content);
|
|
42628
|
-
return PlanSchema.parse(parsed);
|
|
42629
|
-
} catch {
|
|
42630
|
-
return null;
|
|
42631
|
-
}
|
|
42632
|
-
}
|
|
42633
|
-
async function readGateEvidenceFromDisk(directory) {
|
|
42634
|
-
const evidenceMap = new Map;
|
|
42635
|
-
try {
|
|
42636
|
-
const evidenceDir = path5.join(directory, ".swarm", "evidence");
|
|
42637
|
-
const entries = await fs5.readdir(evidenceDir, { withFileTypes: true });
|
|
42638
|
-
for (const entry of entries) {
|
|
42639
|
-
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
42640
|
-
continue;
|
|
42641
|
-
}
|
|
42642
|
-
const taskId = entry.name.replace(/\.json$/, "");
|
|
42643
|
-
if (!/^\d+\.\d+(\.\d+)*$/.test(taskId)) {
|
|
42644
|
-
continue;
|
|
42645
|
-
}
|
|
42646
|
-
try {
|
|
42647
|
-
const filePath = path5.join(evidenceDir, entry.name);
|
|
42648
|
-
const content = await fs5.readFile(filePath, "utf-8");
|
|
42649
|
-
const parsed = JSON.parse(content);
|
|
42650
|
-
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|
|
42651
|
-
evidenceMap.set(taskId, parsed);
|
|
42652
|
-
}
|
|
42653
|
-
} catch {}
|
|
42654
|
-
}
|
|
42655
|
-
} catch {}
|
|
42656
|
-
return evidenceMap;
|
|
42657
|
-
}
|
|
42658
|
-
async function buildRehydrationCache(directory) {
|
|
42659
|
-
const planTaskStates = new Map;
|
|
42660
|
-
const plan = await readPlanFromDisk(directory);
|
|
42661
|
-
if (plan) {
|
|
42662
|
-
for (const phase of plan.phases ?? []) {
|
|
42663
|
-
for (const task of phase.tasks ?? []) {
|
|
42664
|
-
planTaskStates.set(task.id, planStatusToWorkflowState(task.status));
|
|
42665
|
-
}
|
|
42666
|
-
}
|
|
42667
|
-
}
|
|
42668
|
-
const evidenceMap = await readGateEvidenceFromDisk(directory);
|
|
42669
|
-
_rehydrationCache = { planTaskStates, evidenceMap };
|
|
42670
|
-
}
|
|
42671
|
-
function applyRehydrationCache(session) {
|
|
42672
|
-
if (!_rehydrationCache) {
|
|
42673
|
-
return;
|
|
42674
|
-
}
|
|
42675
|
-
if (!session.taskWorkflowStates) {
|
|
42676
|
-
session.taskWorkflowStates = new Map;
|
|
42677
|
-
}
|
|
42678
|
-
const { planTaskStates, evidenceMap } = _rehydrationCache;
|
|
42679
|
-
const STATE_ORDER = [
|
|
42680
|
-
"idle",
|
|
42681
|
-
"coder_delegated",
|
|
42682
|
-
"pre_check_passed",
|
|
42683
|
-
"reviewer_run",
|
|
42684
|
-
"tests_run",
|
|
42685
|
-
"complete"
|
|
42686
|
-
];
|
|
42687
|
-
for (const [taskId, planState] of planTaskStates) {
|
|
42688
|
-
const existingState = session.taskWorkflowStates.get(taskId);
|
|
42689
|
-
const evidence = evidenceMap.get(taskId);
|
|
42690
|
-
if (evidence) {
|
|
42691
|
-
const derivedState = evidenceToWorkflowState(evidence);
|
|
42692
|
-
const existingIndex = existingState ? STATE_ORDER.indexOf(existingState) : -1;
|
|
42693
|
-
const derivedIndex = STATE_ORDER.indexOf(derivedState);
|
|
42694
|
-
if (derivedIndex > existingIndex) {
|
|
42695
|
-
session.taskWorkflowStates.set(taskId, derivedState);
|
|
42696
|
-
}
|
|
42697
|
-
} else {
|
|
42698
|
-
const existingIndex = existingState ? STATE_ORDER.indexOf(existingState) : -1;
|
|
42699
|
-
const derivedIndex = STATE_ORDER.indexOf(planState);
|
|
42700
|
-
if (derivedIndex > existingIndex) {
|
|
42701
|
-
session.taskWorkflowStates.set(taskId, planState);
|
|
42702
|
-
}
|
|
42703
|
-
}
|
|
42704
|
-
}
|
|
42705
|
-
}
|
|
42706
|
-
async function rehydrateSessionFromDisk(directory, session) {
|
|
42707
|
-
await buildRehydrationCache(directory);
|
|
42708
|
-
applyRehydrationCache(session);
|
|
42709
|
-
}
|
|
42710
|
-
function hasActiveTurboMode(sessionID) {
|
|
42711
|
-
if (sessionID) {
|
|
42712
|
-
const session = swarmState.agentSessions.get(sessionID);
|
|
42713
|
-
return session?.turboMode === true;
|
|
42714
|
-
}
|
|
42715
|
-
for (const [_sessionId, session] of swarmState.agentSessions) {
|
|
42716
|
-
if (session.turboMode === true) {
|
|
42717
|
-
return true;
|
|
42718
|
-
}
|
|
42719
|
-
}
|
|
42720
|
-
return false;
|
|
42721
|
-
}
|
|
42722
|
-
|
|
42723
|
-
// src/commands/benchmark.ts
|
|
42837
|
+
init_state();
|
|
42724
42838
|
init_utils();
|
|
42725
42839
|
var CI = {
|
|
42726
42840
|
review_pass_rate: 70,
|
|
@@ -44098,9 +44212,10 @@ async function writeCheckpoint(directory) {
|
|
|
44098
44212
|
|
|
44099
44213
|
// src/session/snapshot-writer.ts
|
|
44100
44214
|
init_utils2();
|
|
44215
|
+
init_state();
|
|
44216
|
+
init_utils();
|
|
44101
44217
|
import { mkdirSync as mkdirSync5, renameSync as renameSync5 } from "fs";
|
|
44102
44218
|
import * as path13 from "path";
|
|
44103
|
-
init_utils();
|
|
44104
44219
|
var _writeInFlight = Promise.resolve();
|
|
44105
44220
|
function serializeAgentSession(s) {
|
|
44106
44221
|
const gateLog = {};
|
|
@@ -44168,6 +44283,10 @@ function serializeAgentSession(s) {
|
|
|
44168
44283
|
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
44169
44284
|
coderRevisions: s.coderRevisions ?? 0,
|
|
44170
44285
|
revisionLimitHit: s.revisionLimitHit ?? false,
|
|
44286
|
+
fullAutoMode: s.fullAutoMode ?? false,
|
|
44287
|
+
fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
|
|
44288
|
+
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
44289
|
+
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
44171
44290
|
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
44172
44291
|
};
|
|
44173
44292
|
}
|
|
@@ -44208,6 +44327,9 @@ async function flushPendingSnapshot(directory) {
|
|
|
44208
44327
|
await _writeInFlight;
|
|
44209
44328
|
}
|
|
44210
44329
|
|
|
44330
|
+
// src/commands/close.ts
|
|
44331
|
+
init_state();
|
|
44332
|
+
|
|
44211
44333
|
// src/tools/write-retro.ts
|
|
44212
44334
|
init_tool();
|
|
44213
44335
|
init_evidence_schema();
|
|
@@ -47051,6 +47173,38 @@ async function handleExportCommand(directory, _args) {
|
|
|
47051
47173
|
const exportData = await getExportData(directory);
|
|
47052
47174
|
return formatExportMarkdown(exportData);
|
|
47053
47175
|
}
|
|
47176
|
+
// src/commands/full-auto.ts
|
|
47177
|
+
init_state();
|
|
47178
|
+
async function handleFullAutoCommand(_directory, args2, sessionID) {
|
|
47179
|
+
if (!sessionID || sessionID.trim() === "") {
|
|
47180
|
+
return "Error: No active session context. Full-Auto Mode requires an active session. Use /swarm full-auto from within an OpenCode session, or start a session first.";
|
|
47181
|
+
}
|
|
47182
|
+
const session = getAgentSession(sessionID);
|
|
47183
|
+
if (!session) {
|
|
47184
|
+
return "Error: No active session. Full-Auto Mode requires an active session to operate.";
|
|
47185
|
+
}
|
|
47186
|
+
const arg = args2[0]?.toLowerCase();
|
|
47187
|
+
let newFullAutoMode;
|
|
47188
|
+
let feedback;
|
|
47189
|
+
if (arg === "on") {
|
|
47190
|
+
newFullAutoMode = true;
|
|
47191
|
+
feedback = "Full-Auto Mode enabled";
|
|
47192
|
+
} else if (arg === "off") {
|
|
47193
|
+
newFullAutoMode = false;
|
|
47194
|
+
feedback = "Full-Auto Mode disabled";
|
|
47195
|
+
} else {
|
|
47196
|
+
newFullAutoMode = !session.fullAutoMode;
|
|
47197
|
+
feedback = newFullAutoMode ? "Full-Auto Mode enabled" : "Full-Auto Mode disabled";
|
|
47198
|
+
}
|
|
47199
|
+
session.fullAutoMode = newFullAutoMode;
|
|
47200
|
+
if (!newFullAutoMode) {
|
|
47201
|
+
session.fullAutoInteractionCount = 0;
|
|
47202
|
+
session.fullAutoDeadlockCount = 0;
|
|
47203
|
+
session.fullAutoLastQuestionHash = null;
|
|
47204
|
+
}
|
|
47205
|
+
return feedback;
|
|
47206
|
+
}
|
|
47207
|
+
|
|
47054
47208
|
// src/commands/handoff.ts
|
|
47055
47209
|
init_utils2();
|
|
47056
47210
|
import crypto4 from "crypto";
|
|
@@ -47358,6 +47512,7 @@ function formatHandoffMarkdown(data) {
|
|
|
47358
47512
|
}
|
|
47359
47513
|
|
|
47360
47514
|
// src/commands/handoff.ts
|
|
47515
|
+
init_state();
|
|
47361
47516
|
async function handleHandoffCommand(directory, _args) {
|
|
47362
47517
|
const handoffData = await getHandoffData(directory);
|
|
47363
47518
|
const markdown = formatHandoffMarkdown(handoffData);
|
|
@@ -48781,6 +48936,7 @@ async function handleResetCommand(directory, args2) {
|
|
|
48781
48936
|
|
|
48782
48937
|
// src/commands/reset-session.ts
|
|
48783
48938
|
init_utils2();
|
|
48939
|
+
init_state();
|
|
48784
48940
|
import * as fs21 from "fs";
|
|
48785
48941
|
import * as path30 from "path";
|
|
48786
48942
|
async function handleResetSessionCommand(directory, _args) {
|
|
@@ -49429,8 +49585,10 @@ No plan content available. Start by creating a .swarm/plan.md file.
|
|
|
49429
49585
|
// src/services/status-service.ts
|
|
49430
49586
|
init_utils2();
|
|
49431
49587
|
init_manager2();
|
|
49588
|
+
init_state();
|
|
49432
49589
|
|
|
49433
49590
|
// src/services/compaction-service.ts
|
|
49591
|
+
init_state();
|
|
49434
49592
|
import * as fs23 from "fs";
|
|
49435
49593
|
import * as path33 from "path";
|
|
49436
49594
|
function makeInitialState() {
|
|
@@ -49820,6 +49978,7 @@ No active swarm plan found. Nothing to sync.`;
|
|
|
49820
49978
|
}
|
|
49821
49979
|
|
|
49822
49980
|
// src/commands/turbo.ts
|
|
49981
|
+
init_state();
|
|
49823
49982
|
async function handleTurboCommand(_directory, args2, sessionID) {
|
|
49824
49983
|
if (!sessionID || sessionID.trim() === "") {
|
|
49825
49984
|
return "Error: No active session context. Turbo Mode requires an active session. Use /swarm turbo from within an OpenCode session, or start a session first.";
|
|
@@ -50023,6 +50182,10 @@ var COMMAND_REGISTRY = {
|
|
|
50023
50182
|
handler: (ctx) => handleTurboCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
50024
50183
|
description: "Toggle Turbo Mode for the active session [on|off]"
|
|
50025
50184
|
},
|
|
50185
|
+
"full-auto": {
|
|
50186
|
+
handler: (ctx) => handleFullAutoCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
50187
|
+
description: "Toggle Full-Auto Mode for the active session [on|off]"
|
|
50188
|
+
},
|
|
50026
50189
|
"write-retro": {
|
|
50027
50190
|
handler: (ctx) => handleWriteRetroCommand(ctx.directory, ctx.args),
|
|
50028
50191
|
description: "Write a retrospective evidence bundle for a completed phase <json>"
|
|
@@ -50083,8 +50246,6 @@ var ARCHITECT_PROMPT = `You are Architect - orchestrator of a multi-agent swarm.
|
|
|
50083
50246
|
Swarm: {{SWARM_ID}}
|
|
50084
50247
|
Your agents: {{AGENT_PREFIX}}explorer, {{AGENT_PREFIX}}sme, {{AGENT_PREFIX}}coder, {{AGENT_PREFIX}}reviewer, {{AGENT_PREFIX}}test_engineer, {{AGENT_PREFIX}}critic, {{AGENT_PREFIX}}critic_sounding_board, {{AGENT_PREFIX}}docs, {{AGENT_PREFIX}}designer
|
|
50085
50248
|
|
|
50086
|
-
{{TURBO_MODE_BANNER}}
|
|
50087
|
-
|
|
50088
50249
|
## PROJECT CONTEXT
|
|
50089
50250
|
Session-start priming block. Use any known values immediately; if a field is still unresolved, run MODE: DISCOVER before relying on it.
|
|
50090
50251
|
Language: {{PROJECT_LANGUAGE}}
|
|
@@ -51112,29 +51273,6 @@ ${customAppendPrompt}`;
|
|
|
51112
51273
|
prompt = prompt?.replace(/\{\{ADVERSARIAL_TEST_STEP\}\}/g, ` 5m. {{AGENT_PREFIX}}test_engineer - Adversarial tests. FAIL \u2192 coder retry from 5g. Scope: attack vectors only \u2014 malformed inputs, boundary violations, injection attempts.
|
|
51113
51274
|
\u2192 REQUIRED: Print "testengineer-adversarial: [PASS | FAIL \u2014 details]"`)?.replace(/\{\{ADVERSARIAL_TEST_CHECKLIST\}\}/g, " [GATE] test_engineer-adversarial: PASS / FAIL \u2014 value: ___");
|
|
51114
51275
|
}
|
|
51115
|
-
const TURBO_MODE_BANNER = `## \uD83D\uDE80 TURBO MODE ACTIVE
|
|
51116
|
-
|
|
51117
|
-
**Speed optimization enabled for this session.**
|
|
51118
|
-
|
|
51119
|
-
While Turbo Mode is active:
|
|
51120
|
-
- **Stage A gates** (lint, imports, pre_check_batch) are still REQUIRED for ALL tasks
|
|
51121
|
-
- **Tier 3 tasks** (security-sensitive files matching: architect*.ts, delegation*.ts, guardrails*.ts, adversarial*.ts, sanitiz*.ts, auth*, permission*, crypto*, secret*, security) still require FULL review (Stage B)
|
|
51122
|
-
- **Tier 0-2 tasks** can skip Stage B (reviewer, test_engineer) to speed up execution
|
|
51123
|
-
- **Phase completion gates** (completion-verify and drift verification gate) are automatically bypassed \u2014 phase_complete will succeed without drift verification evidence when turbo is active. Note: turbo bypass is session-scoped; one session's turbo does not affect other sessions.
|
|
51124
|
-
|
|
51125
|
-
Classification still determines the pipeline:
|
|
51126
|
-
- TIER 0 (metadata): lint + diff only \u2014 no change
|
|
51127
|
-
- TIER 1 (docs): Stage A + reviewer \u2014 no change
|
|
51128
|
-
- TIER 2 (standard code): Stage A + reviewer + test_engineer \u2014 CAN SKIP Stage B with turboMode
|
|
51129
|
-
- TIER 3 (critical): Stage A + 2x reviewer + 2x test_engineer \u2014 Stage B REQUIRED (no turbo bypass)
|
|
51130
|
-
|
|
51131
|
-
Do NOT skip Stage A gates. Do NOT skip Stage B for TIER 3.
|
|
51132
|
-
`;
|
|
51133
|
-
if (hasActiveTurboMode()) {
|
|
51134
|
-
prompt = prompt?.replace(/\{\{TURBO_MODE_BANNER\}\}/g, TURBO_MODE_BANNER);
|
|
51135
|
-
} else {
|
|
51136
|
-
prompt = prompt?.replace(/\{\{TURBO_MODE_BANNER\}\}/g, "");
|
|
51137
|
-
}
|
|
51138
51276
|
return {
|
|
51139
51277
|
name: "architect",
|
|
51140
51278
|
description: "Central orchestrator of the development pipeline. Analyzes requests, coordinates SME consultation, manages code generation, and triages QA feedback.",
|
|
@@ -51594,6 +51732,90 @@ RULES:
|
|
|
51594
51732
|
- Report the first deviation point, not all downstream consequences
|
|
51595
51733
|
- VERDICT is APPROVED only if ALL tasks are VERIFIED with no DRIFT
|
|
51596
51734
|
`;
|
|
51735
|
+
var AUTONOMOUS_OVERSIGHT_PROMPT = `## AUTONOMOUS OVERSIGHT MODE
|
|
51736
|
+
|
|
51737
|
+
You are the sole quality gate between the architect and production. There is no human reviewer. Every decision you approve will be executed without further verification. Act accordingly.
|
|
51738
|
+
|
|
51739
|
+
## CONSTITUTION
|
|
51740
|
+
|
|
51741
|
+
These rules are absolute. You cannot override, relax, or reinterpret them.
|
|
51742
|
+
|
|
51743
|
+
1. DEFAULT POSTURE IS REJECT. You approve only when you have positive evidence of correctness. Absence of problems is not evidence of quality.
|
|
51744
|
+
2. CROSS-VERIFY EVERYTHING. Do not trust the architect's summary. Read the actual files, evidence, plan, and test results yourself.
|
|
51745
|
+
3. NO RUBBER-STAMPING. If you cannot articulate exactly what you verified and why it's correct, your verdict is REJECT.
|
|
51746
|
+
4. SCOPE CONTAINMENT. If work was done outside the plan scope, REJECT. Scope creep in autonomous mode is a critical failure.
|
|
51747
|
+
5. EVIDENCE OVER CLAIMS. The architect may claim tests pass, reviews succeeded, or gates cleared. Verify the evidence files exist and contain valid data.
|
|
51748
|
+
6. ESCALATE UNCERTAINTY. If you are uncertain about a product/design decision (not a technical one), respond with ESCALATE_TO_HUMAN instead of guessing.
|
|
51749
|
+
7. GATE COMPLETENESS. Every task must have: (a) implementation evidence, (b) review evidence with verdict, (c) test evidence with pass/fail. Missing any = REJECT.
|
|
51750
|
+
8. REGRESSION AWARENESS. If the architect claims a fix, verify it doesn't break something else. Check for test results beyond the changed files.
|
|
51751
|
+
9. DEPENDENCY VIGILANCE. Any new dependency must be verified as a real package. Any phantom dependency = CRITICAL REJECT.
|
|
51752
|
+
10. SECURITY BOUNDARY. Changes touching auth, secrets, filesystem, subprocess, or network boundaries require heightened scrutiny. Missing validation at any trust boundary = REJECT.
|
|
51753
|
+
|
|
51754
|
+
## VERIFICATION PROTOCOL
|
|
51755
|
+
|
|
51756
|
+
For every decision point, execute the relevant protocol:
|
|
51757
|
+
|
|
51758
|
+
### Plan Review
|
|
51759
|
+
1. Read .swarm/plan.md and .swarm/spec.md (if exists)
|
|
51760
|
+
2. For each task: verify it has a clear objective, target file, and acceptance criteria
|
|
51761
|
+
3. Check dependency ordering \u2014 no task should depend on a later task's output
|
|
51762
|
+
4. Check scope containment \u2014 every task maps to a stated requirement
|
|
51763
|
+
5. Flag any task that touches 6+ files or mixes unrelated concerns
|
|
51764
|
+
VERDICT: APPROVED | NEEDS_REVISION | REJECTED
|
|
51765
|
+
|
|
51766
|
+
### Task Completion Review
|
|
51767
|
+
1. Read the evidence bundle for the task
|
|
51768
|
+
2. Verify review evidence exists with a non-rubber-stamp verdict
|
|
51769
|
+
3. Verify test evidence exists with PASS status
|
|
51770
|
+
4. Verify the diff is contained to the stated scope
|
|
51771
|
+
5. Check for unplanned side effects in other files
|
|
51772
|
+
VERDICT: APPROVED | BLOCKED \u2014 [reason]
|
|
51773
|
+
|
|
51774
|
+
### Phase Completion Review
|
|
51775
|
+
1. Verify ALL tasks in the phase are marked completed with evidence
|
|
51776
|
+
2. Verify retrospective evidence exists with lessons learned
|
|
51777
|
+
3. Verify drift check evidence exists (if spec.md present)
|
|
51778
|
+
4. Verify regression sweep results exist
|
|
51779
|
+
5. Cross-reference: do completed tasks match the plan? Any dropped? Any added?
|
|
51780
|
+
6. Check: was the reviewer dispatched at least once this phase?
|
|
51781
|
+
VERDICT: APPROVED | BLOCKED \u2014 [missing items]
|
|
51782
|
+
|
|
51783
|
+
### Question Resolution
|
|
51784
|
+
When the architect asks a question:
|
|
51785
|
+
1. Determine if this is a TECHNICAL question or a PRODUCT/DESIGN question
|
|
51786
|
+
2. TECHNICAL: answer it directly using your knowledge of the codebase, plan, and spec
|
|
51787
|
+
3. PRODUCT/DESIGN: respond with ESCALATE_TO_HUMAN \u2014 you do not make product decisions
|
|
51788
|
+
4. AMBIGUOUS: ask the architect to rephrase with more context before answering
|
|
51789
|
+
VERDICT: ANSWER | ESCALATE_TO_HUMAN | REPHRASE
|
|
51790
|
+
|
|
51791
|
+
## SELF-CRITIQUE
|
|
51792
|
+
|
|
51793
|
+
After generating your initial verdict, check yourself:
|
|
51794
|
+
1. Did you check every item in the protocol, or did you skip steps?
|
|
51795
|
+
2. If APPROVED: argue against yourself. What could go wrong that you didn't check?
|
|
51796
|
+
3. If REJECTED: is the rejection grounded in a specific rule number, or is it vague unease?
|
|
51797
|
+
If the self-critique changes your verdict, update it.
|
|
51798
|
+
|
|
51799
|
+
## ANTI-PATTERNS
|
|
51800
|
+
|
|
51801
|
+
Watch for these architect behaviors \u2014 any detected = immediate REJECT:
|
|
51802
|
+
- Skipping reviewer delegation ("this is a simple change")
|
|
51803
|
+
- Batching multiple tasks into one coder call
|
|
51804
|
+
- Marking tasks complete without evidence
|
|
51805
|
+
- Relaxing test requirements ("tests are flaky, skipping")
|
|
51806
|
+
- Scope expansion ("while we're here, let's also...")
|
|
51807
|
+
- Self-approving ("I verified this myself")
|
|
51808
|
+
- Pressure language ("we need to move fast", "this is blocking")
|
|
51809
|
+
|
|
51810
|
+
## OUTPUT FORMAT
|
|
51811
|
+
|
|
51812
|
+
Every response MUST use this structure:
|
|
51813
|
+
|
|
51814
|
+
VERDICT: APPROVED | NEEDS_REVISION | REJECTED | BLOCKED | ANSWER | ESCALATE_TO_HUMAN | REPHRASE
|
|
51815
|
+
REASONING: [2-4 sentences \u2014 what you verified and why]
|
|
51816
|
+
EVIDENCE_CHECKED: [list of files/artifacts you read]
|
|
51817
|
+
ANTI_PATTERNS_DETECTED: [list or "none"]
|
|
51818
|
+
ESCALATION_NEEDED: YES | NO`;
|
|
51597
51819
|
function createCriticAgent(model, customPrompt, customAppendPrompt, role = "plan_critic") {
|
|
51598
51820
|
let prompt;
|
|
51599
51821
|
if (customPrompt) {
|
|
@@ -51634,6 +51856,25 @@ ${customAppendPrompt}` : rolePrompt;
|
|
|
51634
51856
|
}
|
|
51635
51857
|
};
|
|
51636
51858
|
}
|
|
51859
|
+
function createCriticAutonomousOversightAgent(model, customAppendPrompt) {
|
|
51860
|
+
const prompt = customAppendPrompt ? `${AUTONOMOUS_OVERSIGHT_PROMPT}
|
|
51861
|
+
|
|
51862
|
+
${customAppendPrompt}` : AUTONOMOUS_OVERSIGHT_PROMPT;
|
|
51863
|
+
return {
|
|
51864
|
+
name: "critic_oversight",
|
|
51865
|
+
description: "Critic in AUTONOMOUS OVERSIGHT mode \u2014 sole quality gate in full-auto.",
|
|
51866
|
+
config: {
|
|
51867
|
+
model,
|
|
51868
|
+
temperature: 0.1,
|
|
51869
|
+
prompt,
|
|
51870
|
+
tools: {
|
|
51871
|
+
write: false,
|
|
51872
|
+
edit: false,
|
|
51873
|
+
patch: false
|
|
51874
|
+
}
|
|
51875
|
+
}
|
|
51876
|
+
};
|
|
51877
|
+
}
|
|
51637
51878
|
|
|
51638
51879
|
// src/agents/curator-agent.ts
|
|
51639
51880
|
var ROLE_CONFIG = {
|
|
@@ -52624,6 +52865,11 @@ If you call @coder instead of @${swarmId}_coder, the call will FAIL or go to the
|
|
|
52624
52865
|
critic.name = prefixName("critic_drift_verifier");
|
|
52625
52866
|
agents.push(applyOverrides(critic, swarmAgents, swarmPrefix));
|
|
52626
52867
|
}
|
|
52868
|
+
if (!isAgentDisabled("critic_oversight", swarmAgents, swarmPrefix)) {
|
|
52869
|
+
const critic = createCriticAutonomousOversightAgent(swarmAgents?.critic_oversight?.model ?? getModel("critic"));
|
|
52870
|
+
critic.name = prefixName("critic_oversight");
|
|
52871
|
+
agents.push(applyOverrides(critic, swarmAgents, swarmPrefix));
|
|
52872
|
+
}
|
|
52627
52873
|
if (!isAgentDisabled("curator_init", swarmAgents, swarmPrefix)) {
|
|
52628
52874
|
const curatorInitPrompts = getPrompts("curator_init");
|
|
52629
52875
|
const curatorInit = createCuratorAgent(swarmAgents?.curator_init?.model ?? getModel("explorer"), curatorInitPrompts.prompt, curatorInitPrompts.appendPrompt, "curator_init");
|
|
@@ -53065,10 +53311,11 @@ init_constants();
|
|
|
53065
53311
|
init_schema();
|
|
53066
53312
|
|
|
53067
53313
|
// src/hooks/agent-activity.ts
|
|
53068
|
-
|
|
53069
|
-
import * as nodePath2 from "path";
|
|
53314
|
+
init_state();
|
|
53070
53315
|
init_utils();
|
|
53071
53316
|
init_utils2();
|
|
53317
|
+
import { renameSync as renameSync9, unlinkSync as unlinkSync4 } from "fs";
|
|
53318
|
+
import * as nodePath2 from "path";
|
|
53072
53319
|
function createAgentActivityHooks(config3, directory) {
|
|
53073
53320
|
if (config3.hooks?.agent_activity === false) {
|
|
53074
53321
|
return {
|
|
@@ -53722,6 +53969,7 @@ function maskToolOutput(msg, _threshold) {
|
|
|
53722
53969
|
return freedTokens;
|
|
53723
53970
|
}
|
|
53724
53971
|
// src/hooks/curator-llm-factory.ts
|
|
53972
|
+
init_state();
|
|
53725
53973
|
function resolveCuratorAgentName(mode, sessionId) {
|
|
53726
53974
|
const suffix = mode === "init" ? "curator_init" : "curator_phase";
|
|
53727
53975
|
const registeredNames = mode === "init" ? swarmState.curatorInitAgentNames : swarmState.curatorPhaseAgentNames;
|
|
@@ -53881,6 +54129,7 @@ function shouldParallelizeReview(routing) {
|
|
|
53881
54129
|
}
|
|
53882
54130
|
|
|
53883
54131
|
// src/hooks/delegation-gate.ts
|
|
54132
|
+
init_state();
|
|
53884
54133
|
init_telemetry();
|
|
53885
54134
|
|
|
53886
54135
|
// src/hooks/guardrails.ts
|
|
@@ -53949,10 +54198,12 @@ function classifyFile(filePath) {
|
|
|
53949
54198
|
|
|
53950
54199
|
// src/hooks/guardrails.ts
|
|
53951
54200
|
init_manager2();
|
|
54201
|
+
init_state();
|
|
53952
54202
|
init_telemetry();
|
|
53953
54203
|
init_utils();
|
|
53954
54204
|
|
|
53955
54205
|
// src/hooks/loop-detector.ts
|
|
54206
|
+
init_state();
|
|
53956
54207
|
function hashDelegation(toolName, args2) {
|
|
53957
54208
|
const targetAgent = typeof args2?.subagent_type === "string" ? args2.subagent_type : "unknown";
|
|
53958
54209
|
const firstArgKey = args2 != null ? Object.keys(args2)[0] ?? "noargs" : "noargs";
|
|
@@ -55797,6 +56048,7 @@ function createDelegationSanitizerHook(directory) {
|
|
|
55797
56048
|
// src/hooks/delegation-tracker.ts
|
|
55798
56049
|
init_constants();
|
|
55799
56050
|
init_schema();
|
|
56051
|
+
init_state();
|
|
55800
56052
|
function createDelegationTrackerHook(config3, guardrailsEnabled = true) {
|
|
55801
56053
|
return async (input, _output) => {
|
|
55802
56054
|
const now = Date.now();
|
|
@@ -55842,6 +56094,562 @@ function createDelegationTrackerHook(config3, guardrailsEnabled = true) {
|
|
|
55842
56094
|
}
|
|
55843
56095
|
};
|
|
55844
56096
|
}
|
|
56097
|
+
// src/hooks/full-auto-intercept.ts
|
|
56098
|
+
import * as fs30 from "fs";
|
|
56099
|
+
init_schema();
|
|
56100
|
+
|
|
56101
|
+
// src/parallel/file-locks.ts
|
|
56102
|
+
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
56103
|
+
import * as fs29 from "fs";
|
|
56104
|
+
import * as path40 from "path";
|
|
56105
|
+
var LOCKS_DIR = ".swarm/locks";
|
|
56106
|
+
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
56107
|
+
function getLockFilePath(directory, filePath) {
|
|
56108
|
+
const normalized = path40.resolve(directory, filePath);
|
|
56109
|
+
if (!normalized.startsWith(path40.resolve(directory))) {
|
|
56110
|
+
throw new Error("Invalid file path: path traversal not allowed");
|
|
56111
|
+
}
|
|
56112
|
+
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
56113
|
+
return path40.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
56114
|
+
}
|
|
56115
|
+
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
56116
|
+
const lockPath = getLockFilePath(directory, filePath);
|
|
56117
|
+
const locksDir = path40.dirname(lockPath);
|
|
56118
|
+
if (!fs29.existsSync(locksDir)) {
|
|
56119
|
+
fs29.mkdirSync(locksDir, { recursive: true });
|
|
56120
|
+
}
|
|
56121
|
+
if (!fs29.existsSync(lockPath)) {
|
|
56122
|
+
fs29.writeFileSync(lockPath, "", "utf-8");
|
|
56123
|
+
}
|
|
56124
|
+
let release;
|
|
56125
|
+
try {
|
|
56126
|
+
release = await import_proper_lockfile3.default.lock(lockPath, {
|
|
56127
|
+
stale: LOCK_TIMEOUT_MS,
|
|
56128
|
+
retries: { retries: 0 },
|
|
56129
|
+
realpath: false
|
|
56130
|
+
});
|
|
56131
|
+
} catch (err2) {
|
|
56132
|
+
const code = err2.code;
|
|
56133
|
+
if (code === "ELOCKED" || code === "EEXIST") {
|
|
56134
|
+
return { acquired: false };
|
|
56135
|
+
}
|
|
56136
|
+
throw err2;
|
|
56137
|
+
}
|
|
56138
|
+
const lock = {
|
|
56139
|
+
filePath,
|
|
56140
|
+
agent,
|
|
56141
|
+
taskId,
|
|
56142
|
+
timestamp: new Date().toISOString(),
|
|
56143
|
+
expiresAt: Date.now() + LOCK_TIMEOUT_MS,
|
|
56144
|
+
_release: release
|
|
56145
|
+
};
|
|
56146
|
+
return { acquired: true, lock };
|
|
56147
|
+
}
|
|
56148
|
+
|
|
56149
|
+
// src/hooks/full-auto-intercept.ts
|
|
56150
|
+
init_state();
|
|
56151
|
+
init_telemetry();
|
|
56152
|
+
init_utils2();
|
|
56153
|
+
var END_OF_SENTENCE_QUESTION_PATTERN = /\?\s*$/;
|
|
56154
|
+
var ESCALATION_PATTERNS = [
|
|
56155
|
+
/Ready for Phase (?:\d+|\[?N\+1\]?)\?/i,
|
|
56156
|
+
/escalat/i,
|
|
56157
|
+
/What would you like/i,
|
|
56158
|
+
/Should I proceed/i,
|
|
56159
|
+
/Do you want/i
|
|
56160
|
+
];
|
|
56161
|
+
var MID_SENTENCE_QUESTION_PATTERNS = [
|
|
56162
|
+
/\b(v\d+\?)/i,
|
|
56163
|
+
/\b(v\d+\.\d+\?)/i,
|
|
56164
|
+
/\bAPI\?/i,
|
|
56165
|
+
/\bOK\?/i,
|
|
56166
|
+
/\b\d+\?\d+/
|
|
56167
|
+
];
|
|
56168
|
+
function hashString(str) {
|
|
56169
|
+
let hash3 = 5381;
|
|
56170
|
+
for (let i2 = 0;i2 < str.length; i2++) {
|
|
56171
|
+
hash3 = (hash3 << 5) + hash3 + str.charCodeAt(i2);
|
|
56172
|
+
hash3 = hash3 & hash3;
|
|
56173
|
+
}
|
|
56174
|
+
return Math.abs(hash3).toString(36);
|
|
56175
|
+
}
|
|
56176
|
+
function isMidSentenceQuestion(text) {
|
|
56177
|
+
return MID_SENTENCE_QUESTION_PATTERNS.some((pattern) => pattern.test(text));
|
|
56178
|
+
}
|
|
56179
|
+
function resolveOversightAgentName(architectAgentName) {
|
|
56180
|
+
if (!architectAgentName) {
|
|
56181
|
+
return "critic_oversight";
|
|
56182
|
+
}
|
|
56183
|
+
const stripped = stripKnownSwarmPrefix(architectAgentName);
|
|
56184
|
+
if (stripped !== "architect") {
|
|
56185
|
+
return "critic_oversight";
|
|
56186
|
+
}
|
|
56187
|
+
const baseRole = "architect";
|
|
56188
|
+
const lastIndex = architectAgentName.toLowerCase().lastIndexOf(baseRole);
|
|
56189
|
+
if (lastIndex <= 0) {
|
|
56190
|
+
return "critic_oversight";
|
|
56191
|
+
}
|
|
56192
|
+
const prefix = architectAgentName.slice(0, lastIndex);
|
|
56193
|
+
return `${prefix}critic_oversight`;
|
|
56194
|
+
}
|
|
56195
|
+
function detectEscalation(text) {
|
|
56196
|
+
for (const pattern of ESCALATION_PATTERNS) {
|
|
56197
|
+
if (pattern.test(text)) {
|
|
56198
|
+
return "phase_completion";
|
|
56199
|
+
}
|
|
56200
|
+
}
|
|
56201
|
+
if (END_OF_SENTENCE_QUESTION_PATTERN.test(text)) {
|
|
56202
|
+
if (!isMidSentenceQuestion(text)) {
|
|
56203
|
+
return "question";
|
|
56204
|
+
}
|
|
56205
|
+
}
|
|
56206
|
+
return null;
|
|
56207
|
+
}
|
|
56208
|
+
function extractMessageText3(message) {
|
|
56209
|
+
if (!message?.parts)
|
|
56210
|
+
return "";
|
|
56211
|
+
const textParts = message.parts.filter((p) => p?.type === "text" && p.text);
|
|
56212
|
+
return textParts.map((p) => p.text ?? "").join(`
|
|
56213
|
+
`);
|
|
56214
|
+
}
|
|
56215
|
+
function parseCriticResponse(rawResponse) {
|
|
56216
|
+
const result = {
|
|
56217
|
+
verdict: "NEEDS_REVISION",
|
|
56218
|
+
reasoning: "",
|
|
56219
|
+
evidenceChecked: [],
|
|
56220
|
+
antiPatternsDetected: [],
|
|
56221
|
+
escalationNeeded: false,
|
|
56222
|
+
rawResponse
|
|
56223
|
+
};
|
|
56224
|
+
const lines = rawResponse.split(`
|
|
56225
|
+
`);
|
|
56226
|
+
let currentKey = "";
|
|
56227
|
+
let currentValue = "";
|
|
56228
|
+
const commitField = (res, key, value) => {
|
|
56229
|
+
switch (key) {
|
|
56230
|
+
case "VERDICT": {
|
|
56231
|
+
const validVerdicts = [
|
|
56232
|
+
"APPROVED",
|
|
56233
|
+
"NEEDS_REVISION",
|
|
56234
|
+
"REJECTED",
|
|
56235
|
+
"BLOCKED",
|
|
56236
|
+
"ANSWER",
|
|
56237
|
+
"ESCALATE_TO_HUMAN",
|
|
56238
|
+
"REPHRASE"
|
|
56239
|
+
];
|
|
56240
|
+
const normalized = value.trim().toUpperCase().replace(/[`*]/g, "");
|
|
56241
|
+
if (validVerdicts.includes(normalized)) {
|
|
56242
|
+
res.verdict = normalized;
|
|
56243
|
+
} else {
|
|
56244
|
+
console.warn(`[full-auto-intercept] Unknown verdict '${value}' \u2014 defaulting to NEEDS_REVISION`);
|
|
56245
|
+
res.verdict = "NEEDS_REVISION";
|
|
56246
|
+
}
|
|
56247
|
+
break;
|
|
56248
|
+
}
|
|
56249
|
+
case "REASONING":
|
|
56250
|
+
res.reasoning = value.trim();
|
|
56251
|
+
break;
|
|
56252
|
+
case "EVIDENCE_CHECKED":
|
|
56253
|
+
if (value && value !== "none" && value !== '"none"') {
|
|
56254
|
+
res.evidenceChecked = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
56255
|
+
}
|
|
56256
|
+
break;
|
|
56257
|
+
case "ANTI_PATTERNS_DETECTED":
|
|
56258
|
+
if (value && value !== "none" && value !== '"none"') {
|
|
56259
|
+
res.antiPatternsDetected = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
56260
|
+
}
|
|
56261
|
+
break;
|
|
56262
|
+
case "ESCALATION_NEEDED":
|
|
56263
|
+
res.escalationNeeded = value.trim().toUpperCase() === "YES";
|
|
56264
|
+
break;
|
|
56265
|
+
}
|
|
56266
|
+
};
|
|
56267
|
+
for (const line of lines) {
|
|
56268
|
+
const colonIndex = line.indexOf(":");
|
|
56269
|
+
if (colonIndex !== -1) {
|
|
56270
|
+
const key = line.slice(0, colonIndex).trim().toUpperCase();
|
|
56271
|
+
if ([
|
|
56272
|
+
"VERDICT",
|
|
56273
|
+
"REASONING",
|
|
56274
|
+
"EVIDENCE_CHECKED",
|
|
56275
|
+
"ANTI_PATTERNS_DETECTED",
|
|
56276
|
+
"ESCALATION_NEEDED"
|
|
56277
|
+
].includes(key)) {
|
|
56278
|
+
if (currentKey) {
|
|
56279
|
+
commitField(result, currentKey, currentValue);
|
|
56280
|
+
}
|
|
56281
|
+
currentKey = key;
|
|
56282
|
+
currentValue = line.slice(colonIndex + 1).trim();
|
|
56283
|
+
} else {
|
|
56284
|
+
currentValue += `
|
|
56285
|
+
${line}`;
|
|
56286
|
+
}
|
|
56287
|
+
} else {
|
|
56288
|
+
if (line.trim()) {
|
|
56289
|
+
currentValue += `
|
|
56290
|
+
${line}`;
|
|
56291
|
+
}
|
|
56292
|
+
}
|
|
56293
|
+
}
|
|
56294
|
+
if (currentKey) {
|
|
56295
|
+
commitField(result, currentKey, currentValue);
|
|
56296
|
+
}
|
|
56297
|
+
return result;
|
|
56298
|
+
}
|
|
56299
|
+
function escalationTypeToInteractionMode(escalationType) {
|
|
56300
|
+
return escalationType === "phase_completion" ? "phase_completion" : "question_resolution";
|
|
56301
|
+
}
|
|
56302
|
+
async function writeAutoOversightEvent(directory, architectOutput, criticVerdict, criticReasoning, evidenceChecked, interactionCount, deadlockCount, escalationType) {
|
|
56303
|
+
const event = {
|
|
56304
|
+
type: "auto_oversight",
|
|
56305
|
+
timestamp: new Date().toISOString(),
|
|
56306
|
+
interaction_mode: escalationTypeToInteractionMode(escalationType),
|
|
56307
|
+
architect_output: architectOutput,
|
|
56308
|
+
critic_verdict: criticVerdict,
|
|
56309
|
+
critic_reasoning: criticReasoning,
|
|
56310
|
+
evidence_checked: evidenceChecked,
|
|
56311
|
+
interaction_count: interactionCount,
|
|
56312
|
+
deadlock_count: deadlockCount
|
|
56313
|
+
};
|
|
56314
|
+
const lockTaskId = `auto-oversight-${Date.now()}`;
|
|
56315
|
+
const eventsFilePath = "events.jsonl";
|
|
56316
|
+
const dir = directory;
|
|
56317
|
+
let lockResult;
|
|
56318
|
+
try {
|
|
56319
|
+
lockResult = await tryAcquireLock(dir, eventsFilePath, "auto-oversight", lockTaskId);
|
|
56320
|
+
} catch (error93) {
|
|
56321
|
+
console.warn(`[full-auto-intercept] Warning: failed to acquire lock for auto_oversight event: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
56322
|
+
}
|
|
56323
|
+
if (!lockResult?.acquired) {
|
|
56324
|
+
console.warn(`[full-auto-intercept] Warning: could not acquire lock for events.jsonl write \u2014 proceeding without lock`);
|
|
56325
|
+
}
|
|
56326
|
+
try {
|
|
56327
|
+
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
56328
|
+
fs30.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
56329
|
+
`, "utf-8");
|
|
56330
|
+
} catch (writeError) {
|
|
56331
|
+
console.error(`[full-auto-intercept] Warning: failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
56332
|
+
} finally {
|
|
56333
|
+
if (lockResult?.acquired && lockResult.lock._release) {
|
|
56334
|
+
try {
|
|
56335
|
+
await lockResult.lock._release();
|
|
56336
|
+
} catch (releaseError) {
|
|
56337
|
+
console.error(`[full-auto-intercept] Lock release failed:`, releaseError);
|
|
56338
|
+
}
|
|
56339
|
+
}
|
|
56340
|
+
}
|
|
56341
|
+
}
|
|
56342
|
+
function injectVerdictIntoMessages(messages, architectIndex, criticResult, _escalationType, oversightAgentName) {
|
|
56343
|
+
if (criticResult.escalationNeeded || criticResult.verdict === "ESCALATE_TO_HUMAN") {
|
|
56344
|
+
const verdictMessage2 = {
|
|
56345
|
+
info: {
|
|
56346
|
+
role: "assistant",
|
|
56347
|
+
agent: oversightAgentName
|
|
56348
|
+
},
|
|
56349
|
+
parts: [
|
|
56350
|
+
{
|
|
56351
|
+
type: "text",
|
|
56352
|
+
text: `[FULL-AUTO OVERSIGHT \u2014 ESCALATE_TO_HUMAN]
|
|
56353
|
+
|
|
56354
|
+
Critic reasoning: ${criticResult.reasoning}
|
|
56355
|
+
|
|
56356
|
+
This question requires human judgment. The swarm has been paused for human review.`
|
|
56357
|
+
}
|
|
56358
|
+
]
|
|
56359
|
+
};
|
|
56360
|
+
messages.splice(architectIndex + 1, 0, verdictMessage2);
|
|
56361
|
+
return;
|
|
56362
|
+
}
|
|
56363
|
+
if (criticResult.verdict === "ANSWER") {
|
|
56364
|
+
const verdictMessage2 = {
|
|
56365
|
+
info: {
|
|
56366
|
+
role: "assistant",
|
|
56367
|
+
agent: oversightAgentName
|
|
56368
|
+
},
|
|
56369
|
+
parts: [
|
|
56370
|
+
{
|
|
56371
|
+
type: "text",
|
|
56372
|
+
text: `[FULL-AUTO OVERSIGHT \u2014 ANSWER]
|
|
56373
|
+
|
|
56374
|
+
${criticResult.reasoning}`
|
|
56375
|
+
}
|
|
56376
|
+
]
|
|
56377
|
+
};
|
|
56378
|
+
messages.splice(architectIndex + 1, 0, verdictMessage2);
|
|
56379
|
+
return;
|
|
56380
|
+
}
|
|
56381
|
+
const verdictEmoji = criticResult.verdict === "APPROVED" ? "\u2705" : criticResult.verdict === "NEEDS_REVISION" ? "\uD83D\uDD04" : criticResult.verdict === "REJECTED" ? "\u274C" : criticResult.verdict === "BLOCKED" ? "\uD83D\uDEAB" : "\uD83D\uDCAC";
|
|
56382
|
+
const verdictMessage = {
|
|
56383
|
+
info: {
|
|
56384
|
+
role: "assistant",
|
|
56385
|
+
agent: oversightAgentName
|
|
56386
|
+
},
|
|
56387
|
+
parts: [
|
|
56388
|
+
{
|
|
56389
|
+
type: "text",
|
|
56390
|
+
text: `[FULL-AUTO OVERSIGHT] ${verdictEmoji} **${criticResult.verdict}**
|
|
56391
|
+
|
|
56392
|
+
Critic reasoning: ${criticResult.reasoning}`
|
|
56393
|
+
}
|
|
56394
|
+
]
|
|
56395
|
+
};
|
|
56396
|
+
messages.splice(architectIndex + 1, 0, verdictMessage);
|
|
56397
|
+
}
|
|
56398
|
+
async function dispatchCriticAndWriteEvent(directory, architectOutput, criticContext, criticModel, escalationType, interactionCount, deadlockCount, oversightAgentName) {
|
|
56399
|
+
const client = swarmState.opencodeClient;
|
|
56400
|
+
if (!client) {
|
|
56401
|
+
console.warn("[full-auto-intercept] No opencodeClient \u2014 critic dispatch skipped (fallback to PENDING)");
|
|
56402
|
+
const result = {
|
|
56403
|
+
verdict: "PENDING",
|
|
56404
|
+
reasoning: "No opencodeClient available \u2014 critic dispatch not possible",
|
|
56405
|
+
evidenceChecked: [],
|
|
56406
|
+
antiPatternsDetected: [],
|
|
56407
|
+
escalationNeeded: false,
|
|
56408
|
+
rawResponse: ""
|
|
56409
|
+
};
|
|
56410
|
+
await writeAutoOversightEvent(directory, architectOutput, result.verdict, result.reasoning, result.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
56411
|
+
return result;
|
|
56412
|
+
}
|
|
56413
|
+
const oversightAgent = createCriticAutonomousOversightAgent(criticModel, criticContext);
|
|
56414
|
+
console.log(`[full-auto-intercept] Dispatching critic: ${oversightAgent.name} using model ${criticModel}`);
|
|
56415
|
+
let ephemeralSessionId;
|
|
56416
|
+
const cleanup = () => {
|
|
56417
|
+
if (ephemeralSessionId) {
|
|
56418
|
+
const id = ephemeralSessionId;
|
|
56419
|
+
ephemeralSessionId = undefined;
|
|
56420
|
+
client.session.delete({ path: { id } }).catch(() => {});
|
|
56421
|
+
}
|
|
56422
|
+
};
|
|
56423
|
+
let criticResponse = "";
|
|
56424
|
+
try {
|
|
56425
|
+
const createResult = await client.session.create({
|
|
56426
|
+
query: { directory }
|
|
56427
|
+
});
|
|
56428
|
+
if (!createResult.data) {
|
|
56429
|
+
throw new Error(`Failed to create critic session: ${JSON.stringify(createResult.error)}`);
|
|
56430
|
+
}
|
|
56431
|
+
ephemeralSessionId = createResult.data.id;
|
|
56432
|
+
console.log(`[full-auto-intercept] Created ephemeral session: ${ephemeralSessionId}`);
|
|
56433
|
+
const promptResult = await client.session.prompt({
|
|
56434
|
+
path: { id: ephemeralSessionId },
|
|
56435
|
+
body: {
|
|
56436
|
+
agent: oversightAgentName,
|
|
56437
|
+
tools: { write: false, edit: false, patch: false },
|
|
56438
|
+
parts: [{ type: "text", text: criticContext }]
|
|
56439
|
+
}
|
|
56440
|
+
});
|
|
56441
|
+
if (!promptResult.data) {
|
|
56442
|
+
throw new Error(`Critic LLM prompt failed: ${JSON.stringify(promptResult.error)}`);
|
|
56443
|
+
}
|
|
56444
|
+
const textParts = promptResult.data.parts.filter((p) => p.type === "text");
|
|
56445
|
+
criticResponse = textParts.map((p) => p.text).join(`
|
|
56446
|
+
`);
|
|
56447
|
+
console.log(`[full-auto-intercept] Critic response received (${criticResponse.length} chars)`);
|
|
56448
|
+
if (!criticResponse.trim()) {
|
|
56449
|
+
console.warn("[full-auto-intercept] Critic returned empty response \u2014 using fallback verdict");
|
|
56450
|
+
criticResponse = `VERDICT: NEEDS_REVISION
|
|
56451
|
+
REASONING: Critic returned empty response
|
|
56452
|
+
EVIDENCE_CHECKED: none
|
|
56453
|
+
ANTI_PATTERNS_DETECTED: empty_response
|
|
56454
|
+
ESCALATION_NEEDED: NO`;
|
|
56455
|
+
}
|
|
56456
|
+
} finally {
|
|
56457
|
+
cleanup();
|
|
56458
|
+
}
|
|
56459
|
+
let parsed;
|
|
56460
|
+
try {
|
|
56461
|
+
parsed = parseCriticResponse(criticResponse);
|
|
56462
|
+
console.log(`[full-auto-intercept] Critic verdict: ${parsed.verdict} | escalation: ${parsed.escalationNeeded}`);
|
|
56463
|
+
} catch (parseError) {
|
|
56464
|
+
console.error(`[full-auto-intercept] Failed to parse critic response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
56465
|
+
parsed = {
|
|
56466
|
+
verdict: "NEEDS_REVISION",
|
|
56467
|
+
reasoning: "Critic response parsing failed \u2014 defaulting to NEEDS_REVISION",
|
|
56468
|
+
evidenceChecked: [],
|
|
56469
|
+
antiPatternsDetected: [],
|
|
56470
|
+
escalationNeeded: false,
|
|
56471
|
+
rawResponse: criticResponse
|
|
56472
|
+
};
|
|
56473
|
+
}
|
|
56474
|
+
try {
|
|
56475
|
+
await writeAutoOversightEvent(directory, architectOutput, parsed.verdict, parsed.reasoning, parsed.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
56476
|
+
} catch (writeError) {
|
|
56477
|
+
console.error(`[full-auto-intercept] Failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
56478
|
+
}
|
|
56479
|
+
return parsed;
|
|
56480
|
+
}
|
|
56481
|
+
function createFullAutoInterceptHook(config3, directory) {
|
|
56482
|
+
const fullAutoConfig = config3.full_auto ?? {
|
|
56483
|
+
enabled: false,
|
|
56484
|
+
max_interactions_per_phase: 50,
|
|
56485
|
+
deadlock_threshold: 3,
|
|
56486
|
+
escalation_mode: "pause"
|
|
56487
|
+
};
|
|
56488
|
+
if (fullAutoConfig.enabled !== true) {
|
|
56489
|
+
return {
|
|
56490
|
+
messagesTransform: async () => {}
|
|
56491
|
+
};
|
|
56492
|
+
}
|
|
56493
|
+
const deadlockThreshold = fullAutoConfig.deadlock_threshold ?? 3;
|
|
56494
|
+
const maxInteractions = fullAutoConfig.max_interactions_per_phase ?? 50;
|
|
56495
|
+
const escalationMode = fullAutoConfig.escalation_mode ?? "pause";
|
|
56496
|
+
const messagesTransform = async (_input, output) => {
|
|
56497
|
+
const messages = output.messages;
|
|
56498
|
+
if (!messages || messages.length === 0)
|
|
56499
|
+
return;
|
|
56500
|
+
let lastArchitectMessageIndex = -1;
|
|
56501
|
+
for (let i2 = messages.length - 1;i2 >= 0; i2--) {
|
|
56502
|
+
const msg = messages[i2];
|
|
56503
|
+
if (msg?.info?.role === "user") {
|
|
56504
|
+
const agent = msg.info?.agent;
|
|
56505
|
+
const strippedAgent = agent ? stripKnownSwarmPrefix(agent) : undefined;
|
|
56506
|
+
if (!agent || strippedAgent === "architect") {
|
|
56507
|
+
lastArchitectMessageIndex = i2;
|
|
56508
|
+
break;
|
|
56509
|
+
}
|
|
56510
|
+
}
|
|
56511
|
+
}
|
|
56512
|
+
if (lastArchitectMessageIndex === -1)
|
|
56513
|
+
return;
|
|
56514
|
+
const architectMessage = messages[lastArchitectMessageIndex];
|
|
56515
|
+
const architectText = extractMessageText3(architectMessage);
|
|
56516
|
+
if (!architectText)
|
|
56517
|
+
return;
|
|
56518
|
+
const sessionID = architectMessage.info?.sessionID;
|
|
56519
|
+
if (!hasActiveFullAuto(sessionID))
|
|
56520
|
+
return;
|
|
56521
|
+
let session = null;
|
|
56522
|
+
if (sessionID) {
|
|
56523
|
+
const { ensureAgentSession: ensureAgentSession2 } = await Promise.resolve().then(() => (init_state(), exports_state));
|
|
56524
|
+
session = ensureAgentSession2(sessionID);
|
|
56525
|
+
}
|
|
56526
|
+
if (session) {
|
|
56527
|
+
const interactionCount = session.fullAutoInteractionCount ?? 0;
|
|
56528
|
+
if (interactionCount >= maxInteractions) {
|
|
56529
|
+
const escalated = await handleEscalation(directory, "interaction_limit", sessionID, architectText, interactionCount, session.fullAutoDeadlockCount ?? 0, escalationMode);
|
|
56530
|
+
if (escalated)
|
|
56531
|
+
return;
|
|
56532
|
+
}
|
|
56533
|
+
}
|
|
56534
|
+
const escalationType = detectEscalation(architectText);
|
|
56535
|
+
if (!escalationType)
|
|
56536
|
+
return;
|
|
56537
|
+
if (session) {
|
|
56538
|
+
session.fullAutoInteractionCount = (session.fullAutoInteractionCount ?? 0) + 1;
|
|
56539
|
+
}
|
|
56540
|
+
if (escalationType === "question") {
|
|
56541
|
+
const questionHash = hashString(architectText.trim());
|
|
56542
|
+
if (session) {
|
|
56543
|
+
const lastQuestionHash = session.fullAutoLastQuestionHash;
|
|
56544
|
+
if (lastQuestionHash === questionHash) {
|
|
56545
|
+
session.fullAutoDeadlockCount = (session.fullAutoDeadlockCount ?? 0) + 1;
|
|
56546
|
+
console.warn(`[full-auto-intercept] Potential deadlock detected (count: ${session.fullAutoDeadlockCount}/${deadlockThreshold}) \u2014 identical question repeated`);
|
|
56547
|
+
if (session.fullAutoDeadlockCount >= deadlockThreshold) {
|
|
56548
|
+
const escalated = await handleEscalation(directory, "deadlock", sessionID, architectText, session.fullAutoInteractionCount ?? 0, session.fullAutoDeadlockCount, escalationMode);
|
|
56549
|
+
if (escalated)
|
|
56550
|
+
return;
|
|
56551
|
+
}
|
|
56552
|
+
} else {
|
|
56553
|
+
session.fullAutoDeadlockCount = 0;
|
|
56554
|
+
}
|
|
56555
|
+
session.fullAutoLastQuestionHash = questionHash;
|
|
56556
|
+
}
|
|
56557
|
+
}
|
|
56558
|
+
console.log(`[full-auto-intercept] Escalation detected (${escalationType}) \u2014 triggering autonomous oversight`);
|
|
56559
|
+
const criticContext = buildCriticContext(architectText, escalationType);
|
|
56560
|
+
const criticModel = fullAutoConfig.critic_model ?? "claude-sonnet-4-20250514";
|
|
56561
|
+
const oversightAgent = createCriticAutonomousOversightAgent(criticModel, criticContext);
|
|
56562
|
+
const architectAgent = architectMessage.info?.agent;
|
|
56563
|
+
const resolvedOversightAgentName = resolveOversightAgentName(architectAgent);
|
|
56564
|
+
const dispatchAgentName = resolvedOversightAgentName && resolvedOversightAgentName.length > 0 ? resolvedOversightAgentName : "critic_oversight";
|
|
56565
|
+
console.log(`[full-auto-intercept] Created autonomous oversight agent: ${oversightAgent.name} using model ${criticModel} (dispatch as: ${dispatchAgentName})`);
|
|
56566
|
+
const criticResult = await dispatchCriticAndWriteEvent(directory, architectText, criticContext, criticModel, escalationType, session?.fullAutoInteractionCount ?? 0, session?.fullAutoDeadlockCount ?? 0, dispatchAgentName);
|
|
56567
|
+
injectVerdictIntoMessages(messages, lastArchitectMessageIndex, criticResult, escalationType, dispatchAgentName);
|
|
56568
|
+
};
|
|
56569
|
+
return {
|
|
56570
|
+
messagesTransform
|
|
56571
|
+
};
|
|
56572
|
+
}
|
|
56573
|
+
function buildCriticContext(architectOutput, escalationType) {
|
|
56574
|
+
const contextHeader = escalationType === "phase_completion" ? `## ARCHITECT PHASE COMPLETION REQUEST
|
|
56575
|
+
|
|
56576
|
+
The architect has signaled phase completion and is awaiting oversight approval to proceed.` : `## ARCHITECT QUESTION
|
|
56577
|
+
|
|
56578
|
+
The architect has asked a question and is awaiting an autonomous answer or escalation.`;
|
|
56579
|
+
const truncatedOutput = architectOutput.length > 2000 ? architectOutput.slice(0, 2000) + `
|
|
56580
|
+
... [truncated]` : architectOutput;
|
|
56581
|
+
return `${contextHeader}
|
|
56582
|
+
|
|
56583
|
+
### ARCHITECT OUTPUT:
|
|
56584
|
+
${truncatedOutput}
|
|
56585
|
+
|
|
56586
|
+
### YOUR TASK:
|
|
56587
|
+
Evaluate the architect's output and provide a response. If this is a question, answer it directly if you have sufficient information. If this is a phase completion, verify all tasks are complete and provide APPROVED or NEEDS_REVISION.
|
|
56588
|
+
|
|
56589
|
+
Remember: You are the sole quality gate. Default posture is REJECT unless you have positive evidence of correctness.`;
|
|
56590
|
+
}
|
|
56591
|
+
async function writeEscalationReport(directory, reason, architectOutput, interactionCount, deadlockCount, phase) {
|
|
56592
|
+
try {
|
|
56593
|
+
const reportPath = validateSwarmPath(directory, "escalation-report.md");
|
|
56594
|
+
let currentPhase = phase;
|
|
56595
|
+
if (currentPhase === undefined) {
|
|
56596
|
+
try {
|
|
56597
|
+
const planPath = validateSwarmPath(directory, "plan.json");
|
|
56598
|
+
const planContent = fs30.readFileSync(planPath, "utf-8");
|
|
56599
|
+
const plan = JSON.parse(planContent);
|
|
56600
|
+
const incompletePhases = plan.phases.filter((p) => p.status !== "complete").sort((a, b) => b.id - a.id);
|
|
56601
|
+
currentPhase = incompletePhases[0]?.id;
|
|
56602
|
+
} catch {}
|
|
56603
|
+
}
|
|
56604
|
+
const timestamp = new Date().toISOString();
|
|
56605
|
+
const reasonLabels = {
|
|
56606
|
+
interaction_limit: "Interaction Limit Exceeded",
|
|
56607
|
+
deadlock: "Deadlock Threshold Exceeded",
|
|
56608
|
+
ESCALATE_TO_HUMAN: "Critic Response: ESCALATE_TO_HUMAN"
|
|
56609
|
+
};
|
|
56610
|
+
const reportContent = `# Full-Auto Escalation Report
|
|
56611
|
+
|
|
56612
|
+
## Timestamp
|
|
56613
|
+
${timestamp}
|
|
56614
|
+
|
|
56615
|
+
## Reason for Escalation
|
|
56616
|
+
${reasonLabels[reason]}
|
|
56617
|
+
|
|
56618
|
+
## Architect Output That Triggered Escalation
|
|
56619
|
+
\`\`\`
|
|
56620
|
+
${architectOutput.slice(0, 4000)}
|
|
56621
|
+
${architectOutput.length > 4000 ? `
|
|
56622
|
+
... [output truncated]` : ""}
|
|
56623
|
+
\`\`\`
|
|
56624
|
+
|
|
56625
|
+
## FullAuto State at Time of Escalation
|
|
56626
|
+
- **Interaction Count**: ${interactionCount}
|
|
56627
|
+
- **Deadlock Count**: ${deadlockCount}
|
|
56628
|
+
|
|
56629
|
+
## Current Phase and Plan Context
|
|
56630
|
+
- **Current Phase**: ${currentPhase !== undefined ? `Phase ${currentPhase}` : "Unknown"}
|
|
56631
|
+
${currentPhase !== undefined ? `- **Phase Status**: Pending completion` : ""}
|
|
56632
|
+
|
|
56633
|
+
## Resolution
|
|
56634
|
+
This escalation requires human intervention. The swarm has been paused.
|
|
56635
|
+
Please review the architect's output above and provide guidance.
|
|
56636
|
+
`;
|
|
56637
|
+
fs30.writeFileSync(reportPath, reportContent, "utf-8");
|
|
56638
|
+
console.log(`[full-auto-intercept] Escalation report written to: ${reportPath}`);
|
|
56639
|
+
} catch (error93) {
|
|
56640
|
+
console.error(`[full-auto-intercept] Failed to write escalation report:`, error93 instanceof Error ? error93.message : String(error93));
|
|
56641
|
+
}
|
|
56642
|
+
}
|
|
56643
|
+
async function handleEscalation(directory, reason, sessionID, architectOutput, interactionCount, deadlockCount, escalationMode, phase) {
|
|
56644
|
+
telemetry.autoOversightEscalation(sessionID ?? "unknown", reason, interactionCount, deadlockCount, phase);
|
|
56645
|
+
await writeEscalationReport(directory, reason, architectOutput, interactionCount, deadlockCount, phase);
|
|
56646
|
+
if (escalationMode === "terminate") {
|
|
56647
|
+
console.error(`[full-auto-intercept] ESCALATION (terminate mode) \u2014 reason: ${reason}, session: ${sessionID}`);
|
|
56648
|
+
process.exit(1);
|
|
56649
|
+
}
|
|
56650
|
+
console.warn(`[full-auto-intercept] ESCALATION (pause mode) \u2014 reason: ${reason}, session: ${sessionID}`);
|
|
56651
|
+
return true;
|
|
56652
|
+
}
|
|
55845
56653
|
// src/hooks/messages-transform.ts
|
|
55846
56654
|
function consolidateSystemMessages(messages) {
|
|
55847
56655
|
if (messages.length > 0 && messages[0].role === "system" && messages[0].content !== undefined && typeof messages[0].content === "string" && messages[0].content.trim().length > 0) {
|
|
@@ -55910,7 +56718,7 @@ function consolidateSystemMessages(messages) {
|
|
|
55910
56718
|
// src/hooks/phase-monitor.ts
|
|
55911
56719
|
init_schema();
|
|
55912
56720
|
init_manager2();
|
|
55913
|
-
import * as
|
|
56721
|
+
import * as path42 from "path";
|
|
55914
56722
|
init_utils2();
|
|
55915
56723
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
55916
56724
|
let lastKnownPhase = null;
|
|
@@ -55931,9 +56739,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
55931
56739
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
55932
56740
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
55933
56741
|
if (initResult.briefing) {
|
|
55934
|
-
const briefingPath =
|
|
56742
|
+
const briefingPath = path42.join(directory, ".swarm", "curator-briefing.md");
|
|
55935
56743
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
55936
|
-
await mkdir5(
|
|
56744
|
+
await mkdir5(path42.dirname(briefingPath), { recursive: true });
|
|
55937
56745
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
55938
56746
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
55939
56747
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -56066,15 +56874,15 @@ init_schema();
|
|
|
56066
56874
|
init_manager();
|
|
56067
56875
|
init_detector();
|
|
56068
56876
|
init_manager2();
|
|
56069
|
-
import * as
|
|
56070
|
-
import * as
|
|
56877
|
+
import * as fs35 from "fs";
|
|
56878
|
+
import * as path46 from "path";
|
|
56071
56879
|
|
|
56072
56880
|
// src/services/decision-drift-analyzer.ts
|
|
56073
56881
|
init_utils2();
|
|
56074
56882
|
init_manager2();
|
|
56075
56883
|
init_utils();
|
|
56076
|
-
import * as
|
|
56077
|
-
import * as
|
|
56884
|
+
import * as fs32 from "fs";
|
|
56885
|
+
import * as path43 from "path";
|
|
56078
56886
|
var DEFAULT_DRIFT_CONFIG = {
|
|
56079
56887
|
staleThresholdPhases: 1,
|
|
56080
56888
|
detectContradictions: true,
|
|
@@ -56228,11 +57036,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
56228
57036
|
currentPhase = legacyPhase;
|
|
56229
57037
|
}
|
|
56230
57038
|
}
|
|
56231
|
-
const contextPath =
|
|
57039
|
+
const contextPath = path43.join(directory, ".swarm", "context.md");
|
|
56232
57040
|
let contextContent = "";
|
|
56233
57041
|
try {
|
|
56234
|
-
if (
|
|
56235
|
-
contextContent =
|
|
57042
|
+
if (fs32.existsSync(contextPath)) {
|
|
57043
|
+
contextContent = fs32.readFileSync(contextPath, "utf-8");
|
|
56236
57044
|
}
|
|
56237
57045
|
} catch (error93) {
|
|
56238
57046
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -56351,14 +57159,15 @@ init_preflight_integration();
|
|
|
56351
57159
|
init_preflight_service();
|
|
56352
57160
|
|
|
56353
57161
|
// src/hooks/system-enhancer.ts
|
|
57162
|
+
init_state();
|
|
56354
57163
|
init_telemetry();
|
|
56355
57164
|
init_utils();
|
|
56356
57165
|
|
|
56357
57166
|
// src/hooks/adversarial-detector.ts
|
|
56358
57167
|
init_constants();
|
|
56359
57168
|
init_schema();
|
|
56360
|
-
import * as
|
|
56361
|
-
import * as
|
|
57169
|
+
import * as fs33 from "fs/promises";
|
|
57170
|
+
import * as path44 from "path";
|
|
56362
57171
|
function safeGet(obj, key) {
|
|
56363
57172
|
if (!obj || !Object.hasOwn(obj, key))
|
|
56364
57173
|
return;
|
|
@@ -56572,10 +57381,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
56572
57381
|
let eventLogged = false;
|
|
56573
57382
|
let checkpointCreated = false;
|
|
56574
57383
|
try {
|
|
56575
|
-
const swarmDir =
|
|
56576
|
-
await
|
|
56577
|
-
const eventsPath =
|
|
56578
|
-
await
|
|
57384
|
+
const swarmDir = path44.join(directory, ".swarm");
|
|
57385
|
+
await fs33.mkdir(swarmDir, { recursive: true });
|
|
57386
|
+
const eventsPath = path44.join(swarmDir, "events.jsonl");
|
|
57387
|
+
await fs33.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
56579
57388
|
`);
|
|
56580
57389
|
eventLogged = true;
|
|
56581
57390
|
} catch {}
|
|
@@ -56986,7 +57795,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56986
57795
|
} catch {}
|
|
56987
57796
|
try {
|
|
56988
57797
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
56989
|
-
if (!
|
|
57798
|
+
if (!fs35.existsSync(darkMatterPath)) {
|
|
56990
57799
|
const {
|
|
56991
57800
|
detectDarkMatter: detectDarkMatter2,
|
|
56992
57801
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -56998,10 +57807,10 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56998
57807
|
});
|
|
56999
57808
|
if (darkMatter && darkMatter.length > 0) {
|
|
57000
57809
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
57001
|
-
await
|
|
57810
|
+
await fs35.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
57002
57811
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
57003
57812
|
try {
|
|
57004
|
-
const projectName =
|
|
57813
|
+
const projectName = path46.basename(path46.resolve(directory));
|
|
57005
57814
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
57006
57815
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
57007
57816
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -57065,11 +57874,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
57065
57874
|
if (handoffContent) {
|
|
57066
57875
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
57067
57876
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
57068
|
-
if (
|
|
57877
|
+
if (fs35.existsSync(consumedPath)) {
|
|
57069
57878
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
57070
|
-
|
|
57879
|
+
fs35.unlinkSync(consumedPath);
|
|
57071
57880
|
}
|
|
57072
|
-
|
|
57881
|
+
fs35.renameSync(handoffPath, consumedPath);
|
|
57073
57882
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
57074
57883
|
The previous model's session ended. Here is your starting context:
|
|
57075
57884
|
|
|
@@ -57195,6 +58004,15 @@ ${handoffBlock}`);
|
|
|
57195
58004
|
const activeAgent_retro = swarmState.activeAgent.get(sessionId_retro ?? "");
|
|
57196
58005
|
const isArchitect2 = !activeAgent_retro || stripKnownSwarmPrefix(activeAgent_retro) === "architect";
|
|
57197
58006
|
if (isArchitect2) {
|
|
58007
|
+
const sessionIdBanner = _input.sessionID;
|
|
58008
|
+
if (hasActiveTurboMode(sessionIdBanner) || hasActiveFullAuto(sessionIdBanner)) {
|
|
58009
|
+
if (hasActiveTurboMode(sessionIdBanner)) {
|
|
58010
|
+
tryInject(TURBO_MODE_BANNER);
|
|
58011
|
+
}
|
|
58012
|
+
if (hasActiveFullAuto(sessionIdBanner)) {
|
|
58013
|
+
tryInject(FULL_AUTO_BANNER);
|
|
58014
|
+
}
|
|
58015
|
+
}
|
|
57198
58016
|
try {
|
|
57199
58017
|
const currentPhaseNum = plan2?.current_phase ?? 1;
|
|
57200
58018
|
const retroText = await buildRetroInjection(directory, currentPhaseNum, plan2?.title ?? undefined);
|
|
@@ -57357,11 +58175,11 @@ ${budgetWarning}`);
|
|
|
57357
58175
|
if (handoffContent) {
|
|
57358
58176
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
57359
58177
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
57360
|
-
if (
|
|
58178
|
+
if (fs35.existsSync(consumedPath)) {
|
|
57361
58179
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
57362
|
-
|
|
58180
|
+
fs35.unlinkSync(consumedPath);
|
|
57363
58181
|
}
|
|
57364
|
-
|
|
58182
|
+
fs35.renameSync(handoffPath, consumedPath);
|
|
57365
58183
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
57366
58184
|
The previous model's session ended. Here is your starting context:
|
|
57367
58185
|
|
|
@@ -57527,6 +58345,29 @@ ${handoffBlock}`;
|
|
|
57527
58345
|
const activeAgent_retro_b = swarmState.activeAgent.get(sessionId_retro_b ?? "");
|
|
57528
58346
|
const isArchitect_b = !activeAgent_retro_b || stripKnownSwarmPrefix(activeAgent_retro_b) === "architect";
|
|
57529
58347
|
if (isArchitect_b) {
|
|
58348
|
+
const sessionIdBanner_b = _input.sessionID;
|
|
58349
|
+
if (hasActiveTurboMode(sessionIdBanner_b) || hasActiveFullAuto(sessionIdBanner_b)) {
|
|
58350
|
+
if (hasActiveTurboMode(sessionIdBanner_b)) {
|
|
58351
|
+
candidates.push({
|
|
58352
|
+
id: `candidate-${idCounter++}`,
|
|
58353
|
+
kind: "agent_context",
|
|
58354
|
+
text: TURBO_MODE_BANNER,
|
|
58355
|
+
tokens: estimateTokens(TURBO_MODE_BANNER),
|
|
58356
|
+
priority: 1,
|
|
58357
|
+
metadata: { contentType: "prose" }
|
|
58358
|
+
});
|
|
58359
|
+
}
|
|
58360
|
+
if (hasActiveFullAuto(sessionIdBanner_b)) {
|
|
58361
|
+
candidates.push({
|
|
58362
|
+
id: `candidate-${idCounter++}`,
|
|
58363
|
+
kind: "agent_context",
|
|
58364
|
+
text: FULL_AUTO_BANNER,
|
|
58365
|
+
tokens: estimateTokens(FULL_AUTO_BANNER),
|
|
58366
|
+
priority: 1,
|
|
58367
|
+
metadata: { contentType: "prose" }
|
|
58368
|
+
});
|
|
58369
|
+
}
|
|
58370
|
+
}
|
|
57530
58371
|
try {
|
|
57531
58372
|
const currentPhaseNum_b = plan?.current_phase ?? 1;
|
|
57532
58373
|
const retroText_b = await buildRetroInjection(directory, currentPhaseNum_b, plan?.title ?? undefined);
|
|
@@ -58055,6 +58896,7 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
58055
58896
|
}
|
|
58056
58897
|
|
|
58057
58898
|
// src/hooks/delegation-ledger.ts
|
|
58899
|
+
init_state();
|
|
58058
58900
|
var ledgerBySession = new Map;
|
|
58059
58901
|
var callStartTimes = new Map;
|
|
58060
58902
|
function createDelegationLedgerHook(config3, _directory, injectAdvisory) {
|
|
@@ -58146,14 +58988,14 @@ function isReadTool(toolName) {
|
|
|
58146
58988
|
}
|
|
58147
58989
|
|
|
58148
58990
|
// src/hooks/incremental-verify.ts
|
|
58149
|
-
import * as
|
|
58150
|
-
import * as
|
|
58991
|
+
import * as fs36 from "fs";
|
|
58992
|
+
import * as path47 from "path";
|
|
58151
58993
|
|
|
58152
58994
|
// src/hooks/spawn-helper.ts
|
|
58153
58995
|
import * as child_process4 from "child_process";
|
|
58154
58996
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
58155
58997
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
58156
|
-
return new Promise((
|
|
58998
|
+
return new Promise((resolve15) => {
|
|
58157
58999
|
try {
|
|
58158
59000
|
const [rawCmd, ...args2] = command;
|
|
58159
59001
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -58200,24 +59042,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
58200
59042
|
try {
|
|
58201
59043
|
proc.kill();
|
|
58202
59044
|
} catch {}
|
|
58203
|
-
|
|
59045
|
+
resolve15(null);
|
|
58204
59046
|
}, timeoutMs);
|
|
58205
59047
|
proc.on("close", (code) => {
|
|
58206
59048
|
if (done)
|
|
58207
59049
|
return;
|
|
58208
59050
|
done = true;
|
|
58209
59051
|
clearTimeout(timer);
|
|
58210
|
-
|
|
59052
|
+
resolve15({ exitCode: code ?? 1, stdout, stderr });
|
|
58211
59053
|
});
|
|
58212
59054
|
proc.on("error", () => {
|
|
58213
59055
|
if (done)
|
|
58214
59056
|
return;
|
|
58215
59057
|
done = true;
|
|
58216
59058
|
clearTimeout(timer);
|
|
58217
|
-
|
|
59059
|
+
resolve15(null);
|
|
58218
59060
|
});
|
|
58219
59061
|
} catch {
|
|
58220
|
-
|
|
59062
|
+
resolve15(null);
|
|
58221
59063
|
}
|
|
58222
59064
|
});
|
|
58223
59065
|
}
|
|
@@ -58225,21 +59067,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
58225
59067
|
// src/hooks/incremental-verify.ts
|
|
58226
59068
|
var emittedSkipAdvisories = new Set;
|
|
58227
59069
|
function detectPackageManager(projectDir) {
|
|
58228
|
-
if (
|
|
59070
|
+
if (fs36.existsSync(path47.join(projectDir, "bun.lockb")))
|
|
58229
59071
|
return "bun";
|
|
58230
|
-
if (
|
|
59072
|
+
if (fs36.existsSync(path47.join(projectDir, "pnpm-lock.yaml")))
|
|
58231
59073
|
return "pnpm";
|
|
58232
|
-
if (
|
|
59074
|
+
if (fs36.existsSync(path47.join(projectDir, "yarn.lock")))
|
|
58233
59075
|
return "yarn";
|
|
58234
|
-
if (
|
|
59076
|
+
if (fs36.existsSync(path47.join(projectDir, "package-lock.json")))
|
|
58235
59077
|
return "npm";
|
|
58236
59078
|
return "bun";
|
|
58237
59079
|
}
|
|
58238
59080
|
function detectTypecheckCommand(projectDir) {
|
|
58239
|
-
const pkgPath =
|
|
58240
|
-
if (
|
|
59081
|
+
const pkgPath = path47.join(projectDir, "package.json");
|
|
59082
|
+
if (fs36.existsSync(pkgPath)) {
|
|
58241
59083
|
try {
|
|
58242
|
-
const pkg = JSON.parse(
|
|
59084
|
+
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
|
|
58243
59085
|
const scripts = pkg.scripts;
|
|
58244
59086
|
if (scripts?.typecheck) {
|
|
58245
59087
|
const pm = detectPackageManager(projectDir);
|
|
@@ -58253,8 +59095,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
58253
59095
|
...pkg.dependencies,
|
|
58254
59096
|
...pkg.devDependencies
|
|
58255
59097
|
};
|
|
58256
|
-
if (!deps?.typescript && !
|
|
58257
|
-
const hasTSMarkers = deps?.typescript ||
|
|
59098
|
+
if (!deps?.typescript && !fs36.existsSync(path47.join(projectDir, "tsconfig.json"))) {}
|
|
59099
|
+
const hasTSMarkers = deps?.typescript || fs36.existsSync(path47.join(projectDir, "tsconfig.json"));
|
|
58258
59100
|
if (hasTSMarkers) {
|
|
58259
59101
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
58260
59102
|
}
|
|
@@ -58262,17 +59104,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
58262
59104
|
return null;
|
|
58263
59105
|
}
|
|
58264
59106
|
}
|
|
58265
|
-
if (
|
|
59107
|
+
if (fs36.existsSync(path47.join(projectDir, "go.mod"))) {
|
|
58266
59108
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
58267
59109
|
}
|
|
58268
|
-
if (
|
|
59110
|
+
if (fs36.existsSync(path47.join(projectDir, "Cargo.toml"))) {
|
|
58269
59111
|
return { command: ["cargo", "check"], language: "rust" };
|
|
58270
59112
|
}
|
|
58271
|
-
if (
|
|
59113
|
+
if (fs36.existsSync(path47.join(projectDir, "pyproject.toml")) || fs36.existsSync(path47.join(projectDir, "requirements.txt")) || fs36.existsSync(path47.join(projectDir, "setup.py"))) {
|
|
58272
59114
|
return { command: null, language: "python" };
|
|
58273
59115
|
}
|
|
58274
59116
|
try {
|
|
58275
|
-
const entries =
|
|
59117
|
+
const entries = fs36.readdirSync(projectDir);
|
|
58276
59118
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
58277
59119
|
return {
|
|
58278
59120
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -58606,7 +59448,8 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
|
|
|
58606
59448
|
// src/hooks/scope-guard.ts
|
|
58607
59449
|
init_constants();
|
|
58608
59450
|
init_schema();
|
|
58609
|
-
|
|
59451
|
+
init_state();
|
|
59452
|
+
import * as path49 from "path";
|
|
58610
59453
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
58611
59454
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
58612
59455
|
const enabled = config3.enabled ?? true;
|
|
@@ -58658,19 +59501,20 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
58658
59501
|
}
|
|
58659
59502
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
58660
59503
|
const dir = directory ?? process.cwd();
|
|
58661
|
-
const resolvedFile =
|
|
59504
|
+
const resolvedFile = path49.resolve(dir, filePath);
|
|
58662
59505
|
return scopeEntries.some((scope) => {
|
|
58663
|
-
const resolvedScope =
|
|
59506
|
+
const resolvedScope = path49.resolve(dir, scope);
|
|
58664
59507
|
if (resolvedFile === resolvedScope)
|
|
58665
59508
|
return true;
|
|
58666
|
-
const rel =
|
|
58667
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
59509
|
+
const rel = path49.relative(resolvedScope, resolvedFile);
|
|
59510
|
+
return rel.length > 0 && !rel.startsWith("..") && !path49.isAbsolute(rel);
|
|
58668
59511
|
});
|
|
58669
59512
|
}
|
|
58670
59513
|
|
|
58671
59514
|
// src/hooks/self-review.ts
|
|
58672
59515
|
init_constants();
|
|
58673
59516
|
init_schema();
|
|
59517
|
+
init_state();
|
|
58674
59518
|
function createSelfReviewHook(config3, injectAdvisory) {
|
|
58675
59519
|
const enabled = config3.enabled ?? true;
|
|
58676
59520
|
const skipInTurbo = config3.skip_in_turbo ?? true;
|
|
@@ -58713,8 +59557,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
58713
59557
|
}
|
|
58714
59558
|
|
|
58715
59559
|
// src/hooks/slop-detector.ts
|
|
58716
|
-
import * as
|
|
58717
|
-
import * as
|
|
59560
|
+
import * as fs38 from "fs";
|
|
59561
|
+
import * as path50 from "path";
|
|
58718
59562
|
var WRITE_EDIT_TOOLS = new Set([
|
|
58719
59563
|
"write",
|
|
58720
59564
|
"edit",
|
|
@@ -58759,12 +59603,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
58759
59603
|
function walkFiles(dir, exts, deadline) {
|
|
58760
59604
|
const results = [];
|
|
58761
59605
|
try {
|
|
58762
|
-
for (const entry of
|
|
59606
|
+
for (const entry of fs38.readdirSync(dir, { withFileTypes: true })) {
|
|
58763
59607
|
if (deadline !== undefined && Date.now() > deadline)
|
|
58764
59608
|
break;
|
|
58765
59609
|
if (entry.isSymbolicLink())
|
|
58766
59610
|
continue;
|
|
58767
|
-
const full =
|
|
59611
|
+
const full = path50.join(dir, entry.name);
|
|
58768
59612
|
if (entry.isDirectory()) {
|
|
58769
59613
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
58770
59614
|
continue;
|
|
@@ -58779,7 +59623,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58779
59623
|
return results;
|
|
58780
59624
|
}
|
|
58781
59625
|
function checkDeadExports(content, projectDir, startTime) {
|
|
58782
|
-
const hasPackageJson =
|
|
59626
|
+
const hasPackageJson = fs38.existsSync(path50.join(projectDir, "package.json"));
|
|
58783
59627
|
if (!hasPackageJson)
|
|
58784
59628
|
return null;
|
|
58785
59629
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -58802,7 +59646,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
58802
59646
|
if (found || Date.now() - startTime > 480)
|
|
58803
59647
|
break;
|
|
58804
59648
|
try {
|
|
58805
|
-
const text =
|
|
59649
|
+
const text = fs38.readFileSync(file3, "utf-8");
|
|
58806
59650
|
if (importPattern.test(text))
|
|
58807
59651
|
found = true;
|
|
58808
59652
|
importPattern.lastIndex = 0;
|
|
@@ -58935,7 +59779,7 @@ Review before proceeding.`;
|
|
|
58935
59779
|
|
|
58936
59780
|
// src/hooks/steering-consumed.ts
|
|
58937
59781
|
init_utils2();
|
|
58938
|
-
import * as
|
|
59782
|
+
import * as fs39 from "fs";
|
|
58939
59783
|
function recordSteeringConsumed(directory, directiveId) {
|
|
58940
59784
|
try {
|
|
58941
59785
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -58944,7 +59788,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
58944
59788
|
directiveId,
|
|
58945
59789
|
timestamp: new Date().toISOString()
|
|
58946
59790
|
};
|
|
58947
|
-
|
|
59791
|
+
fs39.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
58948
59792
|
`, "utf-8");
|
|
58949
59793
|
} catch {}
|
|
58950
59794
|
}
|
|
@@ -58989,6 +59833,7 @@ init_config_doctor();
|
|
|
58989
59833
|
|
|
58990
59834
|
// src/session/snapshot-reader.ts
|
|
58991
59835
|
init_utils2();
|
|
59836
|
+
init_state();
|
|
58992
59837
|
import { renameSync as renameSync13 } from "fs";
|
|
58993
59838
|
var TRANSIENT_SESSION_FIELDS = [
|
|
58994
59839
|
{ name: "revisionLimitHit", resetValue: false },
|
|
@@ -59081,6 +59926,10 @@ function deserializeAgentSession(s) {
|
|
|
59081
59926
|
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
59082
59927
|
coderRevisions: s.coderRevisions ?? 0,
|
|
59083
59928
|
revisionLimitHit: s.revisionLimitHit ?? false,
|
|
59929
|
+
fullAutoMode: s.fullAutoMode ?? false,
|
|
59930
|
+
fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
|
|
59931
|
+
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
59932
|
+
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
59084
59933
|
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
59085
59934
|
};
|
|
59086
59935
|
}
|
|
@@ -59176,19 +60025,20 @@ async function loadSnapshot(directory) {
|
|
|
59176
60025
|
}
|
|
59177
60026
|
|
|
59178
60027
|
// src/index.ts
|
|
60028
|
+
init_state();
|
|
59179
60029
|
init_telemetry();
|
|
59180
60030
|
|
|
59181
60031
|
// src/tools/batch-symbols.ts
|
|
59182
60032
|
init_tool();
|
|
59183
60033
|
init_create_tool();
|
|
59184
|
-
import * as
|
|
59185
|
-
import * as
|
|
60034
|
+
import * as fs41 from "fs";
|
|
60035
|
+
import * as path52 from "path";
|
|
59186
60036
|
|
|
59187
60037
|
// src/tools/symbols.ts
|
|
59188
60038
|
init_tool();
|
|
59189
60039
|
init_create_tool();
|
|
59190
|
-
import * as
|
|
59191
|
-
import * as
|
|
60040
|
+
import * as fs40 from "fs";
|
|
60041
|
+
import * as path51 from "path";
|
|
59192
60042
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
59193
60043
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
59194
60044
|
function containsWindowsAttacks(str) {
|
|
@@ -59205,11 +60055,11 @@ function containsWindowsAttacks(str) {
|
|
|
59205
60055
|
}
|
|
59206
60056
|
function isPathInWorkspace(filePath, workspace) {
|
|
59207
60057
|
try {
|
|
59208
|
-
const resolvedPath =
|
|
59209
|
-
const realWorkspace =
|
|
59210
|
-
const realResolvedPath =
|
|
59211
|
-
const relativePath =
|
|
59212
|
-
if (relativePath.startsWith("..") ||
|
|
60058
|
+
const resolvedPath = path51.resolve(workspace, filePath);
|
|
60059
|
+
const realWorkspace = fs40.realpathSync(workspace);
|
|
60060
|
+
const realResolvedPath = fs40.realpathSync(resolvedPath);
|
|
60061
|
+
const relativePath = path51.relative(realWorkspace, realResolvedPath);
|
|
60062
|
+
if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
|
|
59213
60063
|
return false;
|
|
59214
60064
|
}
|
|
59215
60065
|
return true;
|
|
@@ -59221,17 +60071,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
59221
60071
|
return isPathInWorkspace(filePath, workspace);
|
|
59222
60072
|
}
|
|
59223
60073
|
function extractTSSymbols(filePath, cwd) {
|
|
59224
|
-
const fullPath =
|
|
60074
|
+
const fullPath = path51.join(cwd, filePath);
|
|
59225
60075
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
59226
60076
|
return [];
|
|
59227
60077
|
}
|
|
59228
60078
|
let content;
|
|
59229
60079
|
try {
|
|
59230
|
-
const stats =
|
|
60080
|
+
const stats = fs40.statSync(fullPath);
|
|
59231
60081
|
if (stats.size > MAX_FILE_SIZE_BYTES2) {
|
|
59232
60082
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
|
|
59233
60083
|
}
|
|
59234
|
-
content =
|
|
60084
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
59235
60085
|
} catch {
|
|
59236
60086
|
return [];
|
|
59237
60087
|
}
|
|
@@ -59373,17 +60223,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
59373
60223
|
});
|
|
59374
60224
|
}
|
|
59375
60225
|
function extractPythonSymbols(filePath, cwd) {
|
|
59376
|
-
const fullPath =
|
|
60226
|
+
const fullPath = path51.join(cwd, filePath);
|
|
59377
60227
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
59378
60228
|
return [];
|
|
59379
60229
|
}
|
|
59380
60230
|
let content;
|
|
59381
60231
|
try {
|
|
59382
|
-
const stats =
|
|
60232
|
+
const stats = fs40.statSync(fullPath);
|
|
59383
60233
|
if (stats.size > MAX_FILE_SIZE_BYTES2) {
|
|
59384
60234
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
|
|
59385
60235
|
}
|
|
59386
|
-
content =
|
|
60236
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
59387
60237
|
} catch {
|
|
59388
60238
|
return [];
|
|
59389
60239
|
}
|
|
@@ -59456,7 +60306,7 @@ var symbols = createSwarmTool({
|
|
|
59456
60306
|
}, null, 2);
|
|
59457
60307
|
}
|
|
59458
60308
|
const cwd = directory;
|
|
59459
|
-
const ext =
|
|
60309
|
+
const ext = path51.extname(file3);
|
|
59460
60310
|
if (containsControlChars(file3)) {
|
|
59461
60311
|
return JSON.stringify({
|
|
59462
60312
|
file: file3,
|
|
@@ -59532,14 +60382,14 @@ function containsWindowsAttacks2(str) {
|
|
|
59532
60382
|
}
|
|
59533
60383
|
function isPathInWorkspace2(filePath, workspace) {
|
|
59534
60384
|
try {
|
|
59535
|
-
const resolvedPath =
|
|
59536
|
-
if (!
|
|
60385
|
+
const resolvedPath = path52.resolve(workspace, filePath);
|
|
60386
|
+
if (!fs41.existsSync(resolvedPath)) {
|
|
59537
60387
|
return true;
|
|
59538
60388
|
}
|
|
59539
|
-
const realWorkspace =
|
|
59540
|
-
const realResolvedPath =
|
|
59541
|
-
const relativePath =
|
|
59542
|
-
if (relativePath.startsWith("..") ||
|
|
60389
|
+
const realWorkspace = fs41.realpathSync(workspace);
|
|
60390
|
+
const realResolvedPath = fs41.realpathSync(resolvedPath);
|
|
60391
|
+
const relativePath = path52.relative(realWorkspace, realResolvedPath);
|
|
60392
|
+
if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
|
|
59543
60393
|
return false;
|
|
59544
60394
|
}
|
|
59545
60395
|
return true;
|
|
@@ -59548,7 +60398,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
59548
60398
|
}
|
|
59549
60399
|
}
|
|
59550
60400
|
function processFile(file3, cwd, exportedOnly) {
|
|
59551
|
-
const ext =
|
|
60401
|
+
const ext = path52.extname(file3);
|
|
59552
60402
|
if (containsControlChars(file3)) {
|
|
59553
60403
|
return {
|
|
59554
60404
|
file: file3,
|
|
@@ -59581,8 +60431,8 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
59581
60431
|
errorType: "path-outside-workspace"
|
|
59582
60432
|
};
|
|
59583
60433
|
}
|
|
59584
|
-
const fullPath =
|
|
59585
|
-
if (!
|
|
60434
|
+
const fullPath = path52.join(cwd, file3);
|
|
60435
|
+
if (!fs41.existsSync(fullPath)) {
|
|
59586
60436
|
return {
|
|
59587
60437
|
file: file3,
|
|
59588
60438
|
success: false,
|
|
@@ -59613,14 +60463,14 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
59613
60463
|
}
|
|
59614
60464
|
let isEmptyFile = false;
|
|
59615
60465
|
try {
|
|
59616
|
-
const stats =
|
|
60466
|
+
const stats = fs41.statSync(fullPath);
|
|
59617
60467
|
if (stats.size === 0) {
|
|
59618
60468
|
isEmptyFile = true;
|
|
59619
60469
|
}
|
|
59620
60470
|
} catch {}
|
|
59621
60471
|
if (syms.length === 0) {
|
|
59622
60472
|
try {
|
|
59623
|
-
const content =
|
|
60473
|
+
const content = fs41.readFileSync(fullPath, "utf-8");
|
|
59624
60474
|
if (content.trim().length === 0) {
|
|
59625
60475
|
isEmptyFile = true;
|
|
59626
60476
|
}
|
|
@@ -59871,8 +60721,8 @@ init_dist();
|
|
|
59871
60721
|
init_manager();
|
|
59872
60722
|
init_create_tool();
|
|
59873
60723
|
init_resolve_working_directory();
|
|
59874
|
-
import * as
|
|
59875
|
-
import * as
|
|
60724
|
+
import * as fs42 from "fs";
|
|
60725
|
+
import * as path53 from "path";
|
|
59876
60726
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
59877
60727
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
59878
60728
|
function isValidTaskId3(taskId) {
|
|
@@ -59889,18 +60739,18 @@ function isValidTaskId3(taskId) {
|
|
|
59889
60739
|
return TASK_ID_PATTERN2.test(taskId);
|
|
59890
60740
|
}
|
|
59891
60741
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
59892
|
-
const normalizedWorkspace =
|
|
59893
|
-
const swarmPath =
|
|
59894
|
-
const normalizedPath =
|
|
60742
|
+
const normalizedWorkspace = path53.resolve(workspaceRoot);
|
|
60743
|
+
const swarmPath = path53.join(normalizedWorkspace, ".swarm", "evidence");
|
|
60744
|
+
const normalizedPath = path53.resolve(filePath);
|
|
59895
60745
|
return normalizedPath.startsWith(swarmPath);
|
|
59896
60746
|
}
|
|
59897
60747
|
function readEvidenceFile(evidencePath) {
|
|
59898
|
-
if (!
|
|
60748
|
+
if (!fs42.existsSync(evidencePath)) {
|
|
59899
60749
|
return null;
|
|
59900
60750
|
}
|
|
59901
60751
|
let content;
|
|
59902
60752
|
try {
|
|
59903
|
-
content =
|
|
60753
|
+
content = fs42.readFileSync(evidencePath, "utf-8");
|
|
59904
60754
|
} catch {
|
|
59905
60755
|
return null;
|
|
59906
60756
|
}
|
|
@@ -59972,7 +60822,7 @@ var check_gate_status = createSwarmTool({
|
|
|
59972
60822
|
};
|
|
59973
60823
|
return JSON.stringify(errorResult, null, 2);
|
|
59974
60824
|
}
|
|
59975
|
-
const evidencePath =
|
|
60825
|
+
const evidencePath = path53.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
59976
60826
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
59977
60827
|
const errorResult = {
|
|
59978
60828
|
taskId: taskIdInput,
|
|
@@ -60065,10 +60915,11 @@ init_co_change_analyzer();
|
|
|
60065
60915
|
// src/tools/completion-verify.ts
|
|
60066
60916
|
init_dist();
|
|
60067
60917
|
init_utils2();
|
|
60068
|
-
|
|
60069
|
-
import * as path53 from "path";
|
|
60918
|
+
init_state();
|
|
60070
60919
|
init_create_tool();
|
|
60071
60920
|
init_resolve_working_directory();
|
|
60921
|
+
import * as fs43 from "fs";
|
|
60922
|
+
import * as path54 from "path";
|
|
60072
60923
|
function extractMatches(regex, text) {
|
|
60073
60924
|
return Array.from(text.matchAll(regex));
|
|
60074
60925
|
}
|
|
@@ -60162,7 +61013,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60162
61013
|
let plan;
|
|
60163
61014
|
try {
|
|
60164
61015
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
60165
|
-
const planRaw =
|
|
61016
|
+
const planRaw = fs43.readFileSync(planPath, "utf-8");
|
|
60166
61017
|
plan = JSON.parse(planRaw);
|
|
60167
61018
|
} catch {
|
|
60168
61019
|
const result2 = {
|
|
@@ -60220,10 +61071,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60220
61071
|
let hasFileReadFailure = false;
|
|
60221
61072
|
for (const filePath of fileTargets) {
|
|
60222
61073
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
60223
|
-
const resolvedPath =
|
|
60224
|
-
const projectRoot =
|
|
60225
|
-
const relative9 =
|
|
60226
|
-
const withinProject = relative9 === "" || !relative9.startsWith("..") && !
|
|
61074
|
+
const resolvedPath = path54.resolve(directory, normalizedPath);
|
|
61075
|
+
const projectRoot = path54.resolve(directory);
|
|
61076
|
+
const relative9 = path54.relative(projectRoot, resolvedPath);
|
|
61077
|
+
const withinProject = relative9 === "" || !relative9.startsWith("..") && !path54.isAbsolute(relative9);
|
|
60227
61078
|
if (!withinProject) {
|
|
60228
61079
|
blockedTasks.push({
|
|
60229
61080
|
task_id: task.id,
|
|
@@ -60236,7 +61087,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60236
61087
|
}
|
|
60237
61088
|
let fileContent;
|
|
60238
61089
|
try {
|
|
60239
|
-
fileContent =
|
|
61090
|
+
fileContent = fs43.readFileSync(resolvedPath, "utf-8");
|
|
60240
61091
|
} catch {
|
|
60241
61092
|
blockedTasks.push({
|
|
60242
61093
|
task_id: task.id,
|
|
@@ -60278,9 +61129,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60278
61129
|
blockedTasks
|
|
60279
61130
|
};
|
|
60280
61131
|
try {
|
|
60281
|
-
const evidenceDir =
|
|
60282
|
-
const evidencePath =
|
|
60283
|
-
|
|
61132
|
+
const evidenceDir = path54.join(directory, ".swarm", "evidence", `${phase}`);
|
|
61133
|
+
const evidencePath = path54.join(evidenceDir, "completion-verify.json");
|
|
61134
|
+
fs43.mkdirSync(evidenceDir, { recursive: true });
|
|
60284
61135
|
const evidenceBundle = {
|
|
60285
61136
|
schema_version: "1.0.0",
|
|
60286
61137
|
task_id: "completion-verify",
|
|
@@ -60301,7 +61152,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60301
61152
|
}
|
|
60302
61153
|
]
|
|
60303
61154
|
};
|
|
60304
|
-
|
|
61155
|
+
fs43.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
60305
61156
|
} catch {}
|
|
60306
61157
|
return JSON.stringify(result, null, 2);
|
|
60307
61158
|
}
|
|
@@ -60355,12 +61206,12 @@ var completion_verify = createSwarmTool({
|
|
|
60355
61206
|
});
|
|
60356
61207
|
// src/tools/complexity-hotspots.ts
|
|
60357
61208
|
init_dist();
|
|
60358
|
-
import * as
|
|
60359
|
-
import * as
|
|
61209
|
+
import * as fs45 from "fs";
|
|
61210
|
+
import * as path56 from "path";
|
|
60360
61211
|
|
|
60361
61212
|
// src/quality/metrics.ts
|
|
60362
|
-
import * as
|
|
60363
|
-
import * as
|
|
61213
|
+
import * as fs44 from "fs";
|
|
61214
|
+
import * as path55 from "path";
|
|
60364
61215
|
var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
|
|
60365
61216
|
var MIN_DUPLICATION_LINES = 10;
|
|
60366
61217
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -60398,11 +61249,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
60398
61249
|
}
|
|
60399
61250
|
function getComplexityForFile(filePath) {
|
|
60400
61251
|
try {
|
|
60401
|
-
const stat2 =
|
|
61252
|
+
const stat2 = fs44.statSync(filePath);
|
|
60402
61253
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
60403
61254
|
return null;
|
|
60404
61255
|
}
|
|
60405
|
-
const content =
|
|
61256
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
60406
61257
|
return estimateCyclomaticComplexity(content);
|
|
60407
61258
|
} catch {
|
|
60408
61259
|
return null;
|
|
@@ -60412,8 +61263,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
60412
61263
|
let totalComplexity = 0;
|
|
60413
61264
|
const analyzedFiles = [];
|
|
60414
61265
|
for (const file3 of files) {
|
|
60415
|
-
const fullPath =
|
|
60416
|
-
if (!
|
|
61266
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61267
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60417
61268
|
continue;
|
|
60418
61269
|
}
|
|
60419
61270
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -60534,8 +61385,8 @@ function countGoExports(content) {
|
|
|
60534
61385
|
}
|
|
60535
61386
|
function getExportCountForFile(filePath) {
|
|
60536
61387
|
try {
|
|
60537
|
-
const content =
|
|
60538
|
-
const ext =
|
|
61388
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
61389
|
+
const ext = path55.extname(filePath).toLowerCase();
|
|
60539
61390
|
switch (ext) {
|
|
60540
61391
|
case ".ts":
|
|
60541
61392
|
case ".tsx":
|
|
@@ -60561,8 +61412,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
60561
61412
|
let totalExports = 0;
|
|
60562
61413
|
const analyzedFiles = [];
|
|
60563
61414
|
for (const file3 of files) {
|
|
60564
|
-
const fullPath =
|
|
60565
|
-
if (!
|
|
61415
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61416
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60566
61417
|
continue;
|
|
60567
61418
|
}
|
|
60568
61419
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -60595,16 +61446,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
60595
61446
|
let duplicateLines = 0;
|
|
60596
61447
|
const analyzedFiles = [];
|
|
60597
61448
|
for (const file3 of files) {
|
|
60598
|
-
const fullPath =
|
|
60599
|
-
if (!
|
|
61449
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61450
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60600
61451
|
continue;
|
|
60601
61452
|
}
|
|
60602
61453
|
try {
|
|
60603
|
-
const stat2 =
|
|
61454
|
+
const stat2 = fs44.statSync(fullPath);
|
|
60604
61455
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
60605
61456
|
continue;
|
|
60606
61457
|
}
|
|
60607
|
-
const content =
|
|
61458
|
+
const content = fs44.readFileSync(fullPath, "utf-8");
|
|
60608
61459
|
const lines = content.split(`
|
|
60609
61460
|
`).filter((line) => line.trim().length > 0);
|
|
60610
61461
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -60628,8 +61479,8 @@ function countCodeLines(content) {
|
|
|
60628
61479
|
return lines.length;
|
|
60629
61480
|
}
|
|
60630
61481
|
function isTestFile(filePath) {
|
|
60631
|
-
const basename8 =
|
|
60632
|
-
const _ext =
|
|
61482
|
+
const basename8 = path55.basename(filePath);
|
|
61483
|
+
const _ext = path55.extname(filePath).toLowerCase();
|
|
60633
61484
|
const testPatterns = [
|
|
60634
61485
|
".test.",
|
|
60635
61486
|
".spec.",
|
|
@@ -60710,8 +61561,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
60710
61561
|
}
|
|
60711
61562
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
60712
61563
|
}
|
|
60713
|
-
function matchesGlobSegment(
|
|
60714
|
-
const normalizedPath =
|
|
61564
|
+
function matchesGlobSegment(path56, glob) {
|
|
61565
|
+
const normalizedPath = path56.replace(/\\/g, "/");
|
|
60715
61566
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
60716
61567
|
if (normalizedPath.includes("//")) {
|
|
60717
61568
|
return false;
|
|
@@ -60742,8 +61593,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
60742
61593
|
function hasGlobstar(glob) {
|
|
60743
61594
|
return glob.includes("**");
|
|
60744
61595
|
}
|
|
60745
|
-
function globMatches(
|
|
60746
|
-
const normalizedPath =
|
|
61596
|
+
function globMatches(path56, glob) {
|
|
61597
|
+
const normalizedPath = path56.replace(/\\/g, "/");
|
|
60747
61598
|
if (!glob || glob === "") {
|
|
60748
61599
|
if (normalizedPath.includes("//")) {
|
|
60749
61600
|
return false;
|
|
@@ -60779,31 +61630,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
60779
61630
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
60780
61631
|
let testLines = 0;
|
|
60781
61632
|
let codeLines = 0;
|
|
60782
|
-
const srcDir =
|
|
60783
|
-
if (
|
|
61633
|
+
const srcDir = path55.join(workingDir, "src");
|
|
61634
|
+
if (fs44.existsSync(srcDir)) {
|
|
60784
61635
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60785
61636
|
codeLines += lines;
|
|
60786
61637
|
});
|
|
60787
61638
|
}
|
|
60788
61639
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
60789
61640
|
for (const dir of possibleSrcDirs) {
|
|
60790
|
-
const dirPath =
|
|
60791
|
-
if (
|
|
61641
|
+
const dirPath = path55.join(workingDir, dir);
|
|
61642
|
+
if (fs44.existsSync(dirPath)) {
|
|
60792
61643
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60793
61644
|
codeLines += lines;
|
|
60794
61645
|
});
|
|
60795
61646
|
}
|
|
60796
61647
|
}
|
|
60797
|
-
const testsDir =
|
|
60798
|
-
if (
|
|
61648
|
+
const testsDir = path55.join(workingDir, "tests");
|
|
61649
|
+
if (fs44.existsSync(testsDir)) {
|
|
60799
61650
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60800
61651
|
testLines += lines;
|
|
60801
61652
|
});
|
|
60802
61653
|
}
|
|
60803
61654
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
60804
61655
|
for (const dir of possibleTestDirs) {
|
|
60805
|
-
const dirPath =
|
|
60806
|
-
if (
|
|
61656
|
+
const dirPath = path55.join(workingDir, dir);
|
|
61657
|
+
if (fs44.existsSync(dirPath) && dirPath !== testsDir) {
|
|
60807
61658
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60808
61659
|
testLines += lines;
|
|
60809
61660
|
});
|
|
@@ -60815,9 +61666,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60815
61666
|
}
|
|
60816
61667
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
60817
61668
|
try {
|
|
60818
|
-
const entries =
|
|
61669
|
+
const entries = fs44.readdirSync(dirPath, { withFileTypes: true });
|
|
60819
61670
|
for (const entry of entries) {
|
|
60820
|
-
const fullPath =
|
|
61671
|
+
const fullPath = path55.join(dirPath, entry.name);
|
|
60821
61672
|
if (entry.isDirectory()) {
|
|
60822
61673
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
60823
61674
|
continue;
|
|
@@ -60825,7 +61676,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60825
61676
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
60826
61677
|
} else if (entry.isFile()) {
|
|
60827
61678
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
60828
|
-
const ext =
|
|
61679
|
+
const ext = path55.extname(entry.name).toLowerCase();
|
|
60829
61680
|
const validExts = [
|
|
60830
61681
|
".ts",
|
|
60831
61682
|
".tsx",
|
|
@@ -60861,7 +61712,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60861
61712
|
continue;
|
|
60862
61713
|
}
|
|
60863
61714
|
try {
|
|
60864
|
-
const content =
|
|
61715
|
+
const content = fs44.readFileSync(fullPath, "utf-8");
|
|
60865
61716
|
const lines = countCodeLines(content);
|
|
60866
61717
|
callback(lines);
|
|
60867
61718
|
} catch {}
|
|
@@ -61062,11 +61913,11 @@ async function getGitChurn(days, directory) {
|
|
|
61062
61913
|
}
|
|
61063
61914
|
function getComplexityForFile2(filePath) {
|
|
61064
61915
|
try {
|
|
61065
|
-
const stat2 =
|
|
61916
|
+
const stat2 = fs45.statSync(filePath);
|
|
61066
61917
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
61067
61918
|
return null;
|
|
61068
61919
|
}
|
|
61069
|
-
const content =
|
|
61920
|
+
const content = fs45.readFileSync(filePath, "utf-8");
|
|
61070
61921
|
return estimateCyclomaticComplexity(content);
|
|
61071
61922
|
} catch {
|
|
61072
61923
|
return null;
|
|
@@ -61077,7 +61928,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
61077
61928
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
61078
61929
|
const filteredChurn = new Map;
|
|
61079
61930
|
for (const [file3, count] of churnMap) {
|
|
61080
|
-
const ext =
|
|
61931
|
+
const ext = path56.extname(file3).toLowerCase();
|
|
61081
61932
|
if (extSet.has(ext)) {
|
|
61082
61933
|
filteredChurn.set(file3, count);
|
|
61083
61934
|
}
|
|
@@ -61087,8 +61938,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
61087
61938
|
let analyzedFiles = 0;
|
|
61088
61939
|
for (const [file3, churnCount] of filteredChurn) {
|
|
61089
61940
|
let fullPath = file3;
|
|
61090
|
-
if (!
|
|
61091
|
-
fullPath =
|
|
61941
|
+
if (!fs45.existsSync(fullPath)) {
|
|
61942
|
+
fullPath = path56.join(cwd, file3);
|
|
61092
61943
|
}
|
|
61093
61944
|
const complexity = getComplexityForFile2(fullPath);
|
|
61094
61945
|
if (complexity !== null) {
|
|
@@ -61352,9 +62203,10 @@ var curator_analyze = createSwarmTool({
|
|
|
61352
62203
|
});
|
|
61353
62204
|
// src/tools/declare-scope.ts
|
|
61354
62205
|
init_tool();
|
|
61355
|
-
|
|
61356
|
-
import * as path56 from "path";
|
|
62206
|
+
init_state();
|
|
61357
62207
|
init_create_tool();
|
|
62208
|
+
import * as fs46 from "fs";
|
|
62209
|
+
import * as path57 from "path";
|
|
61358
62210
|
function validateTaskIdFormat(taskId) {
|
|
61359
62211
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
61360
62212
|
if (!taskIdPattern.test(taskId)) {
|
|
@@ -61432,8 +62284,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61432
62284
|
};
|
|
61433
62285
|
}
|
|
61434
62286
|
}
|
|
61435
|
-
normalizedDir =
|
|
61436
|
-
const pathParts = normalizedDir.split(
|
|
62287
|
+
normalizedDir = path57.normalize(args2.working_directory);
|
|
62288
|
+
const pathParts = normalizedDir.split(path57.sep);
|
|
61437
62289
|
if (pathParts.includes("..")) {
|
|
61438
62290
|
return {
|
|
61439
62291
|
success: false,
|
|
@@ -61443,11 +62295,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61443
62295
|
]
|
|
61444
62296
|
};
|
|
61445
62297
|
}
|
|
61446
|
-
const resolvedDir =
|
|
62298
|
+
const resolvedDir = path57.resolve(normalizedDir);
|
|
61447
62299
|
try {
|
|
61448
|
-
const realPath =
|
|
61449
|
-
const planPath2 =
|
|
61450
|
-
if (!
|
|
62300
|
+
const realPath = fs46.realpathSync(resolvedDir);
|
|
62301
|
+
const planPath2 = path57.join(realPath, ".swarm", "plan.json");
|
|
62302
|
+
if (!fs46.existsSync(planPath2)) {
|
|
61451
62303
|
return {
|
|
61452
62304
|
success: false,
|
|
61453
62305
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -61470,8 +62322,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61470
62322
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
61471
62323
|
}
|
|
61472
62324
|
const directory = normalizedDir || fallbackDir;
|
|
61473
|
-
const planPath =
|
|
61474
|
-
if (!
|
|
62325
|
+
const planPath = path57.resolve(directory, ".swarm", "plan.json");
|
|
62326
|
+
if (!fs46.existsSync(planPath)) {
|
|
61475
62327
|
return {
|
|
61476
62328
|
success: false,
|
|
61477
62329
|
message: "No plan found",
|
|
@@ -61480,7 +62332,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61480
62332
|
}
|
|
61481
62333
|
let planContent;
|
|
61482
62334
|
try {
|
|
61483
|
-
planContent = JSON.parse(
|
|
62335
|
+
planContent = JSON.parse(fs46.readFileSync(planPath, "utf-8"));
|
|
61484
62336
|
} catch {
|
|
61485
62337
|
return {
|
|
61486
62338
|
success: false,
|
|
@@ -61512,8 +62364,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61512
62364
|
const normalizeErrors = [];
|
|
61513
62365
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
61514
62366
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
61515
|
-
if (
|
|
61516
|
-
const relativePath =
|
|
62367
|
+
if (path57.isAbsolute(file3)) {
|
|
62368
|
+
const relativePath = path57.relative(dir, file3).replace(/\\/g, "/");
|
|
61517
62369
|
if (relativePath.startsWith("..")) {
|
|
61518
62370
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
61519
62371
|
return file3;
|
|
@@ -61852,20 +62704,20 @@ function validateBase(base) {
|
|
|
61852
62704
|
function validatePaths(paths) {
|
|
61853
62705
|
if (!paths)
|
|
61854
62706
|
return null;
|
|
61855
|
-
for (const
|
|
61856
|
-
if (!
|
|
62707
|
+
for (const path59 of paths) {
|
|
62708
|
+
if (!path59 || path59.length === 0) {
|
|
61857
62709
|
return "empty path not allowed";
|
|
61858
62710
|
}
|
|
61859
|
-
if (
|
|
62711
|
+
if (path59.length > MAX_PATH_LENGTH) {
|
|
61860
62712
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
61861
62713
|
}
|
|
61862
|
-
if (SHELL_METACHARACTERS2.test(
|
|
62714
|
+
if (SHELL_METACHARACTERS2.test(path59)) {
|
|
61863
62715
|
return "path contains shell metacharacters";
|
|
61864
62716
|
}
|
|
61865
|
-
if (
|
|
62717
|
+
if (path59.startsWith("-")) {
|
|
61866
62718
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
61867
62719
|
}
|
|
61868
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
62720
|
+
if (CONTROL_CHAR_PATTERN2.test(path59)) {
|
|
61869
62721
|
return "path contains control characters";
|
|
61870
62722
|
}
|
|
61871
62723
|
}
|
|
@@ -61946,8 +62798,8 @@ var diff = createSwarmTool({
|
|
|
61946
62798
|
if (parts2.length >= 3) {
|
|
61947
62799
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
61948
62800
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
61949
|
-
const
|
|
61950
|
-
files.push({ path:
|
|
62801
|
+
const path59 = parts2[2];
|
|
62802
|
+
files.push({ path: path59, additions, deletions });
|
|
61951
62803
|
}
|
|
61952
62804
|
}
|
|
61953
62805
|
const contractChanges = [];
|
|
@@ -62229,8 +63081,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
62229
63081
|
// src/tools/evidence-check.ts
|
|
62230
63082
|
init_dist();
|
|
62231
63083
|
init_create_tool();
|
|
62232
|
-
import * as
|
|
62233
|
-
import * as
|
|
63084
|
+
import * as fs47 from "fs";
|
|
63085
|
+
import * as path59 from "path";
|
|
62234
63086
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
62235
63087
|
var MAX_EVIDENCE_FILES = 1000;
|
|
62236
63088
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -62257,9 +63109,9 @@ function validateRequiredTypes(input) {
|
|
|
62257
63109
|
return null;
|
|
62258
63110
|
}
|
|
62259
63111
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
62260
|
-
const normalizedCwd =
|
|
62261
|
-
const swarmPath =
|
|
62262
|
-
const normalizedPath =
|
|
63112
|
+
const normalizedCwd = path59.resolve(cwd);
|
|
63113
|
+
const swarmPath = path59.join(normalizedCwd, ".swarm");
|
|
63114
|
+
const normalizedPath = path59.resolve(filePath);
|
|
62263
63115
|
return normalizedPath.startsWith(swarmPath);
|
|
62264
63116
|
}
|
|
62265
63117
|
function parseCompletedTasks(planContent) {
|
|
@@ -62275,12 +63127,12 @@ function parseCompletedTasks(planContent) {
|
|
|
62275
63127
|
}
|
|
62276
63128
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
62277
63129
|
const evidence = [];
|
|
62278
|
-
if (!
|
|
63130
|
+
if (!fs47.existsSync(evidenceDir) || !fs47.statSync(evidenceDir).isDirectory()) {
|
|
62279
63131
|
return evidence;
|
|
62280
63132
|
}
|
|
62281
63133
|
let files;
|
|
62282
63134
|
try {
|
|
62283
|
-
files =
|
|
63135
|
+
files = fs47.readdirSync(evidenceDir);
|
|
62284
63136
|
} catch {
|
|
62285
63137
|
return evidence;
|
|
62286
63138
|
}
|
|
@@ -62289,14 +63141,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62289
63141
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
62290
63142
|
continue;
|
|
62291
63143
|
}
|
|
62292
|
-
const filePath =
|
|
63144
|
+
const filePath = path59.join(evidenceDir, filename);
|
|
62293
63145
|
try {
|
|
62294
|
-
const resolvedPath =
|
|
62295
|
-
const evidenceDirResolved =
|
|
63146
|
+
const resolvedPath = path59.resolve(filePath);
|
|
63147
|
+
const evidenceDirResolved = path59.resolve(evidenceDir);
|
|
62296
63148
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
62297
63149
|
continue;
|
|
62298
63150
|
}
|
|
62299
|
-
const stat2 =
|
|
63151
|
+
const stat2 = fs47.lstatSync(filePath);
|
|
62300
63152
|
if (!stat2.isFile()) {
|
|
62301
63153
|
continue;
|
|
62302
63154
|
}
|
|
@@ -62305,7 +63157,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62305
63157
|
}
|
|
62306
63158
|
let fileStat;
|
|
62307
63159
|
try {
|
|
62308
|
-
fileStat =
|
|
63160
|
+
fileStat = fs47.statSync(filePath);
|
|
62309
63161
|
if (fileStat.size > MAX_FILE_SIZE_BYTES5) {
|
|
62310
63162
|
continue;
|
|
62311
63163
|
}
|
|
@@ -62314,7 +63166,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62314
63166
|
}
|
|
62315
63167
|
let content;
|
|
62316
63168
|
try {
|
|
62317
|
-
content =
|
|
63169
|
+
content = fs47.readFileSync(filePath, "utf-8");
|
|
62318
63170
|
} catch {
|
|
62319
63171
|
continue;
|
|
62320
63172
|
}
|
|
@@ -62410,7 +63262,7 @@ var evidence_check = createSwarmTool({
|
|
|
62410
63262
|
return JSON.stringify(errorResult, null, 2);
|
|
62411
63263
|
}
|
|
62412
63264
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
62413
|
-
const planPath =
|
|
63265
|
+
const planPath = path59.join(cwd, PLAN_FILE);
|
|
62414
63266
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
62415
63267
|
const errorResult = {
|
|
62416
63268
|
error: "plan file path validation failed",
|
|
@@ -62424,7 +63276,7 @@ var evidence_check = createSwarmTool({
|
|
|
62424
63276
|
}
|
|
62425
63277
|
let planContent;
|
|
62426
63278
|
try {
|
|
62427
|
-
planContent =
|
|
63279
|
+
planContent = fs47.readFileSync(planPath, "utf-8");
|
|
62428
63280
|
} catch {
|
|
62429
63281
|
const result2 = {
|
|
62430
63282
|
message: "No completed tasks found in plan.",
|
|
@@ -62442,7 +63294,7 @@ var evidence_check = createSwarmTool({
|
|
|
62442
63294
|
};
|
|
62443
63295
|
return JSON.stringify(result2, null, 2);
|
|
62444
63296
|
}
|
|
62445
|
-
const evidenceDir =
|
|
63297
|
+
const evidenceDir = path59.join(cwd, EVIDENCE_DIR2);
|
|
62446
63298
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
62447
63299
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
62448
63300
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -62459,8 +63311,8 @@ var evidence_check = createSwarmTool({
|
|
|
62459
63311
|
// src/tools/file-extractor.ts
|
|
62460
63312
|
init_tool();
|
|
62461
63313
|
init_create_tool();
|
|
62462
|
-
import * as
|
|
62463
|
-
import * as
|
|
63314
|
+
import * as fs48 from "fs";
|
|
63315
|
+
import * as path60 from "path";
|
|
62464
63316
|
var EXT_MAP = {
|
|
62465
63317
|
python: ".py",
|
|
62466
63318
|
py: ".py",
|
|
@@ -62522,8 +63374,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
62522
63374
|
execute: async (args2, directory) => {
|
|
62523
63375
|
const { content, output_dir, prefix } = args2;
|
|
62524
63376
|
const targetDir = output_dir || directory;
|
|
62525
|
-
if (!
|
|
62526
|
-
|
|
63377
|
+
if (!fs48.existsSync(targetDir)) {
|
|
63378
|
+
fs48.mkdirSync(targetDir, { recursive: true });
|
|
62527
63379
|
}
|
|
62528
63380
|
if (!content) {
|
|
62529
63381
|
return "Error: content is required";
|
|
@@ -62541,16 +63393,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
62541
63393
|
if (prefix) {
|
|
62542
63394
|
filename = `${prefix}_${filename}`;
|
|
62543
63395
|
}
|
|
62544
|
-
let filepath =
|
|
62545
|
-
const base =
|
|
62546
|
-
const ext =
|
|
63396
|
+
let filepath = path60.join(targetDir, filename);
|
|
63397
|
+
const base = path60.basename(filepath, path60.extname(filepath));
|
|
63398
|
+
const ext = path60.extname(filepath);
|
|
62547
63399
|
let counter = 1;
|
|
62548
|
-
while (
|
|
62549
|
-
filepath =
|
|
63400
|
+
while (fs48.existsSync(filepath)) {
|
|
63401
|
+
filepath = path60.join(targetDir, `${base}_${counter}${ext}`);
|
|
62550
63402
|
counter++;
|
|
62551
63403
|
}
|
|
62552
63404
|
try {
|
|
62553
|
-
|
|
63405
|
+
fs48.writeFileSync(filepath, code.trim(), "utf-8");
|
|
62554
63406
|
savedFiles.push(filepath);
|
|
62555
63407
|
} catch (error93) {
|
|
62556
63408
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -62580,7 +63432,7 @@ init_create_tool();
|
|
|
62580
63432
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
62581
63433
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
62582
63434
|
var GITINGEST_MAX_RETRIES = 2;
|
|
62583
|
-
var delay = (ms) => new Promise((
|
|
63435
|
+
var delay = (ms) => new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
62584
63436
|
async function fetchGitingest(args2) {
|
|
62585
63437
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
62586
63438
|
try {
|
|
@@ -62666,8 +63518,8 @@ var gitingest = createSwarmTool({
|
|
|
62666
63518
|
// src/tools/imports.ts
|
|
62667
63519
|
init_dist();
|
|
62668
63520
|
init_create_tool();
|
|
62669
|
-
import * as
|
|
62670
|
-
import * as
|
|
63521
|
+
import * as fs49 from "fs";
|
|
63522
|
+
import * as path61 from "path";
|
|
62671
63523
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
62672
63524
|
var MAX_SYMBOL_LENGTH = 256;
|
|
62673
63525
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
@@ -62715,7 +63567,7 @@ function validateSymbolInput(symbol3) {
|
|
|
62715
63567
|
return null;
|
|
62716
63568
|
}
|
|
62717
63569
|
function isBinaryFile2(filePath, buffer) {
|
|
62718
|
-
const ext =
|
|
63570
|
+
const ext = path61.extname(filePath).toLowerCase();
|
|
62719
63571
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
62720
63572
|
return false;
|
|
62721
63573
|
}
|
|
@@ -62739,15 +63591,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62739
63591
|
const imports = [];
|
|
62740
63592
|
let _resolvedTarget;
|
|
62741
63593
|
try {
|
|
62742
|
-
_resolvedTarget =
|
|
63594
|
+
_resolvedTarget = path61.resolve(targetFile);
|
|
62743
63595
|
} catch {
|
|
62744
63596
|
_resolvedTarget = targetFile;
|
|
62745
63597
|
}
|
|
62746
|
-
const targetBasename =
|
|
63598
|
+
const targetBasename = path61.basename(targetFile, path61.extname(targetFile));
|
|
62747
63599
|
const targetWithExt = targetFile;
|
|
62748
63600
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
62749
|
-
const normalizedTargetWithExt =
|
|
62750
|
-
const normalizedTargetWithoutExt =
|
|
63601
|
+
const normalizedTargetWithExt = path61.normalize(targetWithExt).replace(/\\/g, "/");
|
|
63602
|
+
const normalizedTargetWithoutExt = path61.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
62751
63603
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
62752
63604
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
62753
63605
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -62770,9 +63622,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62770
63622
|
}
|
|
62771
63623
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
62772
63624
|
let isMatch = false;
|
|
62773
|
-
const _targetDir =
|
|
62774
|
-
const targetExt =
|
|
62775
|
-
const targetBasenameNoExt =
|
|
63625
|
+
const _targetDir = path61.dirname(targetFile);
|
|
63626
|
+
const targetExt = path61.extname(targetFile);
|
|
63627
|
+
const targetBasenameNoExt = path61.basename(targetFile, targetExt);
|
|
62776
63628
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
62777
63629
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
62778
63630
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -62829,7 +63681,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
62829
63681
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
62830
63682
|
let entries;
|
|
62831
63683
|
try {
|
|
62832
|
-
entries =
|
|
63684
|
+
entries = fs49.readdirSync(dir);
|
|
62833
63685
|
} catch (e) {
|
|
62834
63686
|
stats.fileErrors.push({
|
|
62835
63687
|
path: dir,
|
|
@@ -62840,13 +63692,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62840
63692
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
62841
63693
|
for (const entry of entries) {
|
|
62842
63694
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62843
|
-
stats.skippedDirs.push(
|
|
63695
|
+
stats.skippedDirs.push(path61.join(dir, entry));
|
|
62844
63696
|
continue;
|
|
62845
63697
|
}
|
|
62846
|
-
const fullPath =
|
|
63698
|
+
const fullPath = path61.join(dir, entry);
|
|
62847
63699
|
let stat2;
|
|
62848
63700
|
try {
|
|
62849
|
-
stat2 =
|
|
63701
|
+
stat2 = fs49.statSync(fullPath);
|
|
62850
63702
|
} catch (e) {
|
|
62851
63703
|
stats.fileErrors.push({
|
|
62852
63704
|
path: fullPath,
|
|
@@ -62857,7 +63709,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62857
63709
|
if (stat2.isDirectory()) {
|
|
62858
63710
|
findSourceFiles(fullPath, files, stats);
|
|
62859
63711
|
} else if (stat2.isFile()) {
|
|
62860
|
-
const ext =
|
|
63712
|
+
const ext = path61.extname(fullPath).toLowerCase();
|
|
62861
63713
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
62862
63714
|
files.push(fullPath);
|
|
62863
63715
|
}
|
|
@@ -62914,8 +63766,8 @@ var imports = createSwarmTool({
|
|
|
62914
63766
|
return JSON.stringify(errorResult, null, 2);
|
|
62915
63767
|
}
|
|
62916
63768
|
try {
|
|
62917
|
-
const targetFile =
|
|
62918
|
-
if (!
|
|
63769
|
+
const targetFile = path61.resolve(file3);
|
|
63770
|
+
if (!fs49.existsSync(targetFile)) {
|
|
62919
63771
|
const errorResult = {
|
|
62920
63772
|
error: `target file not found: ${file3}`,
|
|
62921
63773
|
target: file3,
|
|
@@ -62925,7 +63777,7 @@ var imports = createSwarmTool({
|
|
|
62925
63777
|
};
|
|
62926
63778
|
return JSON.stringify(errorResult, null, 2);
|
|
62927
63779
|
}
|
|
62928
|
-
const targetStat =
|
|
63780
|
+
const targetStat = fs49.statSync(targetFile);
|
|
62929
63781
|
if (!targetStat.isFile()) {
|
|
62930
63782
|
const errorResult = {
|
|
62931
63783
|
error: "target must be a file, not a directory",
|
|
@@ -62936,7 +63788,7 @@ var imports = createSwarmTool({
|
|
|
62936
63788
|
};
|
|
62937
63789
|
return JSON.stringify(errorResult, null, 2);
|
|
62938
63790
|
}
|
|
62939
|
-
const baseDir =
|
|
63791
|
+
const baseDir = path61.dirname(targetFile);
|
|
62940
63792
|
const scanStats = {
|
|
62941
63793
|
skippedDirs: [],
|
|
62942
63794
|
skippedFiles: 0,
|
|
@@ -62951,12 +63803,12 @@ var imports = createSwarmTool({
|
|
|
62951
63803
|
if (consumers.length >= MAX_CONSUMERS)
|
|
62952
63804
|
break;
|
|
62953
63805
|
try {
|
|
62954
|
-
const stat2 =
|
|
63806
|
+
const stat2 = fs49.statSync(filePath);
|
|
62955
63807
|
if (stat2.size > MAX_FILE_SIZE_BYTES6) {
|
|
62956
63808
|
skippedFileCount++;
|
|
62957
63809
|
continue;
|
|
62958
63810
|
}
|
|
62959
|
-
const buffer =
|
|
63811
|
+
const buffer = fs49.readFileSync(filePath);
|
|
62960
63812
|
if (isBinaryFile2(filePath, buffer)) {
|
|
62961
63813
|
skippedFileCount++;
|
|
62962
63814
|
continue;
|
|
@@ -63156,7 +64008,7 @@ init_dist();
|
|
|
63156
64008
|
init_config();
|
|
63157
64009
|
init_knowledge_store();
|
|
63158
64010
|
init_create_tool();
|
|
63159
|
-
import { existsSync as
|
|
64011
|
+
import { existsSync as existsSync39 } from "fs";
|
|
63160
64012
|
var DEFAULT_LIMIT = 10;
|
|
63161
64013
|
var MAX_LESSON_LENGTH = 200;
|
|
63162
64014
|
var VALID_CATEGORIES3 = [
|
|
@@ -63225,14 +64077,14 @@ function validateLimit(limit) {
|
|
|
63225
64077
|
}
|
|
63226
64078
|
async function readSwarmKnowledge(directory) {
|
|
63227
64079
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
63228
|
-
if (!
|
|
64080
|
+
if (!existsSync39(swarmPath)) {
|
|
63229
64081
|
return [];
|
|
63230
64082
|
}
|
|
63231
64083
|
return readKnowledge(swarmPath);
|
|
63232
64084
|
}
|
|
63233
64085
|
async function readHiveKnowledge() {
|
|
63234
64086
|
const hivePath = resolveHiveKnowledgePath();
|
|
63235
|
-
if (!
|
|
64087
|
+
if (!existsSync39(hivePath)) {
|
|
63236
64088
|
return [];
|
|
63237
64089
|
}
|
|
63238
64090
|
return readKnowledge(hivePath);
|
|
@@ -63545,62 +64397,13 @@ init_dist();
|
|
|
63545
64397
|
init_config();
|
|
63546
64398
|
init_schema();
|
|
63547
64399
|
init_manager();
|
|
63548
|
-
import * as
|
|
64400
|
+
import * as fs50 from "fs";
|
|
63549
64401
|
import * as path62 from "path";
|
|
63550
64402
|
init_review_receipt();
|
|
63551
64403
|
init_utils2();
|
|
63552
|
-
|
|
63553
|
-
// src/parallel/file-locks.ts
|
|
63554
|
-
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
63555
|
-
import * as fs48 from "fs";
|
|
63556
|
-
import * as path61 from "path";
|
|
63557
|
-
var LOCKS_DIR = ".swarm/locks";
|
|
63558
|
-
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
63559
|
-
function getLockFilePath(directory, filePath) {
|
|
63560
|
-
const normalized = path61.resolve(directory, filePath);
|
|
63561
|
-
if (!normalized.startsWith(path61.resolve(directory))) {
|
|
63562
|
-
throw new Error("Invalid file path: path traversal not allowed");
|
|
63563
|
-
}
|
|
63564
|
-
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
63565
|
-
return path61.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
63566
|
-
}
|
|
63567
|
-
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
63568
|
-
const lockPath = getLockFilePath(directory, filePath);
|
|
63569
|
-
const locksDir = path61.dirname(lockPath);
|
|
63570
|
-
if (!fs48.existsSync(locksDir)) {
|
|
63571
|
-
fs48.mkdirSync(locksDir, { recursive: true });
|
|
63572
|
-
}
|
|
63573
|
-
if (!fs48.existsSync(lockPath)) {
|
|
63574
|
-
fs48.writeFileSync(lockPath, "", "utf-8");
|
|
63575
|
-
}
|
|
63576
|
-
let release;
|
|
63577
|
-
try {
|
|
63578
|
-
release = await import_proper_lockfile3.default.lock(lockPath, {
|
|
63579
|
-
stale: LOCK_TIMEOUT_MS,
|
|
63580
|
-
retries: { retries: 0 },
|
|
63581
|
-
realpath: false
|
|
63582
|
-
});
|
|
63583
|
-
} catch (err2) {
|
|
63584
|
-
const code = err2.code;
|
|
63585
|
-
if (code === "ELOCKED" || code === "EEXIST") {
|
|
63586
|
-
return { acquired: false };
|
|
63587
|
-
}
|
|
63588
|
-
throw err2;
|
|
63589
|
-
}
|
|
63590
|
-
const lock = {
|
|
63591
|
-
filePath,
|
|
63592
|
-
agent,
|
|
63593
|
-
taskId,
|
|
63594
|
-
timestamp: new Date().toISOString(),
|
|
63595
|
-
expiresAt: Date.now() + LOCK_TIMEOUT_MS,
|
|
63596
|
-
_release: release
|
|
63597
|
-
};
|
|
63598
|
-
return { acquired: true, lock };
|
|
63599
|
-
}
|
|
63600
|
-
|
|
63601
|
-
// src/tools/phase-complete.ts
|
|
63602
64404
|
init_ledger();
|
|
63603
64405
|
init_manager2();
|
|
64406
|
+
init_state();
|
|
63604
64407
|
init_telemetry();
|
|
63605
64408
|
init_create_tool();
|
|
63606
64409
|
init_resolve_working_directory();
|
|
@@ -63824,7 +64627,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63824
64627
|
let driftVerdictFound = false;
|
|
63825
64628
|
let driftVerdictApproved = false;
|
|
63826
64629
|
try {
|
|
63827
|
-
const driftEvidenceContent =
|
|
64630
|
+
const driftEvidenceContent = fs50.readFileSync(driftEvidencePath, "utf-8");
|
|
63828
64631
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
63829
64632
|
const entries = driftEvidence.entries ?? [];
|
|
63830
64633
|
for (const entry of entries) {
|
|
@@ -63855,13 +64658,13 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63855
64658
|
}
|
|
63856
64659
|
if (!driftVerdictFound) {
|
|
63857
64660
|
const specPath = path62.join(dir, ".swarm", "spec.md");
|
|
63858
|
-
const specExists =
|
|
64661
|
+
const specExists = fs50.existsSync(specPath);
|
|
63859
64662
|
if (!specExists) {
|
|
63860
64663
|
let incompleteTaskCount = 0;
|
|
63861
64664
|
let planPhaseFound = false;
|
|
63862
64665
|
try {
|
|
63863
64666
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
63864
|
-
const planRaw =
|
|
64667
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
63865
64668
|
const plan = JSON.parse(planRaw);
|
|
63866
64669
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
63867
64670
|
if (targetPhase) {
|
|
@@ -63986,7 +64789,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63986
64789
|
let phaseRequiredAgents;
|
|
63987
64790
|
try {
|
|
63988
64791
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
63989
|
-
const planRaw =
|
|
64792
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
63990
64793
|
const plan = JSON.parse(planRaw);
|
|
63991
64794
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
63992
64795
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -64001,7 +64804,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64001
64804
|
if (agentsMissing.length > 0) {
|
|
64002
64805
|
try {
|
|
64003
64806
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64004
|
-
const planRaw =
|
|
64807
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64005
64808
|
const plan = JSON.parse(planRaw);
|
|
64006
64809
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
64007
64810
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -64041,7 +64844,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64041
64844
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
64042
64845
|
try {
|
|
64043
64846
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64044
|
-
const planRaw =
|
|
64847
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64045
64848
|
const plan = JSON.parse(planRaw);
|
|
64046
64849
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
64047
64850
|
if (targetPhase) {
|
|
@@ -64095,7 +64898,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64095
64898
|
}
|
|
64096
64899
|
try {
|
|
64097
64900
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
64098
|
-
|
|
64901
|
+
fs50.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
64099
64902
|
`, "utf-8");
|
|
64100
64903
|
} catch (writeError) {
|
|
64101
64904
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -64116,6 +64919,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64116
64919
|
contributorSession.lastCompletedPhaseAgentsDispatched = new Set(contributorSession.phaseAgentsDispatched);
|
|
64117
64920
|
}
|
|
64118
64921
|
contributorSession.phaseAgentsDispatched = new Set;
|
|
64922
|
+
contributorSession.fullAutoInteractionCount = 0;
|
|
64923
|
+
contributorSession.fullAutoDeadlockCount = 0;
|
|
64924
|
+
contributorSession.fullAutoLastQuestionHash = null;
|
|
64119
64925
|
contributorSession.lastPhaseCompleteTimestamp = now;
|
|
64120
64926
|
const oldPhase = contributorSession.lastPhaseCompletePhase;
|
|
64121
64927
|
contributorSession.lastPhaseCompletePhase = phase;
|
|
@@ -64145,12 +64951,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64145
64951
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
64146
64952
|
try {
|
|
64147
64953
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64148
|
-
const planRaw =
|
|
64954
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64149
64955
|
const plan2 = JSON.parse(planRaw);
|
|
64150
64956
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
64151
64957
|
if (phaseObj) {
|
|
64152
64958
|
phaseObj.status = "complete";
|
|
64153
|
-
|
|
64959
|
+
fs50.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
64154
64960
|
}
|
|
64155
64961
|
} catch {}
|
|
64156
64962
|
} else if (plan) {
|
|
@@ -64187,12 +64993,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64187
64993
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
64188
64994
|
try {
|
|
64189
64995
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64190
|
-
const planRaw =
|
|
64996
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64191
64997
|
const plan = JSON.parse(planRaw);
|
|
64192
64998
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
64193
64999
|
if (phaseObj) {
|
|
64194
65000
|
phaseObj.status = "complete";
|
|
64195
|
-
|
|
65001
|
+
fs50.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
64196
65002
|
}
|
|
64197
65003
|
} catch {}
|
|
64198
65004
|
}
|
|
@@ -64249,7 +65055,7 @@ init_dist();
|
|
|
64249
65055
|
init_discovery();
|
|
64250
65056
|
init_utils();
|
|
64251
65057
|
init_create_tool();
|
|
64252
|
-
import * as
|
|
65058
|
+
import * as fs51 from "fs";
|
|
64253
65059
|
import * as path63 from "path";
|
|
64254
65060
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
64255
65061
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
@@ -64278,31 +65084,31 @@ function validateArgs3(args2) {
|
|
|
64278
65084
|
function detectEcosystems(directory) {
|
|
64279
65085
|
const ecosystems = [];
|
|
64280
65086
|
const cwd = directory;
|
|
64281
|
-
if (
|
|
65087
|
+
if (fs51.existsSync(path63.join(cwd, "package.json"))) {
|
|
64282
65088
|
ecosystems.push("npm");
|
|
64283
65089
|
}
|
|
64284
|
-
if (
|
|
65090
|
+
if (fs51.existsSync(path63.join(cwd, "pyproject.toml")) || fs51.existsSync(path63.join(cwd, "requirements.txt"))) {
|
|
64285
65091
|
ecosystems.push("pip");
|
|
64286
65092
|
}
|
|
64287
|
-
if (
|
|
65093
|
+
if (fs51.existsSync(path63.join(cwd, "Cargo.toml"))) {
|
|
64288
65094
|
ecosystems.push("cargo");
|
|
64289
65095
|
}
|
|
64290
|
-
if (
|
|
65096
|
+
if (fs51.existsSync(path63.join(cwd, "go.mod"))) {
|
|
64291
65097
|
ecosystems.push("go");
|
|
64292
65098
|
}
|
|
64293
65099
|
try {
|
|
64294
|
-
const files =
|
|
65100
|
+
const files = fs51.readdirSync(cwd);
|
|
64295
65101
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
64296
65102
|
ecosystems.push("dotnet");
|
|
64297
65103
|
}
|
|
64298
65104
|
} catch {}
|
|
64299
|
-
if (
|
|
65105
|
+
if (fs51.existsSync(path63.join(cwd, "Gemfile")) || fs51.existsSync(path63.join(cwd, "Gemfile.lock"))) {
|
|
64300
65106
|
ecosystems.push("ruby");
|
|
64301
65107
|
}
|
|
64302
|
-
if (
|
|
65108
|
+
if (fs51.existsSync(path63.join(cwd, "pubspec.yaml"))) {
|
|
64303
65109
|
ecosystems.push("dart");
|
|
64304
65110
|
}
|
|
64305
|
-
if (
|
|
65111
|
+
if (fs51.existsSync(path63.join(cwd, "composer.lock"))) {
|
|
64306
65112
|
ecosystems.push("composer");
|
|
64307
65113
|
}
|
|
64308
65114
|
return ecosystems;
|
|
@@ -65461,7 +66267,7 @@ var pkg_audit = createSwarmTool({
|
|
|
65461
66267
|
// src/tools/placeholder-scan.ts
|
|
65462
66268
|
init_dist();
|
|
65463
66269
|
init_manager();
|
|
65464
|
-
import * as
|
|
66270
|
+
import * as fs52 from "fs";
|
|
65465
66271
|
import * as path64 from "path";
|
|
65466
66272
|
init_utils();
|
|
65467
66273
|
init_create_tool();
|
|
@@ -65796,7 +66602,7 @@ async function placeholderScan(input, directory) {
|
|
|
65796
66602
|
if (!fullPath.startsWith(resolvedDirectory + path64.sep) && fullPath !== resolvedDirectory) {
|
|
65797
66603
|
continue;
|
|
65798
66604
|
}
|
|
65799
|
-
if (!
|
|
66605
|
+
if (!fs52.existsSync(fullPath)) {
|
|
65800
66606
|
continue;
|
|
65801
66607
|
}
|
|
65802
66608
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
@@ -65804,11 +66610,11 @@ async function placeholderScan(input, directory) {
|
|
|
65804
66610
|
}
|
|
65805
66611
|
let content;
|
|
65806
66612
|
try {
|
|
65807
|
-
const stat2 =
|
|
66613
|
+
const stat2 = fs52.statSync(fullPath);
|
|
65808
66614
|
if (stat2.size > MAX_FILE_SIZE) {
|
|
65809
66615
|
continue;
|
|
65810
66616
|
}
|
|
65811
|
-
content =
|
|
66617
|
+
content = fs52.readFileSync(fullPath, "utf-8");
|
|
65812
66618
|
} catch {
|
|
65813
66619
|
continue;
|
|
65814
66620
|
}
|
|
@@ -65870,7 +66676,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
65870
66676
|
});
|
|
65871
66677
|
// src/tools/pre-check-batch.ts
|
|
65872
66678
|
init_dist();
|
|
65873
|
-
import * as
|
|
66679
|
+
import * as fs54 from "fs";
|
|
65874
66680
|
import * as path66 from "path";
|
|
65875
66681
|
|
|
65876
66682
|
// node_modules/yocto-queue/index.js
|
|
@@ -66164,7 +66970,7 @@ var quality_budget = createSwarmTool({
|
|
|
66164
66970
|
init_dist();
|
|
66165
66971
|
init_manager();
|
|
66166
66972
|
init_detector();
|
|
66167
|
-
import * as
|
|
66973
|
+
import * as fs53 from "fs";
|
|
66168
66974
|
import * as path65 from "path";
|
|
66169
66975
|
import { extname as extname14 } from "path";
|
|
66170
66976
|
|
|
@@ -67065,17 +67871,17 @@ var SEVERITY_ORDER = {
|
|
|
67065
67871
|
};
|
|
67066
67872
|
function shouldSkipFile(filePath) {
|
|
67067
67873
|
try {
|
|
67068
|
-
const stats =
|
|
67874
|
+
const stats = fs53.statSync(filePath);
|
|
67069
67875
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
67070
67876
|
return { skip: true, reason: "file too large" };
|
|
67071
67877
|
}
|
|
67072
67878
|
if (stats.size === 0) {
|
|
67073
67879
|
return { skip: true, reason: "empty file" };
|
|
67074
67880
|
}
|
|
67075
|
-
const fd =
|
|
67881
|
+
const fd = fs53.openSync(filePath, "r");
|
|
67076
67882
|
const buffer = Buffer.alloc(8192);
|
|
67077
|
-
const bytesRead =
|
|
67078
|
-
|
|
67883
|
+
const bytesRead = fs53.readSync(fd, buffer, 0, 8192, 0);
|
|
67884
|
+
fs53.closeSync(fd);
|
|
67079
67885
|
if (bytesRead > 0) {
|
|
67080
67886
|
let nullCount = 0;
|
|
67081
67887
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -67114,7 +67920,7 @@ function countBySeverity(findings) {
|
|
|
67114
67920
|
}
|
|
67115
67921
|
function scanFileWithTierA(filePath, language) {
|
|
67116
67922
|
try {
|
|
67117
|
-
const content =
|
|
67923
|
+
const content = fs53.readFileSync(filePath, "utf-8");
|
|
67118
67924
|
const findings = executeRulesSync(filePath, content, language);
|
|
67119
67925
|
return findings.map((f) => ({
|
|
67120
67926
|
rule_id: f.rule_id,
|
|
@@ -67167,7 +67973,7 @@ async function sastScan(input, directory, config3) {
|
|
|
67167
67973
|
_filesSkipped++;
|
|
67168
67974
|
continue;
|
|
67169
67975
|
}
|
|
67170
|
-
if (!
|
|
67976
|
+
if (!fs53.existsSync(resolvedPath)) {
|
|
67171
67977
|
_filesSkipped++;
|
|
67172
67978
|
continue;
|
|
67173
67979
|
}
|
|
@@ -67623,7 +68429,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
67623
68429
|
}
|
|
67624
68430
|
let stat2;
|
|
67625
68431
|
try {
|
|
67626
|
-
stat2 =
|
|
68432
|
+
stat2 = fs54.statSync(file3);
|
|
67627
68433
|
} catch {
|
|
67628
68434
|
skippedFiles++;
|
|
67629
68435
|
continue;
|
|
@@ -67634,7 +68440,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
67634
68440
|
}
|
|
67635
68441
|
let content;
|
|
67636
68442
|
try {
|
|
67637
|
-
const buffer =
|
|
68443
|
+
const buffer = fs54.readFileSync(file3);
|
|
67638
68444
|
if (buffer.includes(0)) {
|
|
67639
68445
|
skippedFiles++;
|
|
67640
68446
|
continue;
|
|
@@ -68167,10 +68973,11 @@ ${paginatedContent}`;
|
|
|
68167
68973
|
});
|
|
68168
68974
|
// src/tools/save-plan.ts
|
|
68169
68975
|
init_tool();
|
|
68170
|
-
import * as
|
|
68976
|
+
import * as fs55 from "fs";
|
|
68171
68977
|
import * as path67 from "path";
|
|
68172
68978
|
init_ledger();
|
|
68173
68979
|
init_manager2();
|
|
68980
|
+
init_state();
|
|
68174
68981
|
init_create_tool();
|
|
68175
68982
|
function detectPlaceholderContent(args2) {
|
|
68176
68983
|
const issues = [];
|
|
@@ -68312,7 +69119,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
68312
69119
|
phases_count: plan.phases.length,
|
|
68313
69120
|
tasks_count: tasksCount
|
|
68314
69121
|
});
|
|
68315
|
-
await
|
|
69122
|
+
await fs55.promises.writeFile(markerPath, marker, "utf8");
|
|
68316
69123
|
} catch {}
|
|
68317
69124
|
const warnings = [];
|
|
68318
69125
|
let criticReviewFound = false;
|
|
@@ -68372,7 +69179,7 @@ var save_plan = createSwarmTool({
|
|
|
68372
69179
|
// src/tools/sbom-generate.ts
|
|
68373
69180
|
init_dist();
|
|
68374
69181
|
init_manager();
|
|
68375
|
-
import * as
|
|
69182
|
+
import * as fs56 from "fs";
|
|
68376
69183
|
import * as path68 from "path";
|
|
68377
69184
|
|
|
68378
69185
|
// src/sbom/detectors/index.ts
|
|
@@ -69221,7 +70028,7 @@ function findManifestFiles(rootDir) {
|
|
|
69221
70028
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
69222
70029
|
function searchDir(dir) {
|
|
69223
70030
|
try {
|
|
69224
|
-
const entries =
|
|
70031
|
+
const entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
69225
70032
|
for (const entry of entries) {
|
|
69226
70033
|
const fullPath = path68.join(dir, entry.name);
|
|
69227
70034
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
@@ -69248,7 +70055,7 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
69248
70055
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
69249
70056
|
for (const dir of directories) {
|
|
69250
70057
|
try {
|
|
69251
|
-
const entries =
|
|
70058
|
+
const entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
69252
70059
|
for (const entry of entries) {
|
|
69253
70060
|
const fullPath = path68.join(dir, entry.name);
|
|
69254
70061
|
if (entry.isFile()) {
|
|
@@ -69285,7 +70092,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
69285
70092
|
}
|
|
69286
70093
|
function ensureOutputDir(outputDir) {
|
|
69287
70094
|
try {
|
|
69288
|
-
|
|
70095
|
+
fs56.mkdirSync(outputDir, { recursive: true });
|
|
69289
70096
|
} catch (error93) {
|
|
69290
70097
|
if (!error93 || error93.code !== "EEXIST") {
|
|
69291
70098
|
throw error93;
|
|
@@ -69379,10 +70186,10 @@ var sbom_generate = createSwarmTool({
|
|
|
69379
70186
|
for (const manifestFile of manifestFiles) {
|
|
69380
70187
|
try {
|
|
69381
70188
|
const fullPath = path68.isAbsolute(manifestFile) ? manifestFile : path68.join(workingDir, manifestFile);
|
|
69382
|
-
if (!
|
|
70189
|
+
if (!fs56.existsSync(fullPath)) {
|
|
69383
70190
|
continue;
|
|
69384
70191
|
}
|
|
69385
|
-
const content =
|
|
70192
|
+
const content = fs56.readFileSync(fullPath, "utf-8");
|
|
69386
70193
|
const components = detectComponents(manifestFile, content);
|
|
69387
70194
|
processedFiles.push(manifestFile);
|
|
69388
70195
|
if (components.length > 0) {
|
|
@@ -69396,7 +70203,7 @@ var sbom_generate = createSwarmTool({
|
|
|
69396
70203
|
const bomJson = serializeCycloneDX(bom);
|
|
69397
70204
|
const filename = generateSbomFilename();
|
|
69398
70205
|
const outputPath = path68.join(outputDir, filename);
|
|
69399
|
-
|
|
70206
|
+
fs56.writeFileSync(outputPath, bomJson, "utf-8");
|
|
69400
70207
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
69401
70208
|
try {
|
|
69402
70209
|
const timestamp = new Date().toISOString();
|
|
@@ -69438,7 +70245,7 @@ var sbom_generate = createSwarmTool({
|
|
|
69438
70245
|
// src/tools/schema-drift.ts
|
|
69439
70246
|
init_dist();
|
|
69440
70247
|
init_create_tool();
|
|
69441
|
-
import * as
|
|
70248
|
+
import * as fs57 from "fs";
|
|
69442
70249
|
import * as path69 from "path";
|
|
69443
70250
|
var SPEC_CANDIDATES = [
|
|
69444
70251
|
"openapi.json",
|
|
@@ -69480,19 +70287,19 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
69480
70287
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
69481
70288
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
69482
70289
|
}
|
|
69483
|
-
const stats =
|
|
70290
|
+
const stats = fs57.statSync(resolvedPath);
|
|
69484
70291
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
69485
70292
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
69486
70293
|
}
|
|
69487
|
-
if (!
|
|
70294
|
+
if (!fs57.existsSync(resolvedPath)) {
|
|
69488
70295
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
69489
70296
|
}
|
|
69490
70297
|
return resolvedPath;
|
|
69491
70298
|
}
|
|
69492
70299
|
for (const candidate of SPEC_CANDIDATES) {
|
|
69493
70300
|
const candidatePath = path69.resolve(cwd, candidate);
|
|
69494
|
-
if (
|
|
69495
|
-
const stats =
|
|
70301
|
+
if (fs57.existsSync(candidatePath)) {
|
|
70302
|
+
const stats = fs57.statSync(candidatePath);
|
|
69496
70303
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
69497
70304
|
return candidatePath;
|
|
69498
70305
|
}
|
|
@@ -69501,7 +70308,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
69501
70308
|
return null;
|
|
69502
70309
|
}
|
|
69503
70310
|
function parseSpec(specFile) {
|
|
69504
|
-
const content =
|
|
70311
|
+
const content = fs57.readFileSync(specFile, "utf-8");
|
|
69505
70312
|
const ext = path69.extname(specFile).toLowerCase();
|
|
69506
70313
|
if (ext === ".json") {
|
|
69507
70314
|
return parseJsonSpec(content);
|
|
@@ -69573,7 +70380,7 @@ function extractRoutes(cwd) {
|
|
|
69573
70380
|
function walkDir(dir) {
|
|
69574
70381
|
let entries;
|
|
69575
70382
|
try {
|
|
69576
|
-
entries =
|
|
70383
|
+
entries = fs57.readdirSync(dir, { withFileTypes: true });
|
|
69577
70384
|
} catch {
|
|
69578
70385
|
return;
|
|
69579
70386
|
}
|
|
@@ -69606,7 +70413,7 @@ function extractRoutes(cwd) {
|
|
|
69606
70413
|
}
|
|
69607
70414
|
function extractRoutesFromFile(filePath) {
|
|
69608
70415
|
const routes = [];
|
|
69609
|
-
const content =
|
|
70416
|
+
const content = fs57.readFileSync(filePath, "utf-8");
|
|
69610
70417
|
const lines = content.split(/\r?\n/);
|
|
69611
70418
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
69612
70419
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -69753,7 +70560,7 @@ var schema_drift = createSwarmTool({
|
|
|
69753
70560
|
// src/tools/search.ts
|
|
69754
70561
|
init_tool();
|
|
69755
70562
|
init_create_tool();
|
|
69756
|
-
import * as
|
|
70563
|
+
import * as fs58 from "fs";
|
|
69757
70564
|
import * as path70 from "path";
|
|
69758
70565
|
var DEFAULT_MAX_RESULTS = 100;
|
|
69759
70566
|
var DEFAULT_MAX_LINES = 200;
|
|
@@ -69791,8 +70598,8 @@ function containsWindowsAttacks3(str) {
|
|
|
69791
70598
|
function isPathInWorkspace3(filePath, workspace) {
|
|
69792
70599
|
try {
|
|
69793
70600
|
const resolvedPath = path70.resolve(workspace, filePath);
|
|
69794
|
-
const realWorkspace =
|
|
69795
|
-
const realResolvedPath =
|
|
70601
|
+
const realWorkspace = fs58.realpathSync(workspace);
|
|
70602
|
+
const realResolvedPath = fs58.realpathSync(resolvedPath);
|
|
69796
70603
|
const relativePath = path70.relative(realWorkspace, realResolvedPath);
|
|
69797
70604
|
if (relativePath.startsWith("..") || path70.isAbsolute(relativePath)) {
|
|
69798
70605
|
return false;
|
|
@@ -69812,7 +70619,7 @@ function findRgInEnvPath() {
|
|
|
69812
70619
|
continue;
|
|
69813
70620
|
const isWindows = process.platform === "win32";
|
|
69814
70621
|
const candidate = path70.join(dir, isWindows ? "rg.exe" : "rg");
|
|
69815
|
-
if (
|
|
70622
|
+
if (fs58.existsSync(candidate))
|
|
69816
70623
|
return candidate;
|
|
69817
70624
|
}
|
|
69818
70625
|
return null;
|
|
@@ -69939,7 +70746,7 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
69939
70746
|
return files;
|
|
69940
70747
|
}
|
|
69941
70748
|
try {
|
|
69942
|
-
const entries =
|
|
70749
|
+
const entries = fs58.readdirSync(dir, { withFileTypes: true });
|
|
69943
70750
|
for (const entry of entries) {
|
|
69944
70751
|
const fullPath = path70.join(dir, entry.name);
|
|
69945
70752
|
const relativePath = path70.relative(workspace, fullPath);
|
|
@@ -69989,7 +70796,7 @@ async function fallbackSearch(opts) {
|
|
|
69989
70796
|
}
|
|
69990
70797
|
let stats;
|
|
69991
70798
|
try {
|
|
69992
|
-
stats =
|
|
70799
|
+
stats = fs58.statSync(fullPath);
|
|
69993
70800
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
69994
70801
|
continue;
|
|
69995
70802
|
}
|
|
@@ -69998,7 +70805,7 @@ async function fallbackSearch(opts) {
|
|
|
69998
70805
|
}
|
|
69999
70806
|
let content;
|
|
70000
70807
|
try {
|
|
70001
|
-
content =
|
|
70808
|
+
content = fs58.readFileSync(fullPath, "utf-8");
|
|
70002
70809
|
} catch {
|
|
70003
70810
|
continue;
|
|
70004
70811
|
}
|
|
@@ -70110,7 +70917,7 @@ var search = createSwarmTool({
|
|
|
70110
70917
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
70111
70918
|
}, null, 2);
|
|
70112
70919
|
}
|
|
70113
|
-
if (!
|
|
70920
|
+
if (!fs58.existsSync(directory)) {
|
|
70114
70921
|
return JSON.stringify({
|
|
70115
70922
|
error: true,
|
|
70116
70923
|
type: "unknown",
|
|
@@ -70153,7 +70960,7 @@ init_secretscan();
|
|
|
70153
70960
|
// src/tools/suggest-patch.ts
|
|
70154
70961
|
init_tool();
|
|
70155
70962
|
init_create_tool();
|
|
70156
|
-
import * as
|
|
70963
|
+
import * as fs59 from "fs";
|
|
70157
70964
|
import * as path71 from "path";
|
|
70158
70965
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
70159
70966
|
function containsWindowsAttacks4(str) {
|
|
@@ -70169,11 +70976,11 @@ function containsWindowsAttacks4(str) {
|
|
|
70169
70976
|
function isPathInWorkspace4(filePath, workspace) {
|
|
70170
70977
|
try {
|
|
70171
70978
|
const resolvedPath = path71.resolve(workspace, filePath);
|
|
70172
|
-
if (!
|
|
70979
|
+
if (!fs59.existsSync(resolvedPath)) {
|
|
70173
70980
|
return true;
|
|
70174
70981
|
}
|
|
70175
|
-
const realWorkspace =
|
|
70176
|
-
const realResolvedPath =
|
|
70982
|
+
const realWorkspace = fs59.realpathSync(workspace);
|
|
70983
|
+
const realResolvedPath = fs59.realpathSync(resolvedPath);
|
|
70177
70984
|
const relativePath = path71.relative(realWorkspace, realResolvedPath);
|
|
70178
70985
|
if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
|
|
70179
70986
|
return false;
|
|
@@ -70347,7 +71154,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70347
71154
|
message: "changes cannot be empty"
|
|
70348
71155
|
}, null, 2);
|
|
70349
71156
|
}
|
|
70350
|
-
if (!
|
|
71157
|
+
if (!fs59.existsSync(directory)) {
|
|
70351
71158
|
return JSON.stringify({
|
|
70352
71159
|
success: false,
|
|
70353
71160
|
error: true,
|
|
@@ -70384,7 +71191,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70384
71191
|
continue;
|
|
70385
71192
|
}
|
|
70386
71193
|
const fullPath = path71.resolve(directory, change.file);
|
|
70387
|
-
if (!
|
|
71194
|
+
if (!fs59.existsSync(fullPath)) {
|
|
70388
71195
|
errors5.push({
|
|
70389
71196
|
success: false,
|
|
70390
71197
|
error: true,
|
|
@@ -70398,7 +71205,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70398
71205
|
}
|
|
70399
71206
|
let content;
|
|
70400
71207
|
try {
|
|
70401
|
-
content =
|
|
71208
|
+
content = fs59.readFileSync(fullPath, "utf-8");
|
|
70402
71209
|
} catch (err2) {
|
|
70403
71210
|
errors5.push({
|
|
70404
71211
|
success: false,
|
|
@@ -70478,7 +71285,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70478
71285
|
init_dist();
|
|
70479
71286
|
init_manager();
|
|
70480
71287
|
init_detector();
|
|
70481
|
-
import * as
|
|
71288
|
+
import * as fs60 from "fs";
|
|
70482
71289
|
import * as path72 from "path";
|
|
70483
71290
|
init_create_tool();
|
|
70484
71291
|
var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
@@ -70575,7 +71382,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
70575
71382
|
}
|
|
70576
71383
|
let content;
|
|
70577
71384
|
try {
|
|
70578
|
-
content =
|
|
71385
|
+
content = fs60.readFileSync(fullPath, "utf8");
|
|
70579
71386
|
} catch {
|
|
70580
71387
|
result.skipped_reason = "file_read_error";
|
|
70581
71388
|
skippedCount++;
|
|
@@ -70655,7 +71462,7 @@ init_test_runner();
|
|
|
70655
71462
|
init_dist();
|
|
70656
71463
|
init_utils();
|
|
70657
71464
|
init_create_tool();
|
|
70658
|
-
import * as
|
|
71465
|
+
import * as fs61 from "fs";
|
|
70659
71466
|
import * as path73 from "path";
|
|
70660
71467
|
var MAX_TEXT_LENGTH = 200;
|
|
70661
71468
|
var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
|
|
@@ -70746,7 +71553,7 @@ function isSupportedExtension(filePath) {
|
|
|
70746
71553
|
function findSourceFiles2(dir, files = []) {
|
|
70747
71554
|
let entries;
|
|
70748
71555
|
try {
|
|
70749
|
-
entries =
|
|
71556
|
+
entries = fs61.readdirSync(dir);
|
|
70750
71557
|
} catch {
|
|
70751
71558
|
return files;
|
|
70752
71559
|
}
|
|
@@ -70758,7 +71565,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
70758
71565
|
const fullPath = path73.join(dir, entry);
|
|
70759
71566
|
let stat2;
|
|
70760
71567
|
try {
|
|
70761
|
-
stat2 =
|
|
71568
|
+
stat2 = fs61.statSync(fullPath);
|
|
70762
71569
|
} catch {
|
|
70763
71570
|
continue;
|
|
70764
71571
|
}
|
|
@@ -70851,7 +71658,7 @@ var todo_extract = createSwarmTool({
|
|
|
70851
71658
|
return JSON.stringify(errorResult, null, 2);
|
|
70852
71659
|
}
|
|
70853
71660
|
const scanPath = resolvedPath;
|
|
70854
|
-
if (!
|
|
71661
|
+
if (!fs61.existsSync(scanPath)) {
|
|
70855
71662
|
const errorResult = {
|
|
70856
71663
|
error: `path not found: ${pathsInput}`,
|
|
70857
71664
|
total: 0,
|
|
@@ -70861,7 +71668,7 @@ var todo_extract = createSwarmTool({
|
|
|
70861
71668
|
return JSON.stringify(errorResult, null, 2);
|
|
70862
71669
|
}
|
|
70863
71670
|
const filesToScan = [];
|
|
70864
|
-
const stat2 =
|
|
71671
|
+
const stat2 = fs61.statSync(scanPath);
|
|
70865
71672
|
if (stat2.isFile()) {
|
|
70866
71673
|
if (isSupportedExtension(scanPath)) {
|
|
70867
71674
|
filesToScan.push(scanPath);
|
|
@@ -70880,11 +71687,11 @@ var todo_extract = createSwarmTool({
|
|
|
70880
71687
|
const allEntries = [];
|
|
70881
71688
|
for (const filePath of filesToScan) {
|
|
70882
71689
|
try {
|
|
70883
|
-
const fileStat =
|
|
71690
|
+
const fileStat = fs61.statSync(filePath);
|
|
70884
71691
|
if (fileStat.size > MAX_FILE_SIZE_BYTES9) {
|
|
70885
71692
|
continue;
|
|
70886
71693
|
}
|
|
70887
|
-
const content =
|
|
71694
|
+
const content = fs61.readFileSync(filePath, "utf-8");
|
|
70888
71695
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
70889
71696
|
allEntries.push(...entries);
|
|
70890
71697
|
} catch {}
|
|
@@ -70913,18 +71720,18 @@ var todo_extract = createSwarmTool({
|
|
|
70913
71720
|
init_tool();
|
|
70914
71721
|
init_schema();
|
|
70915
71722
|
init_gate_evidence();
|
|
70916
|
-
import * as
|
|
71723
|
+
import * as fs63 from "fs";
|
|
70917
71724
|
import * as path75 from "path";
|
|
70918
71725
|
|
|
70919
71726
|
// src/hooks/diff-scope.ts
|
|
70920
|
-
import * as
|
|
71727
|
+
import * as fs62 from "fs";
|
|
70921
71728
|
import * as path74 from "path";
|
|
70922
71729
|
function getDeclaredScope(taskId, directory) {
|
|
70923
71730
|
try {
|
|
70924
71731
|
const planPath = path74.join(directory, ".swarm", "plan.json");
|
|
70925
|
-
if (!
|
|
71732
|
+
if (!fs62.existsSync(planPath))
|
|
70926
71733
|
return null;
|
|
70927
|
-
const raw =
|
|
71734
|
+
const raw = fs62.readFileSync(planPath, "utf-8");
|
|
70928
71735
|
const plan = JSON.parse(raw);
|
|
70929
71736
|
for (const phase of plan.phases ?? []) {
|
|
70930
71737
|
for (const task of phase.tasks ?? []) {
|
|
@@ -71002,6 +71809,7 @@ async function validateDiffScope(taskId, directory) {
|
|
|
71002
71809
|
|
|
71003
71810
|
// src/tools/update-task-status.ts
|
|
71004
71811
|
init_manager2();
|
|
71812
|
+
init_state();
|
|
71005
71813
|
init_telemetry();
|
|
71006
71814
|
init_create_tool();
|
|
71007
71815
|
var VALID_STATUSES2 = [
|
|
@@ -71052,7 +71860,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
71052
71860
|
const resolvedDir2 = workingDirectory;
|
|
71053
71861
|
try {
|
|
71054
71862
|
const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
|
|
71055
|
-
const planRaw =
|
|
71863
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71056
71864
|
const plan = JSON.parse(planRaw);
|
|
71057
71865
|
for (const planPhase of plan.phases ?? []) {
|
|
71058
71866
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -71119,7 +71927,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
71119
71927
|
try {
|
|
71120
71928
|
const resolvedDir2 = workingDirectory;
|
|
71121
71929
|
const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
|
|
71122
|
-
const planRaw =
|
|
71930
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71123
71931
|
const plan = JSON.parse(planRaw);
|
|
71124
71932
|
for (const planPhase of plan.phases ?? []) {
|
|
71125
71933
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -71314,9 +72122,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71314
72122
|
}
|
|
71315
72123
|
const resolvedDir = path75.resolve(normalizedDir);
|
|
71316
72124
|
try {
|
|
71317
|
-
const realPath =
|
|
72125
|
+
const realPath = fs63.realpathSync(resolvedDir);
|
|
71318
72126
|
const planPath = path75.join(realPath, ".swarm", "plan.json");
|
|
71319
|
-
if (!
|
|
72127
|
+
if (!fs63.existsSync(planPath)) {
|
|
71320
72128
|
return {
|
|
71321
72129
|
success: false,
|
|
71322
72130
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -71348,11 +72156,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71348
72156
|
if (args2.status === "in_progress") {
|
|
71349
72157
|
try {
|
|
71350
72158
|
const evidencePath = path75.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
71351
|
-
|
|
71352
|
-
const fd =
|
|
72159
|
+
fs63.mkdirSync(path75.dirname(evidencePath), { recursive: true });
|
|
72160
|
+
const fd = fs63.openSync(evidencePath, "wx");
|
|
71353
72161
|
let writeOk = false;
|
|
71354
72162
|
try {
|
|
71355
|
-
|
|
72163
|
+
fs63.writeSync(fd, JSON.stringify({
|
|
71356
72164
|
task_id: args2.task_id,
|
|
71357
72165
|
required_gates: ["reviewer", "test_engineer"],
|
|
71358
72166
|
gates: {},
|
|
@@ -71360,10 +72168,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71360
72168
|
}, null, 2));
|
|
71361
72169
|
writeOk = true;
|
|
71362
72170
|
} finally {
|
|
71363
|
-
|
|
72171
|
+
fs63.closeSync(fd);
|
|
71364
72172
|
if (!writeOk) {
|
|
71365
72173
|
try {
|
|
71366
|
-
|
|
72174
|
+
fs63.unlinkSync(evidencePath);
|
|
71367
72175
|
} catch {}
|
|
71368
72176
|
}
|
|
71369
72177
|
}
|
|
@@ -71374,7 +72182,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71374
72182
|
let phaseRequiresReviewer = true;
|
|
71375
72183
|
try {
|
|
71376
72184
|
const planPath = path75.join(directory, ".swarm", "plan.json");
|
|
71377
|
-
const planRaw =
|
|
72185
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71378
72186
|
const plan = JSON.parse(planRaw);
|
|
71379
72187
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
71380
72188
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -71472,7 +72280,7 @@ var update_task_status = createSwarmTool({
|
|
|
71472
72280
|
init_tool();
|
|
71473
72281
|
init_utils2();
|
|
71474
72282
|
init_create_tool();
|
|
71475
|
-
import
|
|
72283
|
+
import fs64 from "fs";
|
|
71476
72284
|
import path76 from "path";
|
|
71477
72285
|
function normalizeVerdict(verdict) {
|
|
71478
72286
|
switch (verdict) {
|
|
@@ -71533,10 +72341,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
71533
72341
|
}
|
|
71534
72342
|
const evidenceDir = path76.dirname(validatedPath);
|
|
71535
72343
|
try {
|
|
71536
|
-
await
|
|
72344
|
+
await fs64.promises.mkdir(evidenceDir, { recursive: true });
|
|
71537
72345
|
const tempPath = path76.join(evidenceDir, `.${filename}.tmp`);
|
|
71538
|
-
await
|
|
71539
|
-
await
|
|
72346
|
+
await fs64.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
72347
|
+
await fs64.promises.rename(tempPath, validatedPath);
|
|
71540
72348
|
return JSON.stringify({
|
|
71541
72349
|
success: true,
|
|
71542
72350
|
phase,
|
|
@@ -71614,6 +72422,14 @@ ${footerLines.join(`
|
|
|
71614
72422
|
var _heartbeatTimers = new Map;
|
|
71615
72423
|
var OpenCodeSwarm = async (ctx) => {
|
|
71616
72424
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
72425
|
+
if (config3.full_auto?.enabled === true) {
|
|
72426
|
+
const criticModel = config3.full_auto.critic_model ?? config3.agents?.critic?.model ?? DEFAULT_MODELS.critic;
|
|
72427
|
+
const architectModel = config3.agents?.architect?.model ?? DEFAULT_MODELS.default;
|
|
72428
|
+
if (criticModel === architectModel) {
|
|
72429
|
+
console.warn("[opencode-swarm] Full-auto mode warning: critic model matches architect model. Model validation is advisory-only; full-auto remains enabled. (Runtime architect model is determined by the orchestrator)");
|
|
72430
|
+
}
|
|
72431
|
+
}
|
|
72432
|
+
swarmState.fullAutoEnabledInConfig = config3.full_auto?.enabled === true;
|
|
71617
72433
|
swarmState.opencodeClient = ctx.client;
|
|
71618
72434
|
await loadSnapshot(ctx.directory);
|
|
71619
72435
|
initTelemetry(ctx.directory);
|
|
@@ -71652,6 +72468,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
71652
72468
|
const delegationHandler = createDelegationTrackerHook(config3, guardrailsConfig.enabled);
|
|
71653
72469
|
const authorityConfig = AuthorityConfigSchema.parse(config3.authority ?? {});
|
|
71654
72470
|
const guardrailsHooks = createGuardrailsHooks(ctx.directory, undefined, guardrailsConfig, authorityConfig);
|
|
72471
|
+
const fullAutoInterceptHook = createFullAutoInterceptHook(config3, ctx.directory);
|
|
71655
72472
|
const watchdogConfig = WatchdogConfigSchema.parse(config3.watchdog ?? {});
|
|
71656
72473
|
const advisoryInjector = (sessionId, message) => {
|
|
71657
72474
|
const s = swarmState.agentSessions.get(sessionId);
|
|
@@ -71976,6 +72793,10 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
71976
72793
|
template: "/swarm turbo",
|
|
71977
72794
|
description: "Use /swarm turbo to enable turbo mode for faster execution"
|
|
71978
72795
|
},
|
|
72796
|
+
"swarm-full-auto": {
|
|
72797
|
+
template: "/swarm full-auto $ARGUMENTS",
|
|
72798
|
+
description: "Use /swarm full-auto to toggle Full-Auto Mode for the active session [on|off]"
|
|
72799
|
+
},
|
|
71979
72800
|
"swarm-write-retro": {
|
|
71980
72801
|
template: "/swarm write-retro $ARGUMENTS",
|
|
71981
72802
|
description: "Use /swarm write-retro to manually write a phase retrospective"
|
|
@@ -72034,6 +72855,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
72034
72855
|
pipelineHook["experimental.chat.messages.transform"],
|
|
72035
72856
|
contextBudgetHandler,
|
|
72036
72857
|
guardrailsHooks.messagesTransform,
|
|
72858
|
+
fullAutoInterceptHook?.messagesTransform,
|
|
72037
72859
|
delegationGateHooks.messagesTransform,
|
|
72038
72860
|
delegationSanitizerHook,
|
|
72039
72861
|
knowledgeInjectorHook,
|