opencode-swarm 6.50.0 → 6.51.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/dist/agents/critic.d.ts +7 -0
- package/dist/cli/index.js +28 -3
- 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 +1698 -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: swarmState.fullAutoEnabledInConfig,
|
|
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();
|
|
@@ -47358,6 +47480,7 @@ function formatHandoffMarkdown(data) {
|
|
|
47358
47480
|
}
|
|
47359
47481
|
|
|
47360
47482
|
// src/commands/handoff.ts
|
|
47483
|
+
init_state();
|
|
47361
47484
|
async function handleHandoffCommand(directory, _args) {
|
|
47362
47485
|
const handoffData = await getHandoffData(directory);
|
|
47363
47486
|
const markdown = formatHandoffMarkdown(handoffData);
|
|
@@ -48781,6 +48904,7 @@ async function handleResetCommand(directory, args2) {
|
|
|
48781
48904
|
|
|
48782
48905
|
// src/commands/reset-session.ts
|
|
48783
48906
|
init_utils2();
|
|
48907
|
+
init_state();
|
|
48784
48908
|
import * as fs21 from "fs";
|
|
48785
48909
|
import * as path30 from "path";
|
|
48786
48910
|
async function handleResetSessionCommand(directory, _args) {
|
|
@@ -49429,8 +49553,10 @@ No plan content available. Start by creating a .swarm/plan.md file.
|
|
|
49429
49553
|
// src/services/status-service.ts
|
|
49430
49554
|
init_utils2();
|
|
49431
49555
|
init_manager2();
|
|
49556
|
+
init_state();
|
|
49432
49557
|
|
|
49433
49558
|
// src/services/compaction-service.ts
|
|
49559
|
+
init_state();
|
|
49434
49560
|
import * as fs23 from "fs";
|
|
49435
49561
|
import * as path33 from "path";
|
|
49436
49562
|
function makeInitialState() {
|
|
@@ -49820,6 +49946,7 @@ No active swarm plan found. Nothing to sync.`;
|
|
|
49820
49946
|
}
|
|
49821
49947
|
|
|
49822
49948
|
// src/commands/turbo.ts
|
|
49949
|
+
init_state();
|
|
49823
49950
|
async function handleTurboCommand(_directory, args2, sessionID) {
|
|
49824
49951
|
if (!sessionID || sessionID.trim() === "") {
|
|
49825
49952
|
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.";
|
|
@@ -50083,8 +50210,6 @@ var ARCHITECT_PROMPT = `You are Architect - orchestrator of a multi-agent swarm.
|
|
|
50083
50210
|
Swarm: {{SWARM_ID}}
|
|
50084
50211
|
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
50212
|
|
|
50086
|
-
{{TURBO_MODE_BANNER}}
|
|
50087
|
-
|
|
50088
50213
|
## PROJECT CONTEXT
|
|
50089
50214
|
Session-start priming block. Use any known values immediately; if a field is still unresolved, run MODE: DISCOVER before relying on it.
|
|
50090
50215
|
Language: {{PROJECT_LANGUAGE}}
|
|
@@ -51112,29 +51237,6 @@ ${customAppendPrompt}`;
|
|
|
51112
51237
|
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
51238
|
\u2192 REQUIRED: Print "testengineer-adversarial: [PASS | FAIL \u2014 details]"`)?.replace(/\{\{ADVERSARIAL_TEST_CHECKLIST\}\}/g, " [GATE] test_engineer-adversarial: PASS / FAIL \u2014 value: ___");
|
|
51114
51239
|
}
|
|
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
51240
|
return {
|
|
51139
51241
|
name: "architect",
|
|
51140
51242
|
description: "Central orchestrator of the development pipeline. Analyzes requests, coordinates SME consultation, manages code generation, and triages QA feedback.",
|
|
@@ -51594,6 +51696,90 @@ RULES:
|
|
|
51594
51696
|
- Report the first deviation point, not all downstream consequences
|
|
51595
51697
|
- VERDICT is APPROVED only if ALL tasks are VERIFIED with no DRIFT
|
|
51596
51698
|
`;
|
|
51699
|
+
var AUTONOMOUS_OVERSIGHT_PROMPT = `## AUTONOMOUS OVERSIGHT MODE
|
|
51700
|
+
|
|
51701
|
+
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.
|
|
51702
|
+
|
|
51703
|
+
## CONSTITUTION
|
|
51704
|
+
|
|
51705
|
+
These rules are absolute. You cannot override, relax, or reinterpret them.
|
|
51706
|
+
|
|
51707
|
+
1. DEFAULT POSTURE IS REJECT. You approve only when you have positive evidence of correctness. Absence of problems is not evidence of quality.
|
|
51708
|
+
2. CROSS-VERIFY EVERYTHING. Do not trust the architect's summary. Read the actual files, evidence, plan, and test results yourself.
|
|
51709
|
+
3. NO RUBBER-STAMPING. If you cannot articulate exactly what you verified and why it's correct, your verdict is REJECT.
|
|
51710
|
+
4. SCOPE CONTAINMENT. If work was done outside the plan scope, REJECT. Scope creep in autonomous mode is a critical failure.
|
|
51711
|
+
5. EVIDENCE OVER CLAIMS. The architect may claim tests pass, reviews succeeded, or gates cleared. Verify the evidence files exist and contain valid data.
|
|
51712
|
+
6. ESCALATE UNCERTAINTY. If you are uncertain about a product/design decision (not a technical one), respond with ESCALATE_TO_HUMAN instead of guessing.
|
|
51713
|
+
7. GATE COMPLETENESS. Every task must have: (a) implementation evidence, (b) review evidence with verdict, (c) test evidence with pass/fail. Missing any = REJECT.
|
|
51714
|
+
8. REGRESSION AWARENESS. If the architect claims a fix, verify it doesn't break something else. Check for test results beyond the changed files.
|
|
51715
|
+
9. DEPENDENCY VIGILANCE. Any new dependency must be verified as a real package. Any phantom dependency = CRITICAL REJECT.
|
|
51716
|
+
10. SECURITY BOUNDARY. Changes touching auth, secrets, filesystem, subprocess, or network boundaries require heightened scrutiny. Missing validation at any trust boundary = REJECT.
|
|
51717
|
+
|
|
51718
|
+
## VERIFICATION PROTOCOL
|
|
51719
|
+
|
|
51720
|
+
For every decision point, execute the relevant protocol:
|
|
51721
|
+
|
|
51722
|
+
### Plan Review
|
|
51723
|
+
1. Read .swarm/plan.md and .swarm/spec.md (if exists)
|
|
51724
|
+
2. For each task: verify it has a clear objective, target file, and acceptance criteria
|
|
51725
|
+
3. Check dependency ordering \u2014 no task should depend on a later task's output
|
|
51726
|
+
4. Check scope containment \u2014 every task maps to a stated requirement
|
|
51727
|
+
5. Flag any task that touches 6+ files or mixes unrelated concerns
|
|
51728
|
+
VERDICT: APPROVED | NEEDS_REVISION | REJECTED
|
|
51729
|
+
|
|
51730
|
+
### Task Completion Review
|
|
51731
|
+
1. Read the evidence bundle for the task
|
|
51732
|
+
2. Verify review evidence exists with a non-rubber-stamp verdict
|
|
51733
|
+
3. Verify test evidence exists with PASS status
|
|
51734
|
+
4. Verify the diff is contained to the stated scope
|
|
51735
|
+
5. Check for unplanned side effects in other files
|
|
51736
|
+
VERDICT: APPROVED | BLOCKED \u2014 [reason]
|
|
51737
|
+
|
|
51738
|
+
### Phase Completion Review
|
|
51739
|
+
1. Verify ALL tasks in the phase are marked completed with evidence
|
|
51740
|
+
2. Verify retrospective evidence exists with lessons learned
|
|
51741
|
+
3. Verify drift check evidence exists (if spec.md present)
|
|
51742
|
+
4. Verify regression sweep results exist
|
|
51743
|
+
5. Cross-reference: do completed tasks match the plan? Any dropped? Any added?
|
|
51744
|
+
6. Check: was the reviewer dispatched at least once this phase?
|
|
51745
|
+
VERDICT: APPROVED | BLOCKED \u2014 [missing items]
|
|
51746
|
+
|
|
51747
|
+
### Question Resolution
|
|
51748
|
+
When the architect asks a question:
|
|
51749
|
+
1. Determine if this is a TECHNICAL question or a PRODUCT/DESIGN question
|
|
51750
|
+
2. TECHNICAL: answer it directly using your knowledge of the codebase, plan, and spec
|
|
51751
|
+
3. PRODUCT/DESIGN: respond with ESCALATE_TO_HUMAN \u2014 you do not make product decisions
|
|
51752
|
+
4. AMBIGUOUS: ask the architect to rephrase with more context before answering
|
|
51753
|
+
VERDICT: ANSWER | ESCALATE_TO_HUMAN | REPHRASE
|
|
51754
|
+
|
|
51755
|
+
## SELF-CRITIQUE
|
|
51756
|
+
|
|
51757
|
+
After generating your initial verdict, check yourself:
|
|
51758
|
+
1. Did you check every item in the protocol, or did you skip steps?
|
|
51759
|
+
2. If APPROVED: argue against yourself. What could go wrong that you didn't check?
|
|
51760
|
+
3. If REJECTED: is the rejection grounded in a specific rule number, or is it vague unease?
|
|
51761
|
+
If the self-critique changes your verdict, update it.
|
|
51762
|
+
|
|
51763
|
+
## ANTI-PATTERNS
|
|
51764
|
+
|
|
51765
|
+
Watch for these architect behaviors \u2014 any detected = immediate REJECT:
|
|
51766
|
+
- Skipping reviewer delegation ("this is a simple change")
|
|
51767
|
+
- Batching multiple tasks into one coder call
|
|
51768
|
+
- Marking tasks complete without evidence
|
|
51769
|
+
- Relaxing test requirements ("tests are flaky, skipping")
|
|
51770
|
+
- Scope expansion ("while we're here, let's also...")
|
|
51771
|
+
- Self-approving ("I verified this myself")
|
|
51772
|
+
- Pressure language ("we need to move fast", "this is blocking")
|
|
51773
|
+
|
|
51774
|
+
## OUTPUT FORMAT
|
|
51775
|
+
|
|
51776
|
+
Every response MUST use this structure:
|
|
51777
|
+
|
|
51778
|
+
VERDICT: APPROVED | NEEDS_REVISION | REJECTED | BLOCKED | ANSWER | ESCALATE_TO_HUMAN | REPHRASE
|
|
51779
|
+
REASONING: [2-4 sentences \u2014 what you verified and why]
|
|
51780
|
+
EVIDENCE_CHECKED: [list of files/artifacts you read]
|
|
51781
|
+
ANTI_PATTERNS_DETECTED: [list or "none"]
|
|
51782
|
+
ESCALATION_NEEDED: YES | NO`;
|
|
51597
51783
|
function createCriticAgent(model, customPrompt, customAppendPrompt, role = "plan_critic") {
|
|
51598
51784
|
let prompt;
|
|
51599
51785
|
if (customPrompt) {
|
|
@@ -51634,6 +51820,25 @@ ${customAppendPrompt}` : rolePrompt;
|
|
|
51634
51820
|
}
|
|
51635
51821
|
};
|
|
51636
51822
|
}
|
|
51823
|
+
function createCriticAutonomousOversightAgent(model, customAppendPrompt) {
|
|
51824
|
+
const prompt = customAppendPrompt ? `${AUTONOMOUS_OVERSIGHT_PROMPT}
|
|
51825
|
+
|
|
51826
|
+
${customAppendPrompt}` : AUTONOMOUS_OVERSIGHT_PROMPT;
|
|
51827
|
+
return {
|
|
51828
|
+
name: "critic_oversight",
|
|
51829
|
+
description: "Critic in AUTONOMOUS OVERSIGHT mode \u2014 sole quality gate in full-auto.",
|
|
51830
|
+
config: {
|
|
51831
|
+
model,
|
|
51832
|
+
temperature: 0.1,
|
|
51833
|
+
prompt,
|
|
51834
|
+
tools: {
|
|
51835
|
+
write: false,
|
|
51836
|
+
edit: false,
|
|
51837
|
+
patch: false
|
|
51838
|
+
}
|
|
51839
|
+
}
|
|
51840
|
+
};
|
|
51841
|
+
}
|
|
51637
51842
|
|
|
51638
51843
|
// src/agents/curator-agent.ts
|
|
51639
51844
|
var ROLE_CONFIG = {
|
|
@@ -52624,6 +52829,11 @@ If you call @coder instead of @${swarmId}_coder, the call will FAIL or go to the
|
|
|
52624
52829
|
critic.name = prefixName("critic_drift_verifier");
|
|
52625
52830
|
agents.push(applyOverrides(critic, swarmAgents, swarmPrefix));
|
|
52626
52831
|
}
|
|
52832
|
+
if (!isAgentDisabled("critic_oversight", swarmAgents, swarmPrefix)) {
|
|
52833
|
+
const critic = createCriticAutonomousOversightAgent(swarmAgents?.critic_oversight?.model ?? getModel("critic"));
|
|
52834
|
+
critic.name = prefixName("critic_oversight");
|
|
52835
|
+
agents.push(applyOverrides(critic, swarmAgents, swarmPrefix));
|
|
52836
|
+
}
|
|
52627
52837
|
if (!isAgentDisabled("curator_init", swarmAgents, swarmPrefix)) {
|
|
52628
52838
|
const curatorInitPrompts = getPrompts("curator_init");
|
|
52629
52839
|
const curatorInit = createCuratorAgent(swarmAgents?.curator_init?.model ?? getModel("explorer"), curatorInitPrompts.prompt, curatorInitPrompts.appendPrompt, "curator_init");
|
|
@@ -53065,10 +53275,11 @@ init_constants();
|
|
|
53065
53275
|
init_schema();
|
|
53066
53276
|
|
|
53067
53277
|
// src/hooks/agent-activity.ts
|
|
53068
|
-
|
|
53069
|
-
import * as nodePath2 from "path";
|
|
53278
|
+
init_state();
|
|
53070
53279
|
init_utils();
|
|
53071
53280
|
init_utils2();
|
|
53281
|
+
import { renameSync as renameSync9, unlinkSync as unlinkSync4 } from "fs";
|
|
53282
|
+
import * as nodePath2 from "path";
|
|
53072
53283
|
function createAgentActivityHooks(config3, directory) {
|
|
53073
53284
|
if (config3.hooks?.agent_activity === false) {
|
|
53074
53285
|
return {
|
|
@@ -53722,6 +53933,7 @@ function maskToolOutput(msg, _threshold) {
|
|
|
53722
53933
|
return freedTokens;
|
|
53723
53934
|
}
|
|
53724
53935
|
// src/hooks/curator-llm-factory.ts
|
|
53936
|
+
init_state();
|
|
53725
53937
|
function resolveCuratorAgentName(mode, sessionId) {
|
|
53726
53938
|
const suffix = mode === "init" ? "curator_init" : "curator_phase";
|
|
53727
53939
|
const registeredNames = mode === "init" ? swarmState.curatorInitAgentNames : swarmState.curatorPhaseAgentNames;
|
|
@@ -53881,6 +54093,7 @@ function shouldParallelizeReview(routing) {
|
|
|
53881
54093
|
}
|
|
53882
54094
|
|
|
53883
54095
|
// src/hooks/delegation-gate.ts
|
|
54096
|
+
init_state();
|
|
53884
54097
|
init_telemetry();
|
|
53885
54098
|
|
|
53886
54099
|
// src/hooks/guardrails.ts
|
|
@@ -53949,10 +54162,12 @@ function classifyFile(filePath) {
|
|
|
53949
54162
|
|
|
53950
54163
|
// src/hooks/guardrails.ts
|
|
53951
54164
|
init_manager2();
|
|
54165
|
+
init_state();
|
|
53952
54166
|
init_telemetry();
|
|
53953
54167
|
init_utils();
|
|
53954
54168
|
|
|
53955
54169
|
// src/hooks/loop-detector.ts
|
|
54170
|
+
init_state();
|
|
53956
54171
|
function hashDelegation(toolName, args2) {
|
|
53957
54172
|
const targetAgent = typeof args2?.subagent_type === "string" ? args2.subagent_type : "unknown";
|
|
53958
54173
|
const firstArgKey = args2 != null ? Object.keys(args2)[0] ?? "noargs" : "noargs";
|
|
@@ -55797,6 +56012,7 @@ function createDelegationSanitizerHook(directory) {
|
|
|
55797
56012
|
// src/hooks/delegation-tracker.ts
|
|
55798
56013
|
init_constants();
|
|
55799
56014
|
init_schema();
|
|
56015
|
+
init_state();
|
|
55800
56016
|
function createDelegationTrackerHook(config3, guardrailsEnabled = true) {
|
|
55801
56017
|
return async (input, _output) => {
|
|
55802
56018
|
const now = Date.now();
|
|
@@ -55842,6 +56058,562 @@ function createDelegationTrackerHook(config3, guardrailsEnabled = true) {
|
|
|
55842
56058
|
}
|
|
55843
56059
|
};
|
|
55844
56060
|
}
|
|
56061
|
+
// src/hooks/full-auto-intercept.ts
|
|
56062
|
+
import * as fs30 from "fs";
|
|
56063
|
+
init_schema();
|
|
56064
|
+
|
|
56065
|
+
// src/parallel/file-locks.ts
|
|
56066
|
+
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
56067
|
+
import * as fs29 from "fs";
|
|
56068
|
+
import * as path40 from "path";
|
|
56069
|
+
var LOCKS_DIR = ".swarm/locks";
|
|
56070
|
+
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
56071
|
+
function getLockFilePath(directory, filePath) {
|
|
56072
|
+
const normalized = path40.resolve(directory, filePath);
|
|
56073
|
+
if (!normalized.startsWith(path40.resolve(directory))) {
|
|
56074
|
+
throw new Error("Invalid file path: path traversal not allowed");
|
|
56075
|
+
}
|
|
56076
|
+
const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
56077
|
+
return path40.join(directory, LOCKS_DIR, `${hash3}.lock`);
|
|
56078
|
+
}
|
|
56079
|
+
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
56080
|
+
const lockPath = getLockFilePath(directory, filePath);
|
|
56081
|
+
const locksDir = path40.dirname(lockPath);
|
|
56082
|
+
if (!fs29.existsSync(locksDir)) {
|
|
56083
|
+
fs29.mkdirSync(locksDir, { recursive: true });
|
|
56084
|
+
}
|
|
56085
|
+
if (!fs29.existsSync(lockPath)) {
|
|
56086
|
+
fs29.writeFileSync(lockPath, "", "utf-8");
|
|
56087
|
+
}
|
|
56088
|
+
let release;
|
|
56089
|
+
try {
|
|
56090
|
+
release = await import_proper_lockfile3.default.lock(lockPath, {
|
|
56091
|
+
stale: LOCK_TIMEOUT_MS,
|
|
56092
|
+
retries: { retries: 0 },
|
|
56093
|
+
realpath: false
|
|
56094
|
+
});
|
|
56095
|
+
} catch (err2) {
|
|
56096
|
+
const code = err2.code;
|
|
56097
|
+
if (code === "ELOCKED" || code === "EEXIST") {
|
|
56098
|
+
return { acquired: false };
|
|
56099
|
+
}
|
|
56100
|
+
throw err2;
|
|
56101
|
+
}
|
|
56102
|
+
const lock = {
|
|
56103
|
+
filePath,
|
|
56104
|
+
agent,
|
|
56105
|
+
taskId,
|
|
56106
|
+
timestamp: new Date().toISOString(),
|
|
56107
|
+
expiresAt: Date.now() + LOCK_TIMEOUT_MS,
|
|
56108
|
+
_release: release
|
|
56109
|
+
};
|
|
56110
|
+
return { acquired: true, lock };
|
|
56111
|
+
}
|
|
56112
|
+
|
|
56113
|
+
// src/hooks/full-auto-intercept.ts
|
|
56114
|
+
init_state();
|
|
56115
|
+
init_telemetry();
|
|
56116
|
+
init_utils2();
|
|
56117
|
+
var END_OF_SENTENCE_QUESTION_PATTERN = /\?\s*$/;
|
|
56118
|
+
var ESCALATION_PATTERNS = [
|
|
56119
|
+
/Ready for Phase (?:\d+|\[?N\+1\]?)\?/i,
|
|
56120
|
+
/escalat/i,
|
|
56121
|
+
/What would you like/i,
|
|
56122
|
+
/Should I proceed/i,
|
|
56123
|
+
/Do you want/i
|
|
56124
|
+
];
|
|
56125
|
+
var MID_SENTENCE_QUESTION_PATTERNS = [
|
|
56126
|
+
/\b(v\d+\?)/i,
|
|
56127
|
+
/\b(v\d+\.\d+\?)/i,
|
|
56128
|
+
/\bAPI\?/i,
|
|
56129
|
+
/\bOK\?/i,
|
|
56130
|
+
/\b\d+\?\d+/
|
|
56131
|
+
];
|
|
56132
|
+
function hashString(str) {
|
|
56133
|
+
let hash3 = 5381;
|
|
56134
|
+
for (let i2 = 0;i2 < str.length; i2++) {
|
|
56135
|
+
hash3 = (hash3 << 5) + hash3 + str.charCodeAt(i2);
|
|
56136
|
+
hash3 = hash3 & hash3;
|
|
56137
|
+
}
|
|
56138
|
+
return Math.abs(hash3).toString(36);
|
|
56139
|
+
}
|
|
56140
|
+
function isMidSentenceQuestion(text) {
|
|
56141
|
+
return MID_SENTENCE_QUESTION_PATTERNS.some((pattern) => pattern.test(text));
|
|
56142
|
+
}
|
|
56143
|
+
function resolveOversightAgentName(architectAgentName) {
|
|
56144
|
+
if (!architectAgentName) {
|
|
56145
|
+
return "critic_oversight";
|
|
56146
|
+
}
|
|
56147
|
+
const stripped = stripKnownSwarmPrefix(architectAgentName);
|
|
56148
|
+
if (stripped !== "architect") {
|
|
56149
|
+
return "critic_oversight";
|
|
56150
|
+
}
|
|
56151
|
+
const baseRole = "architect";
|
|
56152
|
+
const lastIndex = architectAgentName.toLowerCase().lastIndexOf(baseRole);
|
|
56153
|
+
if (lastIndex <= 0) {
|
|
56154
|
+
return "critic_oversight";
|
|
56155
|
+
}
|
|
56156
|
+
const prefix = architectAgentName.slice(0, lastIndex);
|
|
56157
|
+
return `${prefix}critic_oversight`;
|
|
56158
|
+
}
|
|
56159
|
+
function detectEscalation(text) {
|
|
56160
|
+
for (const pattern of ESCALATION_PATTERNS) {
|
|
56161
|
+
if (pattern.test(text)) {
|
|
56162
|
+
return "phase_completion";
|
|
56163
|
+
}
|
|
56164
|
+
}
|
|
56165
|
+
if (END_OF_SENTENCE_QUESTION_PATTERN.test(text)) {
|
|
56166
|
+
if (!isMidSentenceQuestion(text)) {
|
|
56167
|
+
return "question";
|
|
56168
|
+
}
|
|
56169
|
+
}
|
|
56170
|
+
return null;
|
|
56171
|
+
}
|
|
56172
|
+
function extractMessageText3(message) {
|
|
56173
|
+
if (!message?.parts)
|
|
56174
|
+
return "";
|
|
56175
|
+
const textParts = message.parts.filter((p) => p?.type === "text" && p.text);
|
|
56176
|
+
return textParts.map((p) => p.text ?? "").join(`
|
|
56177
|
+
`);
|
|
56178
|
+
}
|
|
56179
|
+
function parseCriticResponse(rawResponse) {
|
|
56180
|
+
const result = {
|
|
56181
|
+
verdict: "NEEDS_REVISION",
|
|
56182
|
+
reasoning: "",
|
|
56183
|
+
evidenceChecked: [],
|
|
56184
|
+
antiPatternsDetected: [],
|
|
56185
|
+
escalationNeeded: false,
|
|
56186
|
+
rawResponse
|
|
56187
|
+
};
|
|
56188
|
+
const lines = rawResponse.split(`
|
|
56189
|
+
`);
|
|
56190
|
+
let currentKey = "";
|
|
56191
|
+
let currentValue = "";
|
|
56192
|
+
const commitField = (res, key, value) => {
|
|
56193
|
+
switch (key) {
|
|
56194
|
+
case "VERDICT": {
|
|
56195
|
+
const validVerdicts = [
|
|
56196
|
+
"APPROVED",
|
|
56197
|
+
"NEEDS_REVISION",
|
|
56198
|
+
"REJECTED",
|
|
56199
|
+
"BLOCKED",
|
|
56200
|
+
"ANSWER",
|
|
56201
|
+
"ESCALATE_TO_HUMAN",
|
|
56202
|
+
"REPHRASE"
|
|
56203
|
+
];
|
|
56204
|
+
const normalized = value.trim().toUpperCase().replace(/[`*]/g, "");
|
|
56205
|
+
if (validVerdicts.includes(normalized)) {
|
|
56206
|
+
res.verdict = normalized;
|
|
56207
|
+
} else {
|
|
56208
|
+
console.warn(`[full-auto-intercept] Unknown verdict '${value}' \u2014 defaulting to NEEDS_REVISION`);
|
|
56209
|
+
res.verdict = "NEEDS_REVISION";
|
|
56210
|
+
}
|
|
56211
|
+
break;
|
|
56212
|
+
}
|
|
56213
|
+
case "REASONING":
|
|
56214
|
+
res.reasoning = value.trim();
|
|
56215
|
+
break;
|
|
56216
|
+
case "EVIDENCE_CHECKED":
|
|
56217
|
+
if (value && value !== "none" && value !== '"none"') {
|
|
56218
|
+
res.evidenceChecked = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
56219
|
+
}
|
|
56220
|
+
break;
|
|
56221
|
+
case "ANTI_PATTERNS_DETECTED":
|
|
56222
|
+
if (value && value !== "none" && value !== '"none"') {
|
|
56223
|
+
res.antiPatternsDetected = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
56224
|
+
}
|
|
56225
|
+
break;
|
|
56226
|
+
case "ESCALATION_NEEDED":
|
|
56227
|
+
res.escalationNeeded = value.trim().toUpperCase() === "YES";
|
|
56228
|
+
break;
|
|
56229
|
+
}
|
|
56230
|
+
};
|
|
56231
|
+
for (const line of lines) {
|
|
56232
|
+
const colonIndex = line.indexOf(":");
|
|
56233
|
+
if (colonIndex !== -1) {
|
|
56234
|
+
const key = line.slice(0, colonIndex).trim().toUpperCase();
|
|
56235
|
+
if ([
|
|
56236
|
+
"VERDICT",
|
|
56237
|
+
"REASONING",
|
|
56238
|
+
"EVIDENCE_CHECKED",
|
|
56239
|
+
"ANTI_PATTERNS_DETECTED",
|
|
56240
|
+
"ESCALATION_NEEDED"
|
|
56241
|
+
].includes(key)) {
|
|
56242
|
+
if (currentKey) {
|
|
56243
|
+
commitField(result, currentKey, currentValue);
|
|
56244
|
+
}
|
|
56245
|
+
currentKey = key;
|
|
56246
|
+
currentValue = line.slice(colonIndex + 1).trim();
|
|
56247
|
+
} else {
|
|
56248
|
+
currentValue += `
|
|
56249
|
+
${line}`;
|
|
56250
|
+
}
|
|
56251
|
+
} else {
|
|
56252
|
+
if (line.trim()) {
|
|
56253
|
+
currentValue += `
|
|
56254
|
+
${line}`;
|
|
56255
|
+
}
|
|
56256
|
+
}
|
|
56257
|
+
}
|
|
56258
|
+
if (currentKey) {
|
|
56259
|
+
commitField(result, currentKey, currentValue);
|
|
56260
|
+
}
|
|
56261
|
+
return result;
|
|
56262
|
+
}
|
|
56263
|
+
function escalationTypeToInteractionMode(escalationType) {
|
|
56264
|
+
return escalationType === "phase_completion" ? "phase_completion" : "question_resolution";
|
|
56265
|
+
}
|
|
56266
|
+
async function writeAutoOversightEvent(directory, architectOutput, criticVerdict, criticReasoning, evidenceChecked, interactionCount, deadlockCount, escalationType) {
|
|
56267
|
+
const event = {
|
|
56268
|
+
type: "auto_oversight",
|
|
56269
|
+
timestamp: new Date().toISOString(),
|
|
56270
|
+
interaction_mode: escalationTypeToInteractionMode(escalationType),
|
|
56271
|
+
architect_output: architectOutput,
|
|
56272
|
+
critic_verdict: criticVerdict,
|
|
56273
|
+
critic_reasoning: criticReasoning,
|
|
56274
|
+
evidence_checked: evidenceChecked,
|
|
56275
|
+
interaction_count: interactionCount,
|
|
56276
|
+
deadlock_count: deadlockCount
|
|
56277
|
+
};
|
|
56278
|
+
const lockTaskId = `auto-oversight-${Date.now()}`;
|
|
56279
|
+
const eventsFilePath = "events.jsonl";
|
|
56280
|
+
const dir = directory;
|
|
56281
|
+
let lockResult;
|
|
56282
|
+
try {
|
|
56283
|
+
lockResult = await tryAcquireLock(dir, eventsFilePath, "auto-oversight", lockTaskId);
|
|
56284
|
+
} catch (error93) {
|
|
56285
|
+
console.warn(`[full-auto-intercept] Warning: failed to acquire lock for auto_oversight event: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
56286
|
+
}
|
|
56287
|
+
if (!lockResult?.acquired) {
|
|
56288
|
+
console.warn(`[full-auto-intercept] Warning: could not acquire lock for events.jsonl write \u2014 proceeding without lock`);
|
|
56289
|
+
}
|
|
56290
|
+
try {
|
|
56291
|
+
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
56292
|
+
fs30.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
56293
|
+
`, "utf-8");
|
|
56294
|
+
} catch (writeError) {
|
|
56295
|
+
console.error(`[full-auto-intercept] Warning: failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
56296
|
+
} finally {
|
|
56297
|
+
if (lockResult?.acquired && lockResult.lock._release) {
|
|
56298
|
+
try {
|
|
56299
|
+
await lockResult.lock._release();
|
|
56300
|
+
} catch (releaseError) {
|
|
56301
|
+
console.error(`[full-auto-intercept] Lock release failed:`, releaseError);
|
|
56302
|
+
}
|
|
56303
|
+
}
|
|
56304
|
+
}
|
|
56305
|
+
}
|
|
56306
|
+
function injectVerdictIntoMessages(messages, architectIndex, criticResult, _escalationType, oversightAgentName) {
|
|
56307
|
+
if (criticResult.escalationNeeded || criticResult.verdict === "ESCALATE_TO_HUMAN") {
|
|
56308
|
+
const verdictMessage2 = {
|
|
56309
|
+
info: {
|
|
56310
|
+
role: "assistant",
|
|
56311
|
+
agent: oversightAgentName
|
|
56312
|
+
},
|
|
56313
|
+
parts: [
|
|
56314
|
+
{
|
|
56315
|
+
type: "text",
|
|
56316
|
+
text: `[FULL-AUTO OVERSIGHT \u2014 ESCALATE_TO_HUMAN]
|
|
56317
|
+
|
|
56318
|
+
Critic reasoning: ${criticResult.reasoning}
|
|
56319
|
+
|
|
56320
|
+
This question requires human judgment. The swarm has been paused for human review.`
|
|
56321
|
+
}
|
|
56322
|
+
]
|
|
56323
|
+
};
|
|
56324
|
+
messages.splice(architectIndex + 1, 0, verdictMessage2);
|
|
56325
|
+
return;
|
|
56326
|
+
}
|
|
56327
|
+
if (criticResult.verdict === "ANSWER") {
|
|
56328
|
+
const verdictMessage2 = {
|
|
56329
|
+
info: {
|
|
56330
|
+
role: "assistant",
|
|
56331
|
+
agent: oversightAgentName
|
|
56332
|
+
},
|
|
56333
|
+
parts: [
|
|
56334
|
+
{
|
|
56335
|
+
type: "text",
|
|
56336
|
+
text: `[FULL-AUTO OVERSIGHT \u2014 ANSWER]
|
|
56337
|
+
|
|
56338
|
+
${criticResult.reasoning}`
|
|
56339
|
+
}
|
|
56340
|
+
]
|
|
56341
|
+
};
|
|
56342
|
+
messages.splice(architectIndex + 1, 0, verdictMessage2);
|
|
56343
|
+
return;
|
|
56344
|
+
}
|
|
56345
|
+
const verdictEmoji = criticResult.verdict === "APPROVED" ? "\u2705" : criticResult.verdict === "NEEDS_REVISION" ? "\uD83D\uDD04" : criticResult.verdict === "REJECTED" ? "\u274C" : criticResult.verdict === "BLOCKED" ? "\uD83D\uDEAB" : "\uD83D\uDCAC";
|
|
56346
|
+
const verdictMessage = {
|
|
56347
|
+
info: {
|
|
56348
|
+
role: "assistant",
|
|
56349
|
+
agent: oversightAgentName
|
|
56350
|
+
},
|
|
56351
|
+
parts: [
|
|
56352
|
+
{
|
|
56353
|
+
type: "text",
|
|
56354
|
+
text: `[FULL-AUTO OVERSIGHT] ${verdictEmoji} **${criticResult.verdict}**
|
|
56355
|
+
|
|
56356
|
+
Critic reasoning: ${criticResult.reasoning}`
|
|
56357
|
+
}
|
|
56358
|
+
]
|
|
56359
|
+
};
|
|
56360
|
+
messages.splice(architectIndex + 1, 0, verdictMessage);
|
|
56361
|
+
}
|
|
56362
|
+
async function dispatchCriticAndWriteEvent(directory, architectOutput, criticContext, criticModel, escalationType, interactionCount, deadlockCount, oversightAgentName) {
|
|
56363
|
+
const client = swarmState.opencodeClient;
|
|
56364
|
+
if (!client) {
|
|
56365
|
+
console.warn("[full-auto-intercept] No opencodeClient \u2014 critic dispatch skipped (fallback to PENDING)");
|
|
56366
|
+
const result = {
|
|
56367
|
+
verdict: "PENDING",
|
|
56368
|
+
reasoning: "No opencodeClient available \u2014 critic dispatch not possible",
|
|
56369
|
+
evidenceChecked: [],
|
|
56370
|
+
antiPatternsDetected: [],
|
|
56371
|
+
escalationNeeded: false,
|
|
56372
|
+
rawResponse: ""
|
|
56373
|
+
};
|
|
56374
|
+
await writeAutoOversightEvent(directory, architectOutput, result.verdict, result.reasoning, result.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
56375
|
+
return result;
|
|
56376
|
+
}
|
|
56377
|
+
const oversightAgent = createCriticAutonomousOversightAgent(criticModel, criticContext);
|
|
56378
|
+
console.log(`[full-auto-intercept] Dispatching critic: ${oversightAgent.name} using model ${criticModel}`);
|
|
56379
|
+
let ephemeralSessionId;
|
|
56380
|
+
const cleanup = () => {
|
|
56381
|
+
if (ephemeralSessionId) {
|
|
56382
|
+
const id = ephemeralSessionId;
|
|
56383
|
+
ephemeralSessionId = undefined;
|
|
56384
|
+
client.session.delete({ path: { id } }).catch(() => {});
|
|
56385
|
+
}
|
|
56386
|
+
};
|
|
56387
|
+
let criticResponse = "";
|
|
56388
|
+
try {
|
|
56389
|
+
const createResult = await client.session.create({
|
|
56390
|
+
query: { directory }
|
|
56391
|
+
});
|
|
56392
|
+
if (!createResult.data) {
|
|
56393
|
+
throw new Error(`Failed to create critic session: ${JSON.stringify(createResult.error)}`);
|
|
56394
|
+
}
|
|
56395
|
+
ephemeralSessionId = createResult.data.id;
|
|
56396
|
+
console.log(`[full-auto-intercept] Created ephemeral session: ${ephemeralSessionId}`);
|
|
56397
|
+
const promptResult = await client.session.prompt({
|
|
56398
|
+
path: { id: ephemeralSessionId },
|
|
56399
|
+
body: {
|
|
56400
|
+
agent: oversightAgentName,
|
|
56401
|
+
tools: { write: false, edit: false, patch: false },
|
|
56402
|
+
parts: [{ type: "text", text: criticContext }]
|
|
56403
|
+
}
|
|
56404
|
+
});
|
|
56405
|
+
if (!promptResult.data) {
|
|
56406
|
+
throw new Error(`Critic LLM prompt failed: ${JSON.stringify(promptResult.error)}`);
|
|
56407
|
+
}
|
|
56408
|
+
const textParts = promptResult.data.parts.filter((p) => p.type === "text");
|
|
56409
|
+
criticResponse = textParts.map((p) => p.text).join(`
|
|
56410
|
+
`);
|
|
56411
|
+
console.log(`[full-auto-intercept] Critic response received (${criticResponse.length} chars)`);
|
|
56412
|
+
if (!criticResponse.trim()) {
|
|
56413
|
+
console.warn("[full-auto-intercept] Critic returned empty response \u2014 using fallback verdict");
|
|
56414
|
+
criticResponse = `VERDICT: NEEDS_REVISION
|
|
56415
|
+
REASONING: Critic returned empty response
|
|
56416
|
+
EVIDENCE_CHECKED: none
|
|
56417
|
+
ANTI_PATTERNS_DETECTED: empty_response
|
|
56418
|
+
ESCALATION_NEEDED: NO`;
|
|
56419
|
+
}
|
|
56420
|
+
} finally {
|
|
56421
|
+
cleanup();
|
|
56422
|
+
}
|
|
56423
|
+
let parsed;
|
|
56424
|
+
try {
|
|
56425
|
+
parsed = parseCriticResponse(criticResponse);
|
|
56426
|
+
console.log(`[full-auto-intercept] Critic verdict: ${parsed.verdict} | escalation: ${parsed.escalationNeeded}`);
|
|
56427
|
+
} catch (parseError) {
|
|
56428
|
+
console.error(`[full-auto-intercept] Failed to parse critic response: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
56429
|
+
parsed = {
|
|
56430
|
+
verdict: "NEEDS_REVISION",
|
|
56431
|
+
reasoning: "Critic response parsing failed \u2014 defaulting to NEEDS_REVISION",
|
|
56432
|
+
evidenceChecked: [],
|
|
56433
|
+
antiPatternsDetected: [],
|
|
56434
|
+
escalationNeeded: false,
|
|
56435
|
+
rawResponse: criticResponse
|
|
56436
|
+
};
|
|
56437
|
+
}
|
|
56438
|
+
try {
|
|
56439
|
+
await writeAutoOversightEvent(directory, architectOutput, parsed.verdict, parsed.reasoning, parsed.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
56440
|
+
} catch (writeError) {
|
|
56441
|
+
console.error(`[full-auto-intercept] Failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
56442
|
+
}
|
|
56443
|
+
return parsed;
|
|
56444
|
+
}
|
|
56445
|
+
function createFullAutoInterceptHook(config3, directory) {
|
|
56446
|
+
const fullAutoConfig = config3.full_auto ?? {
|
|
56447
|
+
enabled: false,
|
|
56448
|
+
max_interactions_per_phase: 50,
|
|
56449
|
+
deadlock_threshold: 3,
|
|
56450
|
+
escalation_mode: "pause"
|
|
56451
|
+
};
|
|
56452
|
+
if (fullAutoConfig.enabled !== true) {
|
|
56453
|
+
return {
|
|
56454
|
+
messagesTransform: async () => {}
|
|
56455
|
+
};
|
|
56456
|
+
}
|
|
56457
|
+
const deadlockThreshold = fullAutoConfig.deadlock_threshold ?? 3;
|
|
56458
|
+
const maxInteractions = fullAutoConfig.max_interactions_per_phase ?? 50;
|
|
56459
|
+
const escalationMode = fullAutoConfig.escalation_mode ?? "pause";
|
|
56460
|
+
const messagesTransform = async (_input, output) => {
|
|
56461
|
+
const messages = output.messages;
|
|
56462
|
+
if (!messages || messages.length === 0)
|
|
56463
|
+
return;
|
|
56464
|
+
let lastArchitectMessageIndex = -1;
|
|
56465
|
+
for (let i2 = messages.length - 1;i2 >= 0; i2--) {
|
|
56466
|
+
const msg = messages[i2];
|
|
56467
|
+
if (msg?.info?.role === "user") {
|
|
56468
|
+
const agent = msg.info?.agent;
|
|
56469
|
+
const strippedAgent = agent ? stripKnownSwarmPrefix(agent) : undefined;
|
|
56470
|
+
if (!agent || strippedAgent === "architect") {
|
|
56471
|
+
lastArchitectMessageIndex = i2;
|
|
56472
|
+
break;
|
|
56473
|
+
}
|
|
56474
|
+
}
|
|
56475
|
+
}
|
|
56476
|
+
if (lastArchitectMessageIndex === -1)
|
|
56477
|
+
return;
|
|
56478
|
+
const architectMessage = messages[lastArchitectMessageIndex];
|
|
56479
|
+
const architectText = extractMessageText3(architectMessage);
|
|
56480
|
+
if (!architectText)
|
|
56481
|
+
return;
|
|
56482
|
+
const sessionID = architectMessage.info?.sessionID;
|
|
56483
|
+
if (!hasActiveFullAuto(sessionID))
|
|
56484
|
+
return;
|
|
56485
|
+
let session = null;
|
|
56486
|
+
if (sessionID) {
|
|
56487
|
+
const { ensureAgentSession: ensureAgentSession2 } = await Promise.resolve().then(() => (init_state(), exports_state));
|
|
56488
|
+
session = ensureAgentSession2(sessionID);
|
|
56489
|
+
}
|
|
56490
|
+
if (session) {
|
|
56491
|
+
const interactionCount = session.fullAutoInteractionCount ?? 0;
|
|
56492
|
+
if (interactionCount >= maxInteractions) {
|
|
56493
|
+
const escalated = await handleEscalation(directory, "interaction_limit", sessionID, architectText, interactionCount, session.fullAutoDeadlockCount ?? 0, escalationMode);
|
|
56494
|
+
if (escalated)
|
|
56495
|
+
return;
|
|
56496
|
+
}
|
|
56497
|
+
}
|
|
56498
|
+
const escalationType = detectEscalation(architectText);
|
|
56499
|
+
if (!escalationType)
|
|
56500
|
+
return;
|
|
56501
|
+
if (session) {
|
|
56502
|
+
session.fullAutoInteractionCount = (session.fullAutoInteractionCount ?? 0) + 1;
|
|
56503
|
+
}
|
|
56504
|
+
if (escalationType === "question") {
|
|
56505
|
+
const questionHash = hashString(architectText.trim());
|
|
56506
|
+
if (session) {
|
|
56507
|
+
const lastQuestionHash = session.fullAutoLastQuestionHash;
|
|
56508
|
+
if (lastQuestionHash === questionHash) {
|
|
56509
|
+
session.fullAutoDeadlockCount = (session.fullAutoDeadlockCount ?? 0) + 1;
|
|
56510
|
+
console.warn(`[full-auto-intercept] Potential deadlock detected (count: ${session.fullAutoDeadlockCount}/${deadlockThreshold}) \u2014 identical question repeated`);
|
|
56511
|
+
if (session.fullAutoDeadlockCount >= deadlockThreshold) {
|
|
56512
|
+
const escalated = await handleEscalation(directory, "deadlock", sessionID, architectText, session.fullAutoInteractionCount ?? 0, session.fullAutoDeadlockCount, escalationMode);
|
|
56513
|
+
if (escalated)
|
|
56514
|
+
return;
|
|
56515
|
+
}
|
|
56516
|
+
} else {
|
|
56517
|
+
session.fullAutoDeadlockCount = 0;
|
|
56518
|
+
}
|
|
56519
|
+
session.fullAutoLastQuestionHash = questionHash;
|
|
56520
|
+
}
|
|
56521
|
+
}
|
|
56522
|
+
console.log(`[full-auto-intercept] Escalation detected (${escalationType}) \u2014 triggering autonomous oversight`);
|
|
56523
|
+
const criticContext = buildCriticContext(architectText, escalationType);
|
|
56524
|
+
const criticModel = fullAutoConfig.critic_model ?? "claude-sonnet-4-20250514";
|
|
56525
|
+
const oversightAgent = createCriticAutonomousOversightAgent(criticModel, criticContext);
|
|
56526
|
+
const architectAgent = architectMessage.info?.agent;
|
|
56527
|
+
const resolvedOversightAgentName = resolveOversightAgentName(architectAgent);
|
|
56528
|
+
const dispatchAgentName = resolvedOversightAgentName && resolvedOversightAgentName.length > 0 ? resolvedOversightAgentName : "critic_oversight";
|
|
56529
|
+
console.log(`[full-auto-intercept] Created autonomous oversight agent: ${oversightAgent.name} using model ${criticModel} (dispatch as: ${dispatchAgentName})`);
|
|
56530
|
+
const criticResult = await dispatchCriticAndWriteEvent(directory, architectText, criticContext, criticModel, escalationType, session?.fullAutoInteractionCount ?? 0, session?.fullAutoDeadlockCount ?? 0, dispatchAgentName);
|
|
56531
|
+
injectVerdictIntoMessages(messages, lastArchitectMessageIndex, criticResult, escalationType, dispatchAgentName);
|
|
56532
|
+
};
|
|
56533
|
+
return {
|
|
56534
|
+
messagesTransform
|
|
56535
|
+
};
|
|
56536
|
+
}
|
|
56537
|
+
function buildCriticContext(architectOutput, escalationType) {
|
|
56538
|
+
const contextHeader = escalationType === "phase_completion" ? `## ARCHITECT PHASE COMPLETION REQUEST
|
|
56539
|
+
|
|
56540
|
+
The architect has signaled phase completion and is awaiting oversight approval to proceed.` : `## ARCHITECT QUESTION
|
|
56541
|
+
|
|
56542
|
+
The architect has asked a question and is awaiting an autonomous answer or escalation.`;
|
|
56543
|
+
const truncatedOutput = architectOutput.length > 2000 ? architectOutput.slice(0, 2000) + `
|
|
56544
|
+
... [truncated]` : architectOutput;
|
|
56545
|
+
return `${contextHeader}
|
|
56546
|
+
|
|
56547
|
+
### ARCHITECT OUTPUT:
|
|
56548
|
+
${truncatedOutput}
|
|
56549
|
+
|
|
56550
|
+
### YOUR TASK:
|
|
56551
|
+
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.
|
|
56552
|
+
|
|
56553
|
+
Remember: You are the sole quality gate. Default posture is REJECT unless you have positive evidence of correctness.`;
|
|
56554
|
+
}
|
|
56555
|
+
async function writeEscalationReport(directory, reason, architectOutput, interactionCount, deadlockCount, phase) {
|
|
56556
|
+
try {
|
|
56557
|
+
const reportPath = validateSwarmPath(directory, "escalation-report.md");
|
|
56558
|
+
let currentPhase = phase;
|
|
56559
|
+
if (currentPhase === undefined) {
|
|
56560
|
+
try {
|
|
56561
|
+
const planPath = validateSwarmPath(directory, "plan.json");
|
|
56562
|
+
const planContent = fs30.readFileSync(planPath, "utf-8");
|
|
56563
|
+
const plan = JSON.parse(planContent);
|
|
56564
|
+
const incompletePhases = plan.phases.filter((p) => p.status !== "complete").sort((a, b) => b.id - a.id);
|
|
56565
|
+
currentPhase = incompletePhases[0]?.id;
|
|
56566
|
+
} catch {}
|
|
56567
|
+
}
|
|
56568
|
+
const timestamp = new Date().toISOString();
|
|
56569
|
+
const reasonLabels = {
|
|
56570
|
+
interaction_limit: "Interaction Limit Exceeded",
|
|
56571
|
+
deadlock: "Deadlock Threshold Exceeded",
|
|
56572
|
+
ESCALATE_TO_HUMAN: "Critic Response: ESCALATE_TO_HUMAN"
|
|
56573
|
+
};
|
|
56574
|
+
const reportContent = `# Full-Auto Escalation Report
|
|
56575
|
+
|
|
56576
|
+
## Timestamp
|
|
56577
|
+
${timestamp}
|
|
56578
|
+
|
|
56579
|
+
## Reason for Escalation
|
|
56580
|
+
${reasonLabels[reason]}
|
|
56581
|
+
|
|
56582
|
+
## Architect Output That Triggered Escalation
|
|
56583
|
+
\`\`\`
|
|
56584
|
+
${architectOutput.slice(0, 4000)}
|
|
56585
|
+
${architectOutput.length > 4000 ? `
|
|
56586
|
+
... [output truncated]` : ""}
|
|
56587
|
+
\`\`\`
|
|
56588
|
+
|
|
56589
|
+
## FullAuto State at Time of Escalation
|
|
56590
|
+
- **Interaction Count**: ${interactionCount}
|
|
56591
|
+
- **Deadlock Count**: ${deadlockCount}
|
|
56592
|
+
|
|
56593
|
+
## Current Phase and Plan Context
|
|
56594
|
+
- **Current Phase**: ${currentPhase !== undefined ? `Phase ${currentPhase}` : "Unknown"}
|
|
56595
|
+
${currentPhase !== undefined ? `- **Phase Status**: Pending completion` : ""}
|
|
56596
|
+
|
|
56597
|
+
## Resolution
|
|
56598
|
+
This escalation requires human intervention. The swarm has been paused.
|
|
56599
|
+
Please review the architect's output above and provide guidance.
|
|
56600
|
+
`;
|
|
56601
|
+
fs30.writeFileSync(reportPath, reportContent, "utf-8");
|
|
56602
|
+
console.log(`[full-auto-intercept] Escalation report written to: ${reportPath}`);
|
|
56603
|
+
} catch (error93) {
|
|
56604
|
+
console.error(`[full-auto-intercept] Failed to write escalation report:`, error93 instanceof Error ? error93.message : String(error93));
|
|
56605
|
+
}
|
|
56606
|
+
}
|
|
56607
|
+
async function handleEscalation(directory, reason, sessionID, architectOutput, interactionCount, deadlockCount, escalationMode, phase) {
|
|
56608
|
+
telemetry.autoOversightEscalation(sessionID ?? "unknown", reason, interactionCount, deadlockCount, phase);
|
|
56609
|
+
await writeEscalationReport(directory, reason, architectOutput, interactionCount, deadlockCount, phase);
|
|
56610
|
+
if (escalationMode === "terminate") {
|
|
56611
|
+
console.error(`[full-auto-intercept] ESCALATION (terminate mode) \u2014 reason: ${reason}, session: ${sessionID}`);
|
|
56612
|
+
process.exit(1);
|
|
56613
|
+
}
|
|
56614
|
+
console.warn(`[full-auto-intercept] ESCALATION (pause mode) \u2014 reason: ${reason}, session: ${sessionID}`);
|
|
56615
|
+
return true;
|
|
56616
|
+
}
|
|
55845
56617
|
// src/hooks/messages-transform.ts
|
|
55846
56618
|
function consolidateSystemMessages(messages) {
|
|
55847
56619
|
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 +56682,7 @@ function consolidateSystemMessages(messages) {
|
|
|
55910
56682
|
// src/hooks/phase-monitor.ts
|
|
55911
56683
|
init_schema();
|
|
55912
56684
|
init_manager2();
|
|
55913
|
-
import * as
|
|
56685
|
+
import * as path42 from "path";
|
|
55914
56686
|
init_utils2();
|
|
55915
56687
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
55916
56688
|
let lastKnownPhase = null;
|
|
@@ -55931,9 +56703,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
|
|
|
55931
56703
|
const llmDelegate = delegateFactory?.(sessionId);
|
|
55932
56704
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
55933
56705
|
if (initResult.briefing) {
|
|
55934
|
-
const briefingPath =
|
|
56706
|
+
const briefingPath = path42.join(directory, ".swarm", "curator-briefing.md");
|
|
55935
56707
|
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
|
|
55936
|
-
await mkdir5(
|
|
56708
|
+
await mkdir5(path42.dirname(briefingPath), { recursive: true });
|
|
55937
56709
|
await writeFile5(briefingPath, initResult.briefing, "utf-8");
|
|
55938
56710
|
const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
|
|
55939
56711
|
const initReceipt = buildApprovedReceipt2({
|
|
@@ -56066,15 +56838,15 @@ init_schema();
|
|
|
56066
56838
|
init_manager();
|
|
56067
56839
|
init_detector();
|
|
56068
56840
|
init_manager2();
|
|
56069
|
-
import * as
|
|
56070
|
-
import * as
|
|
56841
|
+
import * as fs35 from "fs";
|
|
56842
|
+
import * as path46 from "path";
|
|
56071
56843
|
|
|
56072
56844
|
// src/services/decision-drift-analyzer.ts
|
|
56073
56845
|
init_utils2();
|
|
56074
56846
|
init_manager2();
|
|
56075
56847
|
init_utils();
|
|
56076
|
-
import * as
|
|
56077
|
-
import * as
|
|
56848
|
+
import * as fs32 from "fs";
|
|
56849
|
+
import * as path43 from "path";
|
|
56078
56850
|
var DEFAULT_DRIFT_CONFIG = {
|
|
56079
56851
|
staleThresholdPhases: 1,
|
|
56080
56852
|
detectContradictions: true,
|
|
@@ -56228,11 +57000,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
56228
57000
|
currentPhase = legacyPhase;
|
|
56229
57001
|
}
|
|
56230
57002
|
}
|
|
56231
|
-
const contextPath =
|
|
57003
|
+
const contextPath = path43.join(directory, ".swarm", "context.md");
|
|
56232
57004
|
let contextContent = "";
|
|
56233
57005
|
try {
|
|
56234
|
-
if (
|
|
56235
|
-
contextContent =
|
|
57006
|
+
if (fs32.existsSync(contextPath)) {
|
|
57007
|
+
contextContent = fs32.readFileSync(contextPath, "utf-8");
|
|
56236
57008
|
}
|
|
56237
57009
|
} catch (error93) {
|
|
56238
57010
|
log("[DecisionDriftAnalyzer] context file read failed", {
|
|
@@ -56351,14 +57123,15 @@ init_preflight_integration();
|
|
|
56351
57123
|
init_preflight_service();
|
|
56352
57124
|
|
|
56353
57125
|
// src/hooks/system-enhancer.ts
|
|
57126
|
+
init_state();
|
|
56354
57127
|
init_telemetry();
|
|
56355
57128
|
init_utils();
|
|
56356
57129
|
|
|
56357
57130
|
// src/hooks/adversarial-detector.ts
|
|
56358
57131
|
init_constants();
|
|
56359
57132
|
init_schema();
|
|
56360
|
-
import * as
|
|
56361
|
-
import * as
|
|
57133
|
+
import * as fs33 from "fs/promises";
|
|
57134
|
+
import * as path44 from "path";
|
|
56362
57135
|
function safeGet(obj, key) {
|
|
56363
57136
|
if (!obj || !Object.hasOwn(obj, key))
|
|
56364
57137
|
return;
|
|
@@ -56572,10 +57345,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
|
|
|
56572
57345
|
let eventLogged = false;
|
|
56573
57346
|
let checkpointCreated = false;
|
|
56574
57347
|
try {
|
|
56575
|
-
const swarmDir =
|
|
56576
|
-
await
|
|
56577
|
-
const eventsPath =
|
|
56578
|
-
await
|
|
57348
|
+
const swarmDir = path44.join(directory, ".swarm");
|
|
57349
|
+
await fs33.mkdir(swarmDir, { recursive: true });
|
|
57350
|
+
const eventsPath = path44.join(swarmDir, "events.jsonl");
|
|
57351
|
+
await fs33.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
|
|
56579
57352
|
`);
|
|
56580
57353
|
eventLogged = true;
|
|
56581
57354
|
} catch {}
|
|
@@ -56986,7 +57759,7 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56986
57759
|
} catch {}
|
|
56987
57760
|
try {
|
|
56988
57761
|
const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
|
|
56989
|
-
if (!
|
|
57762
|
+
if (!fs35.existsSync(darkMatterPath)) {
|
|
56990
57763
|
const {
|
|
56991
57764
|
detectDarkMatter: detectDarkMatter2,
|
|
56992
57765
|
formatDarkMatterOutput: formatDarkMatterOutput2,
|
|
@@ -56998,10 +57771,10 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
56998
57771
|
});
|
|
56999
57772
|
if (darkMatter && darkMatter.length > 0) {
|
|
57000
57773
|
const darkMatterReport = formatDarkMatterOutput2(darkMatter);
|
|
57001
|
-
await
|
|
57774
|
+
await fs35.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
|
|
57002
57775
|
warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
|
|
57003
57776
|
try {
|
|
57004
|
-
const projectName =
|
|
57777
|
+
const projectName = path46.basename(path46.resolve(directory));
|
|
57005
57778
|
const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
|
|
57006
57779
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
57007
57780
|
const existingEntries = await readKnowledge(knowledgePath);
|
|
@@ -57065,11 +57838,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
57065
57838
|
if (handoffContent) {
|
|
57066
57839
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
57067
57840
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
57068
|
-
if (
|
|
57841
|
+
if (fs35.existsSync(consumedPath)) {
|
|
57069
57842
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
57070
|
-
|
|
57843
|
+
fs35.unlinkSync(consumedPath);
|
|
57071
57844
|
}
|
|
57072
|
-
|
|
57845
|
+
fs35.renameSync(handoffPath, consumedPath);
|
|
57073
57846
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
57074
57847
|
The previous model's session ended. Here is your starting context:
|
|
57075
57848
|
|
|
@@ -57195,6 +57968,15 @@ ${handoffBlock}`);
|
|
|
57195
57968
|
const activeAgent_retro = swarmState.activeAgent.get(sessionId_retro ?? "");
|
|
57196
57969
|
const isArchitect2 = !activeAgent_retro || stripKnownSwarmPrefix(activeAgent_retro) === "architect";
|
|
57197
57970
|
if (isArchitect2) {
|
|
57971
|
+
const sessionIdBanner = _input.sessionID;
|
|
57972
|
+
if (hasActiveTurboMode(sessionIdBanner) || hasActiveFullAuto(sessionIdBanner)) {
|
|
57973
|
+
if (hasActiveTurboMode(sessionIdBanner)) {
|
|
57974
|
+
tryInject(TURBO_MODE_BANNER);
|
|
57975
|
+
}
|
|
57976
|
+
if (hasActiveFullAuto(sessionIdBanner)) {
|
|
57977
|
+
tryInject(FULL_AUTO_BANNER);
|
|
57978
|
+
}
|
|
57979
|
+
}
|
|
57198
57980
|
try {
|
|
57199
57981
|
const currentPhaseNum = plan2?.current_phase ?? 1;
|
|
57200
57982
|
const retroText = await buildRetroInjection(directory, currentPhaseNum, plan2?.title ?? undefined);
|
|
@@ -57357,11 +58139,11 @@ ${budgetWarning}`);
|
|
|
57357
58139
|
if (handoffContent) {
|
|
57358
58140
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
57359
58141
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
57360
|
-
if (
|
|
58142
|
+
if (fs35.existsSync(consumedPath)) {
|
|
57361
58143
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
57362
|
-
|
|
58144
|
+
fs35.unlinkSync(consumedPath);
|
|
57363
58145
|
}
|
|
57364
|
-
|
|
58146
|
+
fs35.renameSync(handoffPath, consumedPath);
|
|
57365
58147
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
57366
58148
|
The previous model's session ended. Here is your starting context:
|
|
57367
58149
|
|
|
@@ -57527,6 +58309,29 @@ ${handoffBlock}`;
|
|
|
57527
58309
|
const activeAgent_retro_b = swarmState.activeAgent.get(sessionId_retro_b ?? "");
|
|
57528
58310
|
const isArchitect_b = !activeAgent_retro_b || stripKnownSwarmPrefix(activeAgent_retro_b) === "architect";
|
|
57529
58311
|
if (isArchitect_b) {
|
|
58312
|
+
const sessionIdBanner_b = _input.sessionID;
|
|
58313
|
+
if (hasActiveTurboMode(sessionIdBanner_b) || hasActiveFullAuto(sessionIdBanner_b)) {
|
|
58314
|
+
if (hasActiveTurboMode(sessionIdBanner_b)) {
|
|
58315
|
+
candidates.push({
|
|
58316
|
+
id: `candidate-${idCounter++}`,
|
|
58317
|
+
kind: "agent_context",
|
|
58318
|
+
text: TURBO_MODE_BANNER,
|
|
58319
|
+
tokens: estimateTokens(TURBO_MODE_BANNER),
|
|
58320
|
+
priority: 1,
|
|
58321
|
+
metadata: { contentType: "prose" }
|
|
58322
|
+
});
|
|
58323
|
+
}
|
|
58324
|
+
if (hasActiveFullAuto(sessionIdBanner_b)) {
|
|
58325
|
+
candidates.push({
|
|
58326
|
+
id: `candidate-${idCounter++}`,
|
|
58327
|
+
kind: "agent_context",
|
|
58328
|
+
text: FULL_AUTO_BANNER,
|
|
58329
|
+
tokens: estimateTokens(FULL_AUTO_BANNER),
|
|
58330
|
+
priority: 1,
|
|
58331
|
+
metadata: { contentType: "prose" }
|
|
58332
|
+
});
|
|
58333
|
+
}
|
|
58334
|
+
}
|
|
57530
58335
|
try {
|
|
57531
58336
|
const currentPhaseNum_b = plan?.current_phase ?? 1;
|
|
57532
58337
|
const retroText_b = await buildRetroInjection(directory, currentPhaseNum_b, plan?.title ?? undefined);
|
|
@@ -58055,6 +58860,7 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
58055
58860
|
}
|
|
58056
58861
|
|
|
58057
58862
|
// src/hooks/delegation-ledger.ts
|
|
58863
|
+
init_state();
|
|
58058
58864
|
var ledgerBySession = new Map;
|
|
58059
58865
|
var callStartTimes = new Map;
|
|
58060
58866
|
function createDelegationLedgerHook(config3, _directory, injectAdvisory) {
|
|
@@ -58146,14 +58952,14 @@ function isReadTool(toolName) {
|
|
|
58146
58952
|
}
|
|
58147
58953
|
|
|
58148
58954
|
// src/hooks/incremental-verify.ts
|
|
58149
|
-
import * as
|
|
58150
|
-
import * as
|
|
58955
|
+
import * as fs36 from "fs";
|
|
58956
|
+
import * as path47 from "path";
|
|
58151
58957
|
|
|
58152
58958
|
// src/hooks/spawn-helper.ts
|
|
58153
58959
|
import * as child_process4 from "child_process";
|
|
58154
58960
|
var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
|
|
58155
58961
|
function spawnAsync(command, cwd, timeoutMs) {
|
|
58156
|
-
return new Promise((
|
|
58962
|
+
return new Promise((resolve15) => {
|
|
58157
58963
|
try {
|
|
58158
58964
|
const [rawCmd, ...args2] = command;
|
|
58159
58965
|
const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
|
|
@@ -58200,24 +59006,24 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
58200
59006
|
try {
|
|
58201
59007
|
proc.kill();
|
|
58202
59008
|
} catch {}
|
|
58203
|
-
|
|
59009
|
+
resolve15(null);
|
|
58204
59010
|
}, timeoutMs);
|
|
58205
59011
|
proc.on("close", (code) => {
|
|
58206
59012
|
if (done)
|
|
58207
59013
|
return;
|
|
58208
59014
|
done = true;
|
|
58209
59015
|
clearTimeout(timer);
|
|
58210
|
-
|
|
59016
|
+
resolve15({ exitCode: code ?? 1, stdout, stderr });
|
|
58211
59017
|
});
|
|
58212
59018
|
proc.on("error", () => {
|
|
58213
59019
|
if (done)
|
|
58214
59020
|
return;
|
|
58215
59021
|
done = true;
|
|
58216
59022
|
clearTimeout(timer);
|
|
58217
|
-
|
|
59023
|
+
resolve15(null);
|
|
58218
59024
|
});
|
|
58219
59025
|
} catch {
|
|
58220
|
-
|
|
59026
|
+
resolve15(null);
|
|
58221
59027
|
}
|
|
58222
59028
|
});
|
|
58223
59029
|
}
|
|
@@ -58225,21 +59031,21 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
58225
59031
|
// src/hooks/incremental-verify.ts
|
|
58226
59032
|
var emittedSkipAdvisories = new Set;
|
|
58227
59033
|
function detectPackageManager(projectDir) {
|
|
58228
|
-
if (
|
|
59034
|
+
if (fs36.existsSync(path47.join(projectDir, "bun.lockb")))
|
|
58229
59035
|
return "bun";
|
|
58230
|
-
if (
|
|
59036
|
+
if (fs36.existsSync(path47.join(projectDir, "pnpm-lock.yaml")))
|
|
58231
59037
|
return "pnpm";
|
|
58232
|
-
if (
|
|
59038
|
+
if (fs36.existsSync(path47.join(projectDir, "yarn.lock")))
|
|
58233
59039
|
return "yarn";
|
|
58234
|
-
if (
|
|
59040
|
+
if (fs36.existsSync(path47.join(projectDir, "package-lock.json")))
|
|
58235
59041
|
return "npm";
|
|
58236
59042
|
return "bun";
|
|
58237
59043
|
}
|
|
58238
59044
|
function detectTypecheckCommand(projectDir) {
|
|
58239
|
-
const pkgPath =
|
|
58240
|
-
if (
|
|
59045
|
+
const pkgPath = path47.join(projectDir, "package.json");
|
|
59046
|
+
if (fs36.existsSync(pkgPath)) {
|
|
58241
59047
|
try {
|
|
58242
|
-
const pkg = JSON.parse(
|
|
59048
|
+
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
|
|
58243
59049
|
const scripts = pkg.scripts;
|
|
58244
59050
|
if (scripts?.typecheck) {
|
|
58245
59051
|
const pm = detectPackageManager(projectDir);
|
|
@@ -58253,8 +59059,8 @@ function detectTypecheckCommand(projectDir) {
|
|
|
58253
59059
|
...pkg.dependencies,
|
|
58254
59060
|
...pkg.devDependencies
|
|
58255
59061
|
};
|
|
58256
|
-
if (!deps?.typescript && !
|
|
58257
|
-
const hasTSMarkers = deps?.typescript ||
|
|
59062
|
+
if (!deps?.typescript && !fs36.existsSync(path47.join(projectDir, "tsconfig.json"))) {}
|
|
59063
|
+
const hasTSMarkers = deps?.typescript || fs36.existsSync(path47.join(projectDir, "tsconfig.json"));
|
|
58258
59064
|
if (hasTSMarkers) {
|
|
58259
59065
|
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
58260
59066
|
}
|
|
@@ -58262,17 +59068,17 @@ function detectTypecheckCommand(projectDir) {
|
|
|
58262
59068
|
return null;
|
|
58263
59069
|
}
|
|
58264
59070
|
}
|
|
58265
|
-
if (
|
|
59071
|
+
if (fs36.existsSync(path47.join(projectDir, "go.mod"))) {
|
|
58266
59072
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
58267
59073
|
}
|
|
58268
|
-
if (
|
|
59074
|
+
if (fs36.existsSync(path47.join(projectDir, "Cargo.toml"))) {
|
|
58269
59075
|
return { command: ["cargo", "check"], language: "rust" };
|
|
58270
59076
|
}
|
|
58271
|
-
if (
|
|
59077
|
+
if (fs36.existsSync(path47.join(projectDir, "pyproject.toml")) || fs36.existsSync(path47.join(projectDir, "requirements.txt")) || fs36.existsSync(path47.join(projectDir, "setup.py"))) {
|
|
58272
59078
|
return { command: null, language: "python" };
|
|
58273
59079
|
}
|
|
58274
59080
|
try {
|
|
58275
|
-
const entries =
|
|
59081
|
+
const entries = fs36.readdirSync(projectDir);
|
|
58276
59082
|
if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
58277
59083
|
return {
|
|
58278
59084
|
command: ["dotnet", "build", "--no-restore"],
|
|
@@ -58606,7 +59412,8 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
|
|
|
58606
59412
|
// src/hooks/scope-guard.ts
|
|
58607
59413
|
init_constants();
|
|
58608
59414
|
init_schema();
|
|
58609
|
-
|
|
59415
|
+
init_state();
|
|
59416
|
+
import * as path49 from "path";
|
|
58610
59417
|
var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
|
|
58611
59418
|
function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
58612
59419
|
const enabled = config3.enabled ?? true;
|
|
@@ -58658,19 +59465,20 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
|
|
|
58658
59465
|
}
|
|
58659
59466
|
function isFileInScope(filePath, scopeEntries, directory) {
|
|
58660
59467
|
const dir = directory ?? process.cwd();
|
|
58661
|
-
const resolvedFile =
|
|
59468
|
+
const resolvedFile = path49.resolve(dir, filePath);
|
|
58662
59469
|
return scopeEntries.some((scope) => {
|
|
58663
|
-
const resolvedScope =
|
|
59470
|
+
const resolvedScope = path49.resolve(dir, scope);
|
|
58664
59471
|
if (resolvedFile === resolvedScope)
|
|
58665
59472
|
return true;
|
|
58666
|
-
const rel =
|
|
58667
|
-
return rel.length > 0 && !rel.startsWith("..") && !
|
|
59473
|
+
const rel = path49.relative(resolvedScope, resolvedFile);
|
|
59474
|
+
return rel.length > 0 && !rel.startsWith("..") && !path49.isAbsolute(rel);
|
|
58668
59475
|
});
|
|
58669
59476
|
}
|
|
58670
59477
|
|
|
58671
59478
|
// src/hooks/self-review.ts
|
|
58672
59479
|
init_constants();
|
|
58673
59480
|
init_schema();
|
|
59481
|
+
init_state();
|
|
58674
59482
|
function createSelfReviewHook(config3, injectAdvisory) {
|
|
58675
59483
|
const enabled = config3.enabled ?? true;
|
|
58676
59484
|
const skipInTurbo = config3.skip_in_turbo ?? true;
|
|
@@ -58713,8 +59521,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
58713
59521
|
}
|
|
58714
59522
|
|
|
58715
59523
|
// src/hooks/slop-detector.ts
|
|
58716
|
-
import * as
|
|
58717
|
-
import * as
|
|
59524
|
+
import * as fs38 from "fs";
|
|
59525
|
+
import * as path50 from "path";
|
|
58718
59526
|
var WRITE_EDIT_TOOLS = new Set([
|
|
58719
59527
|
"write",
|
|
58720
59528
|
"edit",
|
|
@@ -58759,12 +59567,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
58759
59567
|
function walkFiles(dir, exts, deadline) {
|
|
58760
59568
|
const results = [];
|
|
58761
59569
|
try {
|
|
58762
|
-
for (const entry of
|
|
59570
|
+
for (const entry of fs38.readdirSync(dir, { withFileTypes: true })) {
|
|
58763
59571
|
if (deadline !== undefined && Date.now() > deadline)
|
|
58764
59572
|
break;
|
|
58765
59573
|
if (entry.isSymbolicLink())
|
|
58766
59574
|
continue;
|
|
58767
|
-
const full =
|
|
59575
|
+
const full = path50.join(dir, entry.name);
|
|
58768
59576
|
if (entry.isDirectory()) {
|
|
58769
59577
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
58770
59578
|
continue;
|
|
@@ -58779,7 +59587,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
58779
59587
|
return results;
|
|
58780
59588
|
}
|
|
58781
59589
|
function checkDeadExports(content, projectDir, startTime) {
|
|
58782
|
-
const hasPackageJson =
|
|
59590
|
+
const hasPackageJson = fs38.existsSync(path50.join(projectDir, "package.json"));
|
|
58783
59591
|
if (!hasPackageJson)
|
|
58784
59592
|
return null;
|
|
58785
59593
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -58802,7 +59610,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
58802
59610
|
if (found || Date.now() - startTime > 480)
|
|
58803
59611
|
break;
|
|
58804
59612
|
try {
|
|
58805
|
-
const text =
|
|
59613
|
+
const text = fs38.readFileSync(file3, "utf-8");
|
|
58806
59614
|
if (importPattern.test(text))
|
|
58807
59615
|
found = true;
|
|
58808
59616
|
importPattern.lastIndex = 0;
|
|
@@ -58935,7 +59743,7 @@ Review before proceeding.`;
|
|
|
58935
59743
|
|
|
58936
59744
|
// src/hooks/steering-consumed.ts
|
|
58937
59745
|
init_utils2();
|
|
58938
|
-
import * as
|
|
59746
|
+
import * as fs39 from "fs";
|
|
58939
59747
|
function recordSteeringConsumed(directory, directiveId) {
|
|
58940
59748
|
try {
|
|
58941
59749
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -58944,7 +59752,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
58944
59752
|
directiveId,
|
|
58945
59753
|
timestamp: new Date().toISOString()
|
|
58946
59754
|
};
|
|
58947
|
-
|
|
59755
|
+
fs39.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
58948
59756
|
`, "utf-8");
|
|
58949
59757
|
} catch {}
|
|
58950
59758
|
}
|
|
@@ -58989,6 +59797,7 @@ init_config_doctor();
|
|
|
58989
59797
|
|
|
58990
59798
|
// src/session/snapshot-reader.ts
|
|
58991
59799
|
init_utils2();
|
|
59800
|
+
init_state();
|
|
58992
59801
|
import { renameSync as renameSync13 } from "fs";
|
|
58993
59802
|
var TRANSIENT_SESSION_FIELDS = [
|
|
58994
59803
|
{ name: "revisionLimitHit", resetValue: false },
|
|
@@ -59081,6 +59890,10 @@ function deserializeAgentSession(s) {
|
|
|
59081
59890
|
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
59082
59891
|
coderRevisions: s.coderRevisions ?? 0,
|
|
59083
59892
|
revisionLimitHit: s.revisionLimitHit ?? false,
|
|
59893
|
+
fullAutoMode: s.fullAutoMode ?? false,
|
|
59894
|
+
fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
|
|
59895
|
+
fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
|
|
59896
|
+
fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
|
|
59084
59897
|
sessionRehydratedAt: s.sessionRehydratedAt ?? 0
|
|
59085
59898
|
};
|
|
59086
59899
|
}
|
|
@@ -59176,19 +59989,20 @@ async function loadSnapshot(directory) {
|
|
|
59176
59989
|
}
|
|
59177
59990
|
|
|
59178
59991
|
// src/index.ts
|
|
59992
|
+
init_state();
|
|
59179
59993
|
init_telemetry();
|
|
59180
59994
|
|
|
59181
59995
|
// src/tools/batch-symbols.ts
|
|
59182
59996
|
init_tool();
|
|
59183
59997
|
init_create_tool();
|
|
59184
|
-
import * as
|
|
59185
|
-
import * as
|
|
59998
|
+
import * as fs41 from "fs";
|
|
59999
|
+
import * as path52 from "path";
|
|
59186
60000
|
|
|
59187
60001
|
// src/tools/symbols.ts
|
|
59188
60002
|
init_tool();
|
|
59189
60003
|
init_create_tool();
|
|
59190
|
-
import * as
|
|
59191
|
-
import * as
|
|
60004
|
+
import * as fs40 from "fs";
|
|
60005
|
+
import * as path51 from "path";
|
|
59192
60006
|
var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
|
|
59193
60007
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
59194
60008
|
function containsWindowsAttacks(str) {
|
|
@@ -59205,11 +60019,11 @@ function containsWindowsAttacks(str) {
|
|
|
59205
60019
|
}
|
|
59206
60020
|
function isPathInWorkspace(filePath, workspace) {
|
|
59207
60021
|
try {
|
|
59208
|
-
const resolvedPath =
|
|
59209
|
-
const realWorkspace =
|
|
59210
|
-
const realResolvedPath =
|
|
59211
|
-
const relativePath =
|
|
59212
|
-
if (relativePath.startsWith("..") ||
|
|
60022
|
+
const resolvedPath = path51.resolve(workspace, filePath);
|
|
60023
|
+
const realWorkspace = fs40.realpathSync(workspace);
|
|
60024
|
+
const realResolvedPath = fs40.realpathSync(resolvedPath);
|
|
60025
|
+
const relativePath = path51.relative(realWorkspace, realResolvedPath);
|
|
60026
|
+
if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
|
|
59213
60027
|
return false;
|
|
59214
60028
|
}
|
|
59215
60029
|
return true;
|
|
@@ -59221,17 +60035,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
59221
60035
|
return isPathInWorkspace(filePath, workspace);
|
|
59222
60036
|
}
|
|
59223
60037
|
function extractTSSymbols(filePath, cwd) {
|
|
59224
|
-
const fullPath =
|
|
60038
|
+
const fullPath = path51.join(cwd, filePath);
|
|
59225
60039
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
59226
60040
|
return [];
|
|
59227
60041
|
}
|
|
59228
60042
|
let content;
|
|
59229
60043
|
try {
|
|
59230
|
-
const stats =
|
|
60044
|
+
const stats = fs40.statSync(fullPath);
|
|
59231
60045
|
if (stats.size > MAX_FILE_SIZE_BYTES2) {
|
|
59232
60046
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
|
|
59233
60047
|
}
|
|
59234
|
-
content =
|
|
60048
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
59235
60049
|
} catch {
|
|
59236
60050
|
return [];
|
|
59237
60051
|
}
|
|
@@ -59373,17 +60187,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
59373
60187
|
});
|
|
59374
60188
|
}
|
|
59375
60189
|
function extractPythonSymbols(filePath, cwd) {
|
|
59376
|
-
const fullPath =
|
|
60190
|
+
const fullPath = path51.join(cwd, filePath);
|
|
59377
60191
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
59378
60192
|
return [];
|
|
59379
60193
|
}
|
|
59380
60194
|
let content;
|
|
59381
60195
|
try {
|
|
59382
|
-
const stats =
|
|
60196
|
+
const stats = fs40.statSync(fullPath);
|
|
59383
60197
|
if (stats.size > MAX_FILE_SIZE_BYTES2) {
|
|
59384
60198
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
|
|
59385
60199
|
}
|
|
59386
|
-
content =
|
|
60200
|
+
content = fs40.readFileSync(fullPath, "utf-8");
|
|
59387
60201
|
} catch {
|
|
59388
60202
|
return [];
|
|
59389
60203
|
}
|
|
@@ -59456,7 +60270,7 @@ var symbols = createSwarmTool({
|
|
|
59456
60270
|
}, null, 2);
|
|
59457
60271
|
}
|
|
59458
60272
|
const cwd = directory;
|
|
59459
|
-
const ext =
|
|
60273
|
+
const ext = path51.extname(file3);
|
|
59460
60274
|
if (containsControlChars(file3)) {
|
|
59461
60275
|
return JSON.stringify({
|
|
59462
60276
|
file: file3,
|
|
@@ -59532,14 +60346,14 @@ function containsWindowsAttacks2(str) {
|
|
|
59532
60346
|
}
|
|
59533
60347
|
function isPathInWorkspace2(filePath, workspace) {
|
|
59534
60348
|
try {
|
|
59535
|
-
const resolvedPath =
|
|
59536
|
-
if (!
|
|
60349
|
+
const resolvedPath = path52.resolve(workspace, filePath);
|
|
60350
|
+
if (!fs41.existsSync(resolvedPath)) {
|
|
59537
60351
|
return true;
|
|
59538
60352
|
}
|
|
59539
|
-
const realWorkspace =
|
|
59540
|
-
const realResolvedPath =
|
|
59541
|
-
const relativePath =
|
|
59542
|
-
if (relativePath.startsWith("..") ||
|
|
60353
|
+
const realWorkspace = fs41.realpathSync(workspace);
|
|
60354
|
+
const realResolvedPath = fs41.realpathSync(resolvedPath);
|
|
60355
|
+
const relativePath = path52.relative(realWorkspace, realResolvedPath);
|
|
60356
|
+
if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
|
|
59543
60357
|
return false;
|
|
59544
60358
|
}
|
|
59545
60359
|
return true;
|
|
@@ -59548,7 +60362,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
59548
60362
|
}
|
|
59549
60363
|
}
|
|
59550
60364
|
function processFile(file3, cwd, exportedOnly) {
|
|
59551
|
-
const ext =
|
|
60365
|
+
const ext = path52.extname(file3);
|
|
59552
60366
|
if (containsControlChars(file3)) {
|
|
59553
60367
|
return {
|
|
59554
60368
|
file: file3,
|
|
@@ -59581,8 +60395,8 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
59581
60395
|
errorType: "path-outside-workspace"
|
|
59582
60396
|
};
|
|
59583
60397
|
}
|
|
59584
|
-
const fullPath =
|
|
59585
|
-
if (!
|
|
60398
|
+
const fullPath = path52.join(cwd, file3);
|
|
60399
|
+
if (!fs41.existsSync(fullPath)) {
|
|
59586
60400
|
return {
|
|
59587
60401
|
file: file3,
|
|
59588
60402
|
success: false,
|
|
@@ -59613,14 +60427,14 @@ function processFile(file3, cwd, exportedOnly) {
|
|
|
59613
60427
|
}
|
|
59614
60428
|
let isEmptyFile = false;
|
|
59615
60429
|
try {
|
|
59616
|
-
const stats =
|
|
60430
|
+
const stats = fs41.statSync(fullPath);
|
|
59617
60431
|
if (stats.size === 0) {
|
|
59618
60432
|
isEmptyFile = true;
|
|
59619
60433
|
}
|
|
59620
60434
|
} catch {}
|
|
59621
60435
|
if (syms.length === 0) {
|
|
59622
60436
|
try {
|
|
59623
|
-
const content =
|
|
60437
|
+
const content = fs41.readFileSync(fullPath, "utf-8");
|
|
59624
60438
|
if (content.trim().length === 0) {
|
|
59625
60439
|
isEmptyFile = true;
|
|
59626
60440
|
}
|
|
@@ -59871,8 +60685,8 @@ init_dist();
|
|
|
59871
60685
|
init_manager();
|
|
59872
60686
|
init_create_tool();
|
|
59873
60687
|
init_resolve_working_directory();
|
|
59874
|
-
import * as
|
|
59875
|
-
import * as
|
|
60688
|
+
import * as fs42 from "fs";
|
|
60689
|
+
import * as path53 from "path";
|
|
59876
60690
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
59877
60691
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
59878
60692
|
function isValidTaskId3(taskId) {
|
|
@@ -59889,18 +60703,18 @@ function isValidTaskId3(taskId) {
|
|
|
59889
60703
|
return TASK_ID_PATTERN2.test(taskId);
|
|
59890
60704
|
}
|
|
59891
60705
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
59892
|
-
const normalizedWorkspace =
|
|
59893
|
-
const swarmPath =
|
|
59894
|
-
const normalizedPath =
|
|
60706
|
+
const normalizedWorkspace = path53.resolve(workspaceRoot);
|
|
60707
|
+
const swarmPath = path53.join(normalizedWorkspace, ".swarm", "evidence");
|
|
60708
|
+
const normalizedPath = path53.resolve(filePath);
|
|
59895
60709
|
return normalizedPath.startsWith(swarmPath);
|
|
59896
60710
|
}
|
|
59897
60711
|
function readEvidenceFile(evidencePath) {
|
|
59898
|
-
if (!
|
|
60712
|
+
if (!fs42.existsSync(evidencePath)) {
|
|
59899
60713
|
return null;
|
|
59900
60714
|
}
|
|
59901
60715
|
let content;
|
|
59902
60716
|
try {
|
|
59903
|
-
content =
|
|
60717
|
+
content = fs42.readFileSync(evidencePath, "utf-8");
|
|
59904
60718
|
} catch {
|
|
59905
60719
|
return null;
|
|
59906
60720
|
}
|
|
@@ -59972,7 +60786,7 @@ var check_gate_status = createSwarmTool({
|
|
|
59972
60786
|
};
|
|
59973
60787
|
return JSON.stringify(errorResult, null, 2);
|
|
59974
60788
|
}
|
|
59975
|
-
const evidencePath =
|
|
60789
|
+
const evidencePath = path53.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
59976
60790
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
59977
60791
|
const errorResult = {
|
|
59978
60792
|
taskId: taskIdInput,
|
|
@@ -60065,10 +60879,11 @@ init_co_change_analyzer();
|
|
|
60065
60879
|
// src/tools/completion-verify.ts
|
|
60066
60880
|
init_dist();
|
|
60067
60881
|
init_utils2();
|
|
60068
|
-
|
|
60069
|
-
import * as path53 from "path";
|
|
60882
|
+
init_state();
|
|
60070
60883
|
init_create_tool();
|
|
60071
60884
|
init_resolve_working_directory();
|
|
60885
|
+
import * as fs43 from "fs";
|
|
60886
|
+
import * as path54 from "path";
|
|
60072
60887
|
function extractMatches(regex, text) {
|
|
60073
60888
|
return Array.from(text.matchAll(regex));
|
|
60074
60889
|
}
|
|
@@ -60162,7 +60977,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60162
60977
|
let plan;
|
|
60163
60978
|
try {
|
|
60164
60979
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
60165
|
-
const planRaw =
|
|
60980
|
+
const planRaw = fs43.readFileSync(planPath, "utf-8");
|
|
60166
60981
|
plan = JSON.parse(planRaw);
|
|
60167
60982
|
} catch {
|
|
60168
60983
|
const result2 = {
|
|
@@ -60220,10 +61035,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60220
61035
|
let hasFileReadFailure = false;
|
|
60221
61036
|
for (const filePath of fileTargets) {
|
|
60222
61037
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
60223
|
-
const resolvedPath =
|
|
60224
|
-
const projectRoot =
|
|
60225
|
-
const relative9 =
|
|
60226
|
-
const withinProject = relative9 === "" || !relative9.startsWith("..") && !
|
|
61038
|
+
const resolvedPath = path54.resolve(directory, normalizedPath);
|
|
61039
|
+
const projectRoot = path54.resolve(directory);
|
|
61040
|
+
const relative9 = path54.relative(projectRoot, resolvedPath);
|
|
61041
|
+
const withinProject = relative9 === "" || !relative9.startsWith("..") && !path54.isAbsolute(relative9);
|
|
60227
61042
|
if (!withinProject) {
|
|
60228
61043
|
blockedTasks.push({
|
|
60229
61044
|
task_id: task.id,
|
|
@@ -60236,7 +61051,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60236
61051
|
}
|
|
60237
61052
|
let fileContent;
|
|
60238
61053
|
try {
|
|
60239
|
-
fileContent =
|
|
61054
|
+
fileContent = fs43.readFileSync(resolvedPath, "utf-8");
|
|
60240
61055
|
} catch {
|
|
60241
61056
|
blockedTasks.push({
|
|
60242
61057
|
task_id: task.id,
|
|
@@ -60278,9 +61093,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60278
61093
|
blockedTasks
|
|
60279
61094
|
};
|
|
60280
61095
|
try {
|
|
60281
|
-
const evidenceDir =
|
|
60282
|
-
const evidencePath =
|
|
60283
|
-
|
|
61096
|
+
const evidenceDir = path54.join(directory, ".swarm", "evidence", `${phase}`);
|
|
61097
|
+
const evidencePath = path54.join(evidenceDir, "completion-verify.json");
|
|
61098
|
+
fs43.mkdirSync(evidenceDir, { recursive: true });
|
|
60284
61099
|
const evidenceBundle = {
|
|
60285
61100
|
schema_version: "1.0.0",
|
|
60286
61101
|
task_id: "completion-verify",
|
|
@@ -60301,7 +61116,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
60301
61116
|
}
|
|
60302
61117
|
]
|
|
60303
61118
|
};
|
|
60304
|
-
|
|
61119
|
+
fs43.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
60305
61120
|
} catch {}
|
|
60306
61121
|
return JSON.stringify(result, null, 2);
|
|
60307
61122
|
}
|
|
@@ -60355,12 +61170,12 @@ var completion_verify = createSwarmTool({
|
|
|
60355
61170
|
});
|
|
60356
61171
|
// src/tools/complexity-hotspots.ts
|
|
60357
61172
|
init_dist();
|
|
60358
|
-
import * as
|
|
60359
|
-
import * as
|
|
61173
|
+
import * as fs45 from "fs";
|
|
61174
|
+
import * as path56 from "path";
|
|
60360
61175
|
|
|
60361
61176
|
// src/quality/metrics.ts
|
|
60362
|
-
import * as
|
|
60363
|
-
import * as
|
|
61177
|
+
import * as fs44 from "fs";
|
|
61178
|
+
import * as path55 from "path";
|
|
60364
61179
|
var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
|
|
60365
61180
|
var MIN_DUPLICATION_LINES = 10;
|
|
60366
61181
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -60398,11 +61213,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
60398
61213
|
}
|
|
60399
61214
|
function getComplexityForFile(filePath) {
|
|
60400
61215
|
try {
|
|
60401
|
-
const stat2 =
|
|
61216
|
+
const stat2 = fs44.statSync(filePath);
|
|
60402
61217
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
60403
61218
|
return null;
|
|
60404
61219
|
}
|
|
60405
|
-
const content =
|
|
61220
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
60406
61221
|
return estimateCyclomaticComplexity(content);
|
|
60407
61222
|
} catch {
|
|
60408
61223
|
return null;
|
|
@@ -60412,8 +61227,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
60412
61227
|
let totalComplexity = 0;
|
|
60413
61228
|
const analyzedFiles = [];
|
|
60414
61229
|
for (const file3 of files) {
|
|
60415
|
-
const fullPath =
|
|
60416
|
-
if (!
|
|
61230
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61231
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60417
61232
|
continue;
|
|
60418
61233
|
}
|
|
60419
61234
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -60534,8 +61349,8 @@ function countGoExports(content) {
|
|
|
60534
61349
|
}
|
|
60535
61350
|
function getExportCountForFile(filePath) {
|
|
60536
61351
|
try {
|
|
60537
|
-
const content =
|
|
60538
|
-
const ext =
|
|
61352
|
+
const content = fs44.readFileSync(filePath, "utf-8");
|
|
61353
|
+
const ext = path55.extname(filePath).toLowerCase();
|
|
60539
61354
|
switch (ext) {
|
|
60540
61355
|
case ".ts":
|
|
60541
61356
|
case ".tsx":
|
|
@@ -60561,8 +61376,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
60561
61376
|
let totalExports = 0;
|
|
60562
61377
|
const analyzedFiles = [];
|
|
60563
61378
|
for (const file3 of files) {
|
|
60564
|
-
const fullPath =
|
|
60565
|
-
if (!
|
|
61379
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61380
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60566
61381
|
continue;
|
|
60567
61382
|
}
|
|
60568
61383
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -60595,16 +61410,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
60595
61410
|
let duplicateLines = 0;
|
|
60596
61411
|
const analyzedFiles = [];
|
|
60597
61412
|
for (const file3 of files) {
|
|
60598
|
-
const fullPath =
|
|
60599
|
-
if (!
|
|
61413
|
+
const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
|
|
61414
|
+
if (!fs44.existsSync(fullPath)) {
|
|
60600
61415
|
continue;
|
|
60601
61416
|
}
|
|
60602
61417
|
try {
|
|
60603
|
-
const stat2 =
|
|
61418
|
+
const stat2 = fs44.statSync(fullPath);
|
|
60604
61419
|
if (stat2.size > MAX_FILE_SIZE_BYTES3) {
|
|
60605
61420
|
continue;
|
|
60606
61421
|
}
|
|
60607
|
-
const content =
|
|
61422
|
+
const content = fs44.readFileSync(fullPath, "utf-8");
|
|
60608
61423
|
const lines = content.split(`
|
|
60609
61424
|
`).filter((line) => line.trim().length > 0);
|
|
60610
61425
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -60628,8 +61443,8 @@ function countCodeLines(content) {
|
|
|
60628
61443
|
return lines.length;
|
|
60629
61444
|
}
|
|
60630
61445
|
function isTestFile(filePath) {
|
|
60631
|
-
const basename8 =
|
|
60632
|
-
const _ext =
|
|
61446
|
+
const basename8 = path55.basename(filePath);
|
|
61447
|
+
const _ext = path55.extname(filePath).toLowerCase();
|
|
60633
61448
|
const testPatterns = [
|
|
60634
61449
|
".test.",
|
|
60635
61450
|
".spec.",
|
|
@@ -60710,8 +61525,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
60710
61525
|
}
|
|
60711
61526
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
60712
61527
|
}
|
|
60713
|
-
function matchesGlobSegment(
|
|
60714
|
-
const normalizedPath =
|
|
61528
|
+
function matchesGlobSegment(path56, glob) {
|
|
61529
|
+
const normalizedPath = path56.replace(/\\/g, "/");
|
|
60715
61530
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
60716
61531
|
if (normalizedPath.includes("//")) {
|
|
60717
61532
|
return false;
|
|
@@ -60742,8 +61557,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
60742
61557
|
function hasGlobstar(glob) {
|
|
60743
61558
|
return glob.includes("**");
|
|
60744
61559
|
}
|
|
60745
|
-
function globMatches(
|
|
60746
|
-
const normalizedPath =
|
|
61560
|
+
function globMatches(path56, glob) {
|
|
61561
|
+
const normalizedPath = path56.replace(/\\/g, "/");
|
|
60747
61562
|
if (!glob || glob === "") {
|
|
60748
61563
|
if (normalizedPath.includes("//")) {
|
|
60749
61564
|
return false;
|
|
@@ -60779,31 +61594,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
60779
61594
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
60780
61595
|
let testLines = 0;
|
|
60781
61596
|
let codeLines = 0;
|
|
60782
|
-
const srcDir =
|
|
60783
|
-
if (
|
|
61597
|
+
const srcDir = path55.join(workingDir, "src");
|
|
61598
|
+
if (fs44.existsSync(srcDir)) {
|
|
60784
61599
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60785
61600
|
codeLines += lines;
|
|
60786
61601
|
});
|
|
60787
61602
|
}
|
|
60788
61603
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
60789
61604
|
for (const dir of possibleSrcDirs) {
|
|
60790
|
-
const dirPath =
|
|
60791
|
-
if (
|
|
61605
|
+
const dirPath = path55.join(workingDir, dir);
|
|
61606
|
+
if (fs44.existsSync(dirPath)) {
|
|
60792
61607
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
60793
61608
|
codeLines += lines;
|
|
60794
61609
|
});
|
|
60795
61610
|
}
|
|
60796
61611
|
}
|
|
60797
|
-
const testsDir =
|
|
60798
|
-
if (
|
|
61612
|
+
const testsDir = path55.join(workingDir, "tests");
|
|
61613
|
+
if (fs44.existsSync(testsDir)) {
|
|
60799
61614
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60800
61615
|
testLines += lines;
|
|
60801
61616
|
});
|
|
60802
61617
|
}
|
|
60803
61618
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
60804
61619
|
for (const dir of possibleTestDirs) {
|
|
60805
|
-
const dirPath =
|
|
60806
|
-
if (
|
|
61620
|
+
const dirPath = path55.join(workingDir, dir);
|
|
61621
|
+
if (fs44.existsSync(dirPath) && dirPath !== testsDir) {
|
|
60807
61622
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
60808
61623
|
testLines += lines;
|
|
60809
61624
|
});
|
|
@@ -60815,9 +61630,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
60815
61630
|
}
|
|
60816
61631
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
60817
61632
|
try {
|
|
60818
|
-
const entries =
|
|
61633
|
+
const entries = fs44.readdirSync(dirPath, { withFileTypes: true });
|
|
60819
61634
|
for (const entry of entries) {
|
|
60820
|
-
const fullPath =
|
|
61635
|
+
const fullPath = path55.join(dirPath, entry.name);
|
|
60821
61636
|
if (entry.isDirectory()) {
|
|
60822
61637
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
60823
61638
|
continue;
|
|
@@ -60825,7 +61640,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60825
61640
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
60826
61641
|
} else if (entry.isFile()) {
|
|
60827
61642
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
60828
|
-
const ext =
|
|
61643
|
+
const ext = path55.extname(entry.name).toLowerCase();
|
|
60829
61644
|
const validExts = [
|
|
60830
61645
|
".ts",
|
|
60831
61646
|
".tsx",
|
|
@@ -60861,7 +61676,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
60861
61676
|
continue;
|
|
60862
61677
|
}
|
|
60863
61678
|
try {
|
|
60864
|
-
const content =
|
|
61679
|
+
const content = fs44.readFileSync(fullPath, "utf-8");
|
|
60865
61680
|
const lines = countCodeLines(content);
|
|
60866
61681
|
callback(lines);
|
|
60867
61682
|
} catch {}
|
|
@@ -61062,11 +61877,11 @@ async function getGitChurn(days, directory) {
|
|
|
61062
61877
|
}
|
|
61063
61878
|
function getComplexityForFile2(filePath) {
|
|
61064
61879
|
try {
|
|
61065
|
-
const stat2 =
|
|
61880
|
+
const stat2 = fs45.statSync(filePath);
|
|
61066
61881
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
61067
61882
|
return null;
|
|
61068
61883
|
}
|
|
61069
|
-
const content =
|
|
61884
|
+
const content = fs45.readFileSync(filePath, "utf-8");
|
|
61070
61885
|
return estimateCyclomaticComplexity(content);
|
|
61071
61886
|
} catch {
|
|
61072
61887
|
return null;
|
|
@@ -61077,7 +61892,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
61077
61892
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
61078
61893
|
const filteredChurn = new Map;
|
|
61079
61894
|
for (const [file3, count] of churnMap) {
|
|
61080
|
-
const ext =
|
|
61895
|
+
const ext = path56.extname(file3).toLowerCase();
|
|
61081
61896
|
if (extSet.has(ext)) {
|
|
61082
61897
|
filteredChurn.set(file3, count);
|
|
61083
61898
|
}
|
|
@@ -61087,8 +61902,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
61087
61902
|
let analyzedFiles = 0;
|
|
61088
61903
|
for (const [file3, churnCount] of filteredChurn) {
|
|
61089
61904
|
let fullPath = file3;
|
|
61090
|
-
if (!
|
|
61091
|
-
fullPath =
|
|
61905
|
+
if (!fs45.existsSync(fullPath)) {
|
|
61906
|
+
fullPath = path56.join(cwd, file3);
|
|
61092
61907
|
}
|
|
61093
61908
|
const complexity = getComplexityForFile2(fullPath);
|
|
61094
61909
|
if (complexity !== null) {
|
|
@@ -61352,9 +62167,10 @@ var curator_analyze = createSwarmTool({
|
|
|
61352
62167
|
});
|
|
61353
62168
|
// src/tools/declare-scope.ts
|
|
61354
62169
|
init_tool();
|
|
61355
|
-
|
|
61356
|
-
import * as path56 from "path";
|
|
62170
|
+
init_state();
|
|
61357
62171
|
init_create_tool();
|
|
62172
|
+
import * as fs46 from "fs";
|
|
62173
|
+
import * as path57 from "path";
|
|
61358
62174
|
function validateTaskIdFormat(taskId) {
|
|
61359
62175
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
61360
62176
|
if (!taskIdPattern.test(taskId)) {
|
|
@@ -61432,8 +62248,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61432
62248
|
};
|
|
61433
62249
|
}
|
|
61434
62250
|
}
|
|
61435
|
-
normalizedDir =
|
|
61436
|
-
const pathParts = normalizedDir.split(
|
|
62251
|
+
normalizedDir = path57.normalize(args2.working_directory);
|
|
62252
|
+
const pathParts = normalizedDir.split(path57.sep);
|
|
61437
62253
|
if (pathParts.includes("..")) {
|
|
61438
62254
|
return {
|
|
61439
62255
|
success: false,
|
|
@@ -61443,11 +62259,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61443
62259
|
]
|
|
61444
62260
|
};
|
|
61445
62261
|
}
|
|
61446
|
-
const resolvedDir =
|
|
62262
|
+
const resolvedDir = path57.resolve(normalizedDir);
|
|
61447
62263
|
try {
|
|
61448
|
-
const realPath =
|
|
61449
|
-
const planPath2 =
|
|
61450
|
-
if (!
|
|
62264
|
+
const realPath = fs46.realpathSync(resolvedDir);
|
|
62265
|
+
const planPath2 = path57.join(realPath, ".swarm", "plan.json");
|
|
62266
|
+
if (!fs46.existsSync(planPath2)) {
|
|
61451
62267
|
return {
|
|
61452
62268
|
success: false,
|
|
61453
62269
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -61470,8 +62286,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61470
62286
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
61471
62287
|
}
|
|
61472
62288
|
const directory = normalizedDir || fallbackDir;
|
|
61473
|
-
const planPath =
|
|
61474
|
-
if (!
|
|
62289
|
+
const planPath = path57.resolve(directory, ".swarm", "plan.json");
|
|
62290
|
+
if (!fs46.existsSync(planPath)) {
|
|
61475
62291
|
return {
|
|
61476
62292
|
success: false,
|
|
61477
62293
|
message: "No plan found",
|
|
@@ -61480,7 +62296,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61480
62296
|
}
|
|
61481
62297
|
let planContent;
|
|
61482
62298
|
try {
|
|
61483
|
-
planContent = JSON.parse(
|
|
62299
|
+
planContent = JSON.parse(fs46.readFileSync(planPath, "utf-8"));
|
|
61484
62300
|
} catch {
|
|
61485
62301
|
return {
|
|
61486
62302
|
success: false,
|
|
@@ -61512,8 +62328,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
61512
62328
|
const normalizeErrors = [];
|
|
61513
62329
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
61514
62330
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
61515
|
-
if (
|
|
61516
|
-
const relativePath =
|
|
62331
|
+
if (path57.isAbsolute(file3)) {
|
|
62332
|
+
const relativePath = path57.relative(dir, file3).replace(/\\/g, "/");
|
|
61517
62333
|
if (relativePath.startsWith("..")) {
|
|
61518
62334
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
61519
62335
|
return file3;
|
|
@@ -61852,20 +62668,20 @@ function validateBase(base) {
|
|
|
61852
62668
|
function validatePaths(paths) {
|
|
61853
62669
|
if (!paths)
|
|
61854
62670
|
return null;
|
|
61855
|
-
for (const
|
|
61856
|
-
if (!
|
|
62671
|
+
for (const path59 of paths) {
|
|
62672
|
+
if (!path59 || path59.length === 0) {
|
|
61857
62673
|
return "empty path not allowed";
|
|
61858
62674
|
}
|
|
61859
|
-
if (
|
|
62675
|
+
if (path59.length > MAX_PATH_LENGTH) {
|
|
61860
62676
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
61861
62677
|
}
|
|
61862
|
-
if (SHELL_METACHARACTERS2.test(
|
|
62678
|
+
if (SHELL_METACHARACTERS2.test(path59)) {
|
|
61863
62679
|
return "path contains shell metacharacters";
|
|
61864
62680
|
}
|
|
61865
|
-
if (
|
|
62681
|
+
if (path59.startsWith("-")) {
|
|
61866
62682
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
61867
62683
|
}
|
|
61868
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
62684
|
+
if (CONTROL_CHAR_PATTERN2.test(path59)) {
|
|
61869
62685
|
return "path contains control characters";
|
|
61870
62686
|
}
|
|
61871
62687
|
}
|
|
@@ -61946,8 +62762,8 @@ var diff = createSwarmTool({
|
|
|
61946
62762
|
if (parts2.length >= 3) {
|
|
61947
62763
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
61948
62764
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
61949
|
-
const
|
|
61950
|
-
files.push({ path:
|
|
62765
|
+
const path59 = parts2[2];
|
|
62766
|
+
files.push({ path: path59, additions, deletions });
|
|
61951
62767
|
}
|
|
61952
62768
|
}
|
|
61953
62769
|
const contractChanges = [];
|
|
@@ -62229,8 +63045,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
62229
63045
|
// src/tools/evidence-check.ts
|
|
62230
63046
|
init_dist();
|
|
62231
63047
|
init_create_tool();
|
|
62232
|
-
import * as
|
|
62233
|
-
import * as
|
|
63048
|
+
import * as fs47 from "fs";
|
|
63049
|
+
import * as path59 from "path";
|
|
62234
63050
|
var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
|
|
62235
63051
|
var MAX_EVIDENCE_FILES = 1000;
|
|
62236
63052
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -62257,9 +63073,9 @@ function validateRequiredTypes(input) {
|
|
|
62257
63073
|
return null;
|
|
62258
63074
|
}
|
|
62259
63075
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
62260
|
-
const normalizedCwd =
|
|
62261
|
-
const swarmPath =
|
|
62262
|
-
const normalizedPath =
|
|
63076
|
+
const normalizedCwd = path59.resolve(cwd);
|
|
63077
|
+
const swarmPath = path59.join(normalizedCwd, ".swarm");
|
|
63078
|
+
const normalizedPath = path59.resolve(filePath);
|
|
62263
63079
|
return normalizedPath.startsWith(swarmPath);
|
|
62264
63080
|
}
|
|
62265
63081
|
function parseCompletedTasks(planContent) {
|
|
@@ -62275,12 +63091,12 @@ function parseCompletedTasks(planContent) {
|
|
|
62275
63091
|
}
|
|
62276
63092
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
62277
63093
|
const evidence = [];
|
|
62278
|
-
if (!
|
|
63094
|
+
if (!fs47.existsSync(evidenceDir) || !fs47.statSync(evidenceDir).isDirectory()) {
|
|
62279
63095
|
return evidence;
|
|
62280
63096
|
}
|
|
62281
63097
|
let files;
|
|
62282
63098
|
try {
|
|
62283
|
-
files =
|
|
63099
|
+
files = fs47.readdirSync(evidenceDir);
|
|
62284
63100
|
} catch {
|
|
62285
63101
|
return evidence;
|
|
62286
63102
|
}
|
|
@@ -62289,14 +63105,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62289
63105
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
62290
63106
|
continue;
|
|
62291
63107
|
}
|
|
62292
|
-
const filePath =
|
|
63108
|
+
const filePath = path59.join(evidenceDir, filename);
|
|
62293
63109
|
try {
|
|
62294
|
-
const resolvedPath =
|
|
62295
|
-
const evidenceDirResolved =
|
|
63110
|
+
const resolvedPath = path59.resolve(filePath);
|
|
63111
|
+
const evidenceDirResolved = path59.resolve(evidenceDir);
|
|
62296
63112
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
62297
63113
|
continue;
|
|
62298
63114
|
}
|
|
62299
|
-
const stat2 =
|
|
63115
|
+
const stat2 = fs47.lstatSync(filePath);
|
|
62300
63116
|
if (!stat2.isFile()) {
|
|
62301
63117
|
continue;
|
|
62302
63118
|
}
|
|
@@ -62305,7 +63121,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62305
63121
|
}
|
|
62306
63122
|
let fileStat;
|
|
62307
63123
|
try {
|
|
62308
|
-
fileStat =
|
|
63124
|
+
fileStat = fs47.statSync(filePath);
|
|
62309
63125
|
if (fileStat.size > MAX_FILE_SIZE_BYTES5) {
|
|
62310
63126
|
continue;
|
|
62311
63127
|
}
|
|
@@ -62314,7 +63130,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
62314
63130
|
}
|
|
62315
63131
|
let content;
|
|
62316
63132
|
try {
|
|
62317
|
-
content =
|
|
63133
|
+
content = fs47.readFileSync(filePath, "utf-8");
|
|
62318
63134
|
} catch {
|
|
62319
63135
|
continue;
|
|
62320
63136
|
}
|
|
@@ -62410,7 +63226,7 @@ var evidence_check = createSwarmTool({
|
|
|
62410
63226
|
return JSON.stringify(errorResult, null, 2);
|
|
62411
63227
|
}
|
|
62412
63228
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
62413
|
-
const planPath =
|
|
63229
|
+
const planPath = path59.join(cwd, PLAN_FILE);
|
|
62414
63230
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
62415
63231
|
const errorResult = {
|
|
62416
63232
|
error: "plan file path validation failed",
|
|
@@ -62424,7 +63240,7 @@ var evidence_check = createSwarmTool({
|
|
|
62424
63240
|
}
|
|
62425
63241
|
let planContent;
|
|
62426
63242
|
try {
|
|
62427
|
-
planContent =
|
|
63243
|
+
planContent = fs47.readFileSync(planPath, "utf-8");
|
|
62428
63244
|
} catch {
|
|
62429
63245
|
const result2 = {
|
|
62430
63246
|
message: "No completed tasks found in plan.",
|
|
@@ -62442,7 +63258,7 @@ var evidence_check = createSwarmTool({
|
|
|
62442
63258
|
};
|
|
62443
63259
|
return JSON.stringify(result2, null, 2);
|
|
62444
63260
|
}
|
|
62445
|
-
const evidenceDir =
|
|
63261
|
+
const evidenceDir = path59.join(cwd, EVIDENCE_DIR2);
|
|
62446
63262
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
62447
63263
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
62448
63264
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -62459,8 +63275,8 @@ var evidence_check = createSwarmTool({
|
|
|
62459
63275
|
// src/tools/file-extractor.ts
|
|
62460
63276
|
init_tool();
|
|
62461
63277
|
init_create_tool();
|
|
62462
|
-
import * as
|
|
62463
|
-
import * as
|
|
63278
|
+
import * as fs48 from "fs";
|
|
63279
|
+
import * as path60 from "path";
|
|
62464
63280
|
var EXT_MAP = {
|
|
62465
63281
|
python: ".py",
|
|
62466
63282
|
py: ".py",
|
|
@@ -62522,8 +63338,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
62522
63338
|
execute: async (args2, directory) => {
|
|
62523
63339
|
const { content, output_dir, prefix } = args2;
|
|
62524
63340
|
const targetDir = output_dir || directory;
|
|
62525
|
-
if (!
|
|
62526
|
-
|
|
63341
|
+
if (!fs48.existsSync(targetDir)) {
|
|
63342
|
+
fs48.mkdirSync(targetDir, { recursive: true });
|
|
62527
63343
|
}
|
|
62528
63344
|
if (!content) {
|
|
62529
63345
|
return "Error: content is required";
|
|
@@ -62541,16 +63357,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
62541
63357
|
if (prefix) {
|
|
62542
63358
|
filename = `${prefix}_${filename}`;
|
|
62543
63359
|
}
|
|
62544
|
-
let filepath =
|
|
62545
|
-
const base =
|
|
62546
|
-
const ext =
|
|
63360
|
+
let filepath = path60.join(targetDir, filename);
|
|
63361
|
+
const base = path60.basename(filepath, path60.extname(filepath));
|
|
63362
|
+
const ext = path60.extname(filepath);
|
|
62547
63363
|
let counter = 1;
|
|
62548
|
-
while (
|
|
62549
|
-
filepath =
|
|
63364
|
+
while (fs48.existsSync(filepath)) {
|
|
63365
|
+
filepath = path60.join(targetDir, `${base}_${counter}${ext}`);
|
|
62550
63366
|
counter++;
|
|
62551
63367
|
}
|
|
62552
63368
|
try {
|
|
62553
|
-
|
|
63369
|
+
fs48.writeFileSync(filepath, code.trim(), "utf-8");
|
|
62554
63370
|
savedFiles.push(filepath);
|
|
62555
63371
|
} catch (error93) {
|
|
62556
63372
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -62580,7 +63396,7 @@ init_create_tool();
|
|
|
62580
63396
|
var GITINGEST_TIMEOUT_MS = 1e4;
|
|
62581
63397
|
var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
|
|
62582
63398
|
var GITINGEST_MAX_RETRIES = 2;
|
|
62583
|
-
var delay = (ms) => new Promise((
|
|
63399
|
+
var delay = (ms) => new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
62584
63400
|
async function fetchGitingest(args2) {
|
|
62585
63401
|
for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
|
|
62586
63402
|
try {
|
|
@@ -62666,8 +63482,8 @@ var gitingest = createSwarmTool({
|
|
|
62666
63482
|
// src/tools/imports.ts
|
|
62667
63483
|
init_dist();
|
|
62668
63484
|
init_create_tool();
|
|
62669
|
-
import * as
|
|
62670
|
-
import * as
|
|
63485
|
+
import * as fs49 from "fs";
|
|
63486
|
+
import * as path61 from "path";
|
|
62671
63487
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
62672
63488
|
var MAX_SYMBOL_LENGTH = 256;
|
|
62673
63489
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
@@ -62715,7 +63531,7 @@ function validateSymbolInput(symbol3) {
|
|
|
62715
63531
|
return null;
|
|
62716
63532
|
}
|
|
62717
63533
|
function isBinaryFile2(filePath, buffer) {
|
|
62718
|
-
const ext =
|
|
63534
|
+
const ext = path61.extname(filePath).toLowerCase();
|
|
62719
63535
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
62720
63536
|
return false;
|
|
62721
63537
|
}
|
|
@@ -62739,15 +63555,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62739
63555
|
const imports = [];
|
|
62740
63556
|
let _resolvedTarget;
|
|
62741
63557
|
try {
|
|
62742
|
-
_resolvedTarget =
|
|
63558
|
+
_resolvedTarget = path61.resolve(targetFile);
|
|
62743
63559
|
} catch {
|
|
62744
63560
|
_resolvedTarget = targetFile;
|
|
62745
63561
|
}
|
|
62746
|
-
const targetBasename =
|
|
63562
|
+
const targetBasename = path61.basename(targetFile, path61.extname(targetFile));
|
|
62747
63563
|
const targetWithExt = targetFile;
|
|
62748
63564
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
62749
|
-
const normalizedTargetWithExt =
|
|
62750
|
-
const normalizedTargetWithoutExt =
|
|
63565
|
+
const normalizedTargetWithExt = path61.normalize(targetWithExt).replace(/\\/g, "/");
|
|
63566
|
+
const normalizedTargetWithoutExt = path61.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
62751
63567
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
62752
63568
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
62753
63569
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -62770,9 +63586,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
62770
63586
|
}
|
|
62771
63587
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
62772
63588
|
let isMatch = false;
|
|
62773
|
-
const _targetDir =
|
|
62774
|
-
const targetExt =
|
|
62775
|
-
const targetBasenameNoExt =
|
|
63589
|
+
const _targetDir = path61.dirname(targetFile);
|
|
63590
|
+
const targetExt = path61.extname(targetFile);
|
|
63591
|
+
const targetBasenameNoExt = path61.basename(targetFile, targetExt);
|
|
62776
63592
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
62777
63593
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
62778
63594
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -62829,7 +63645,7 @@ var SKIP_DIRECTORIES3 = new Set([
|
|
|
62829
63645
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
62830
63646
|
let entries;
|
|
62831
63647
|
try {
|
|
62832
|
-
entries =
|
|
63648
|
+
entries = fs49.readdirSync(dir);
|
|
62833
63649
|
} catch (e) {
|
|
62834
63650
|
stats.fileErrors.push({
|
|
62835
63651
|
path: dir,
|
|
@@ -62840,13 +63656,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62840
63656
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
62841
63657
|
for (const entry of entries) {
|
|
62842
63658
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62843
|
-
stats.skippedDirs.push(
|
|
63659
|
+
stats.skippedDirs.push(path61.join(dir, entry));
|
|
62844
63660
|
continue;
|
|
62845
63661
|
}
|
|
62846
|
-
const fullPath =
|
|
63662
|
+
const fullPath = path61.join(dir, entry);
|
|
62847
63663
|
let stat2;
|
|
62848
63664
|
try {
|
|
62849
|
-
stat2 =
|
|
63665
|
+
stat2 = fs49.statSync(fullPath);
|
|
62850
63666
|
} catch (e) {
|
|
62851
63667
|
stats.fileErrors.push({
|
|
62852
63668
|
path: fullPath,
|
|
@@ -62857,7 +63673,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
62857
63673
|
if (stat2.isDirectory()) {
|
|
62858
63674
|
findSourceFiles(fullPath, files, stats);
|
|
62859
63675
|
} else if (stat2.isFile()) {
|
|
62860
|
-
const ext =
|
|
63676
|
+
const ext = path61.extname(fullPath).toLowerCase();
|
|
62861
63677
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
62862
63678
|
files.push(fullPath);
|
|
62863
63679
|
}
|
|
@@ -62914,8 +63730,8 @@ var imports = createSwarmTool({
|
|
|
62914
63730
|
return JSON.stringify(errorResult, null, 2);
|
|
62915
63731
|
}
|
|
62916
63732
|
try {
|
|
62917
|
-
const targetFile =
|
|
62918
|
-
if (!
|
|
63733
|
+
const targetFile = path61.resolve(file3);
|
|
63734
|
+
if (!fs49.existsSync(targetFile)) {
|
|
62919
63735
|
const errorResult = {
|
|
62920
63736
|
error: `target file not found: ${file3}`,
|
|
62921
63737
|
target: file3,
|
|
@@ -62925,7 +63741,7 @@ var imports = createSwarmTool({
|
|
|
62925
63741
|
};
|
|
62926
63742
|
return JSON.stringify(errorResult, null, 2);
|
|
62927
63743
|
}
|
|
62928
|
-
const targetStat =
|
|
63744
|
+
const targetStat = fs49.statSync(targetFile);
|
|
62929
63745
|
if (!targetStat.isFile()) {
|
|
62930
63746
|
const errorResult = {
|
|
62931
63747
|
error: "target must be a file, not a directory",
|
|
@@ -62936,7 +63752,7 @@ var imports = createSwarmTool({
|
|
|
62936
63752
|
};
|
|
62937
63753
|
return JSON.stringify(errorResult, null, 2);
|
|
62938
63754
|
}
|
|
62939
|
-
const baseDir =
|
|
63755
|
+
const baseDir = path61.dirname(targetFile);
|
|
62940
63756
|
const scanStats = {
|
|
62941
63757
|
skippedDirs: [],
|
|
62942
63758
|
skippedFiles: 0,
|
|
@@ -62951,12 +63767,12 @@ var imports = createSwarmTool({
|
|
|
62951
63767
|
if (consumers.length >= MAX_CONSUMERS)
|
|
62952
63768
|
break;
|
|
62953
63769
|
try {
|
|
62954
|
-
const stat2 =
|
|
63770
|
+
const stat2 = fs49.statSync(filePath);
|
|
62955
63771
|
if (stat2.size > MAX_FILE_SIZE_BYTES6) {
|
|
62956
63772
|
skippedFileCount++;
|
|
62957
63773
|
continue;
|
|
62958
63774
|
}
|
|
62959
|
-
const buffer =
|
|
63775
|
+
const buffer = fs49.readFileSync(filePath);
|
|
62960
63776
|
if (isBinaryFile2(filePath, buffer)) {
|
|
62961
63777
|
skippedFileCount++;
|
|
62962
63778
|
continue;
|
|
@@ -63156,7 +63972,7 @@ init_dist();
|
|
|
63156
63972
|
init_config();
|
|
63157
63973
|
init_knowledge_store();
|
|
63158
63974
|
init_create_tool();
|
|
63159
|
-
import { existsSync as
|
|
63975
|
+
import { existsSync as existsSync39 } from "fs";
|
|
63160
63976
|
var DEFAULT_LIMIT = 10;
|
|
63161
63977
|
var MAX_LESSON_LENGTH = 200;
|
|
63162
63978
|
var VALID_CATEGORIES3 = [
|
|
@@ -63225,14 +64041,14 @@ function validateLimit(limit) {
|
|
|
63225
64041
|
}
|
|
63226
64042
|
async function readSwarmKnowledge(directory) {
|
|
63227
64043
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
63228
|
-
if (!
|
|
64044
|
+
if (!existsSync39(swarmPath)) {
|
|
63229
64045
|
return [];
|
|
63230
64046
|
}
|
|
63231
64047
|
return readKnowledge(swarmPath);
|
|
63232
64048
|
}
|
|
63233
64049
|
async function readHiveKnowledge() {
|
|
63234
64050
|
const hivePath = resolveHiveKnowledgePath();
|
|
63235
|
-
if (!
|
|
64051
|
+
if (!existsSync39(hivePath)) {
|
|
63236
64052
|
return [];
|
|
63237
64053
|
}
|
|
63238
64054
|
return readKnowledge(hivePath);
|
|
@@ -63545,62 +64361,13 @@ init_dist();
|
|
|
63545
64361
|
init_config();
|
|
63546
64362
|
init_schema();
|
|
63547
64363
|
init_manager();
|
|
63548
|
-
import * as
|
|
64364
|
+
import * as fs50 from "fs";
|
|
63549
64365
|
import * as path62 from "path";
|
|
63550
64366
|
init_review_receipt();
|
|
63551
64367
|
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
64368
|
init_ledger();
|
|
63603
64369
|
init_manager2();
|
|
64370
|
+
init_state();
|
|
63604
64371
|
init_telemetry();
|
|
63605
64372
|
init_create_tool();
|
|
63606
64373
|
init_resolve_working_directory();
|
|
@@ -63824,7 +64591,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63824
64591
|
let driftVerdictFound = false;
|
|
63825
64592
|
let driftVerdictApproved = false;
|
|
63826
64593
|
try {
|
|
63827
|
-
const driftEvidenceContent =
|
|
64594
|
+
const driftEvidenceContent = fs50.readFileSync(driftEvidencePath, "utf-8");
|
|
63828
64595
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
63829
64596
|
const entries = driftEvidence.entries ?? [];
|
|
63830
64597
|
for (const entry of entries) {
|
|
@@ -63855,13 +64622,13 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63855
64622
|
}
|
|
63856
64623
|
if (!driftVerdictFound) {
|
|
63857
64624
|
const specPath = path62.join(dir, ".swarm", "spec.md");
|
|
63858
|
-
const specExists =
|
|
64625
|
+
const specExists = fs50.existsSync(specPath);
|
|
63859
64626
|
if (!specExists) {
|
|
63860
64627
|
let incompleteTaskCount = 0;
|
|
63861
64628
|
let planPhaseFound = false;
|
|
63862
64629
|
try {
|
|
63863
64630
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
63864
|
-
const planRaw =
|
|
64631
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
63865
64632
|
const plan = JSON.parse(planRaw);
|
|
63866
64633
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
63867
64634
|
if (targetPhase) {
|
|
@@ -63986,7 +64753,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
63986
64753
|
let phaseRequiredAgents;
|
|
63987
64754
|
try {
|
|
63988
64755
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
63989
|
-
const planRaw =
|
|
64756
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
63990
64757
|
const plan = JSON.parse(planRaw);
|
|
63991
64758
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
63992
64759
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -64001,7 +64768,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64001
64768
|
if (agentsMissing.length > 0) {
|
|
64002
64769
|
try {
|
|
64003
64770
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64004
|
-
const planRaw =
|
|
64771
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64005
64772
|
const plan = JSON.parse(planRaw);
|
|
64006
64773
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
64007
64774
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -64041,7 +64808,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64041
64808
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
64042
64809
|
try {
|
|
64043
64810
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64044
|
-
const planRaw =
|
|
64811
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64045
64812
|
const plan = JSON.parse(planRaw);
|
|
64046
64813
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
64047
64814
|
if (targetPhase) {
|
|
@@ -64095,7 +64862,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64095
64862
|
}
|
|
64096
64863
|
try {
|
|
64097
64864
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
64098
|
-
|
|
64865
|
+
fs50.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
64099
64866
|
`, "utf-8");
|
|
64100
64867
|
} catch (writeError) {
|
|
64101
64868
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -64116,6 +64883,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64116
64883
|
contributorSession.lastCompletedPhaseAgentsDispatched = new Set(contributorSession.phaseAgentsDispatched);
|
|
64117
64884
|
}
|
|
64118
64885
|
contributorSession.phaseAgentsDispatched = new Set;
|
|
64886
|
+
contributorSession.fullAutoInteractionCount = 0;
|
|
64887
|
+
contributorSession.fullAutoDeadlockCount = 0;
|
|
64888
|
+
contributorSession.fullAutoLastQuestionHash = null;
|
|
64119
64889
|
contributorSession.lastPhaseCompleteTimestamp = now;
|
|
64120
64890
|
const oldPhase = contributorSession.lastPhaseCompletePhase;
|
|
64121
64891
|
contributorSession.lastPhaseCompletePhase = phase;
|
|
@@ -64145,12 +64915,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64145
64915
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
64146
64916
|
try {
|
|
64147
64917
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64148
|
-
const planRaw =
|
|
64918
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64149
64919
|
const plan2 = JSON.parse(planRaw);
|
|
64150
64920
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
64151
64921
|
if (phaseObj) {
|
|
64152
64922
|
phaseObj.status = "complete";
|
|
64153
|
-
|
|
64923
|
+
fs50.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
64154
64924
|
}
|
|
64155
64925
|
} catch {}
|
|
64156
64926
|
} else if (plan) {
|
|
@@ -64187,12 +64957,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
64187
64957
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
64188
64958
|
try {
|
|
64189
64959
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
64190
|
-
const planRaw =
|
|
64960
|
+
const planRaw = fs50.readFileSync(planPath, "utf-8");
|
|
64191
64961
|
const plan = JSON.parse(planRaw);
|
|
64192
64962
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
64193
64963
|
if (phaseObj) {
|
|
64194
64964
|
phaseObj.status = "complete";
|
|
64195
|
-
|
|
64965
|
+
fs50.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
64196
64966
|
}
|
|
64197
64967
|
} catch {}
|
|
64198
64968
|
}
|
|
@@ -64249,7 +65019,7 @@ init_dist();
|
|
|
64249
65019
|
init_discovery();
|
|
64250
65020
|
init_utils();
|
|
64251
65021
|
init_create_tool();
|
|
64252
|
-
import * as
|
|
65022
|
+
import * as fs51 from "fs";
|
|
64253
65023
|
import * as path63 from "path";
|
|
64254
65024
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
64255
65025
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
@@ -64278,31 +65048,31 @@ function validateArgs3(args2) {
|
|
|
64278
65048
|
function detectEcosystems(directory) {
|
|
64279
65049
|
const ecosystems = [];
|
|
64280
65050
|
const cwd = directory;
|
|
64281
|
-
if (
|
|
65051
|
+
if (fs51.existsSync(path63.join(cwd, "package.json"))) {
|
|
64282
65052
|
ecosystems.push("npm");
|
|
64283
65053
|
}
|
|
64284
|
-
if (
|
|
65054
|
+
if (fs51.existsSync(path63.join(cwd, "pyproject.toml")) || fs51.existsSync(path63.join(cwd, "requirements.txt"))) {
|
|
64285
65055
|
ecosystems.push("pip");
|
|
64286
65056
|
}
|
|
64287
|
-
if (
|
|
65057
|
+
if (fs51.existsSync(path63.join(cwd, "Cargo.toml"))) {
|
|
64288
65058
|
ecosystems.push("cargo");
|
|
64289
65059
|
}
|
|
64290
|
-
if (
|
|
65060
|
+
if (fs51.existsSync(path63.join(cwd, "go.mod"))) {
|
|
64291
65061
|
ecosystems.push("go");
|
|
64292
65062
|
}
|
|
64293
65063
|
try {
|
|
64294
|
-
const files =
|
|
65064
|
+
const files = fs51.readdirSync(cwd);
|
|
64295
65065
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
64296
65066
|
ecosystems.push("dotnet");
|
|
64297
65067
|
}
|
|
64298
65068
|
} catch {}
|
|
64299
|
-
if (
|
|
65069
|
+
if (fs51.existsSync(path63.join(cwd, "Gemfile")) || fs51.existsSync(path63.join(cwd, "Gemfile.lock"))) {
|
|
64300
65070
|
ecosystems.push("ruby");
|
|
64301
65071
|
}
|
|
64302
|
-
if (
|
|
65072
|
+
if (fs51.existsSync(path63.join(cwd, "pubspec.yaml"))) {
|
|
64303
65073
|
ecosystems.push("dart");
|
|
64304
65074
|
}
|
|
64305
|
-
if (
|
|
65075
|
+
if (fs51.existsSync(path63.join(cwd, "composer.lock"))) {
|
|
64306
65076
|
ecosystems.push("composer");
|
|
64307
65077
|
}
|
|
64308
65078
|
return ecosystems;
|
|
@@ -65461,7 +66231,7 @@ var pkg_audit = createSwarmTool({
|
|
|
65461
66231
|
// src/tools/placeholder-scan.ts
|
|
65462
66232
|
init_dist();
|
|
65463
66233
|
init_manager();
|
|
65464
|
-
import * as
|
|
66234
|
+
import * as fs52 from "fs";
|
|
65465
66235
|
import * as path64 from "path";
|
|
65466
66236
|
init_utils();
|
|
65467
66237
|
init_create_tool();
|
|
@@ -65796,7 +66566,7 @@ async function placeholderScan(input, directory) {
|
|
|
65796
66566
|
if (!fullPath.startsWith(resolvedDirectory + path64.sep) && fullPath !== resolvedDirectory) {
|
|
65797
66567
|
continue;
|
|
65798
66568
|
}
|
|
65799
|
-
if (!
|
|
66569
|
+
if (!fs52.existsSync(fullPath)) {
|
|
65800
66570
|
continue;
|
|
65801
66571
|
}
|
|
65802
66572
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
@@ -65804,11 +66574,11 @@ async function placeholderScan(input, directory) {
|
|
|
65804
66574
|
}
|
|
65805
66575
|
let content;
|
|
65806
66576
|
try {
|
|
65807
|
-
const stat2 =
|
|
66577
|
+
const stat2 = fs52.statSync(fullPath);
|
|
65808
66578
|
if (stat2.size > MAX_FILE_SIZE) {
|
|
65809
66579
|
continue;
|
|
65810
66580
|
}
|
|
65811
|
-
content =
|
|
66581
|
+
content = fs52.readFileSync(fullPath, "utf-8");
|
|
65812
66582
|
} catch {
|
|
65813
66583
|
continue;
|
|
65814
66584
|
}
|
|
@@ -65870,7 +66640,7 @@ var placeholder_scan = createSwarmTool({
|
|
|
65870
66640
|
});
|
|
65871
66641
|
// src/tools/pre-check-batch.ts
|
|
65872
66642
|
init_dist();
|
|
65873
|
-
import * as
|
|
66643
|
+
import * as fs54 from "fs";
|
|
65874
66644
|
import * as path66 from "path";
|
|
65875
66645
|
|
|
65876
66646
|
// node_modules/yocto-queue/index.js
|
|
@@ -66164,7 +66934,7 @@ var quality_budget = createSwarmTool({
|
|
|
66164
66934
|
init_dist();
|
|
66165
66935
|
init_manager();
|
|
66166
66936
|
init_detector();
|
|
66167
|
-
import * as
|
|
66937
|
+
import * as fs53 from "fs";
|
|
66168
66938
|
import * as path65 from "path";
|
|
66169
66939
|
import { extname as extname14 } from "path";
|
|
66170
66940
|
|
|
@@ -67065,17 +67835,17 @@ var SEVERITY_ORDER = {
|
|
|
67065
67835
|
};
|
|
67066
67836
|
function shouldSkipFile(filePath) {
|
|
67067
67837
|
try {
|
|
67068
|
-
const stats =
|
|
67838
|
+
const stats = fs53.statSync(filePath);
|
|
67069
67839
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
67070
67840
|
return { skip: true, reason: "file too large" };
|
|
67071
67841
|
}
|
|
67072
67842
|
if (stats.size === 0) {
|
|
67073
67843
|
return { skip: true, reason: "empty file" };
|
|
67074
67844
|
}
|
|
67075
|
-
const fd =
|
|
67845
|
+
const fd = fs53.openSync(filePath, "r");
|
|
67076
67846
|
const buffer = Buffer.alloc(8192);
|
|
67077
|
-
const bytesRead =
|
|
67078
|
-
|
|
67847
|
+
const bytesRead = fs53.readSync(fd, buffer, 0, 8192, 0);
|
|
67848
|
+
fs53.closeSync(fd);
|
|
67079
67849
|
if (bytesRead > 0) {
|
|
67080
67850
|
let nullCount = 0;
|
|
67081
67851
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -67114,7 +67884,7 @@ function countBySeverity(findings) {
|
|
|
67114
67884
|
}
|
|
67115
67885
|
function scanFileWithTierA(filePath, language) {
|
|
67116
67886
|
try {
|
|
67117
|
-
const content =
|
|
67887
|
+
const content = fs53.readFileSync(filePath, "utf-8");
|
|
67118
67888
|
const findings = executeRulesSync(filePath, content, language);
|
|
67119
67889
|
return findings.map((f) => ({
|
|
67120
67890
|
rule_id: f.rule_id,
|
|
@@ -67167,7 +67937,7 @@ async function sastScan(input, directory, config3) {
|
|
|
67167
67937
|
_filesSkipped++;
|
|
67168
67938
|
continue;
|
|
67169
67939
|
}
|
|
67170
|
-
if (!
|
|
67940
|
+
if (!fs53.existsSync(resolvedPath)) {
|
|
67171
67941
|
_filesSkipped++;
|
|
67172
67942
|
continue;
|
|
67173
67943
|
}
|
|
@@ -67623,7 +68393,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
67623
68393
|
}
|
|
67624
68394
|
let stat2;
|
|
67625
68395
|
try {
|
|
67626
|
-
stat2 =
|
|
68396
|
+
stat2 = fs54.statSync(file3);
|
|
67627
68397
|
} catch {
|
|
67628
68398
|
skippedFiles++;
|
|
67629
68399
|
continue;
|
|
@@ -67634,7 +68404,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
67634
68404
|
}
|
|
67635
68405
|
let content;
|
|
67636
68406
|
try {
|
|
67637
|
-
const buffer =
|
|
68407
|
+
const buffer = fs54.readFileSync(file3);
|
|
67638
68408
|
if (buffer.includes(0)) {
|
|
67639
68409
|
skippedFiles++;
|
|
67640
68410
|
continue;
|
|
@@ -68167,10 +68937,11 @@ ${paginatedContent}`;
|
|
|
68167
68937
|
});
|
|
68168
68938
|
// src/tools/save-plan.ts
|
|
68169
68939
|
init_tool();
|
|
68170
|
-
import * as
|
|
68940
|
+
import * as fs55 from "fs";
|
|
68171
68941
|
import * as path67 from "path";
|
|
68172
68942
|
init_ledger();
|
|
68173
68943
|
init_manager2();
|
|
68944
|
+
init_state();
|
|
68174
68945
|
init_create_tool();
|
|
68175
68946
|
function detectPlaceholderContent(args2) {
|
|
68176
68947
|
const issues = [];
|
|
@@ -68312,7 +69083,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
68312
69083
|
phases_count: plan.phases.length,
|
|
68313
69084
|
tasks_count: tasksCount
|
|
68314
69085
|
});
|
|
68315
|
-
await
|
|
69086
|
+
await fs55.promises.writeFile(markerPath, marker, "utf8");
|
|
68316
69087
|
} catch {}
|
|
68317
69088
|
const warnings = [];
|
|
68318
69089
|
let criticReviewFound = false;
|
|
@@ -68372,7 +69143,7 @@ var save_plan = createSwarmTool({
|
|
|
68372
69143
|
// src/tools/sbom-generate.ts
|
|
68373
69144
|
init_dist();
|
|
68374
69145
|
init_manager();
|
|
68375
|
-
import * as
|
|
69146
|
+
import * as fs56 from "fs";
|
|
68376
69147
|
import * as path68 from "path";
|
|
68377
69148
|
|
|
68378
69149
|
// src/sbom/detectors/index.ts
|
|
@@ -69221,7 +69992,7 @@ function findManifestFiles(rootDir) {
|
|
|
69221
69992
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
69222
69993
|
function searchDir(dir) {
|
|
69223
69994
|
try {
|
|
69224
|
-
const entries =
|
|
69995
|
+
const entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
69225
69996
|
for (const entry of entries) {
|
|
69226
69997
|
const fullPath = path68.join(dir, entry.name);
|
|
69227
69998
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
@@ -69248,7 +70019,7 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
69248
70019
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
69249
70020
|
for (const dir of directories) {
|
|
69250
70021
|
try {
|
|
69251
|
-
const entries =
|
|
70022
|
+
const entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
69252
70023
|
for (const entry of entries) {
|
|
69253
70024
|
const fullPath = path68.join(dir, entry.name);
|
|
69254
70025
|
if (entry.isFile()) {
|
|
@@ -69285,7 +70056,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
69285
70056
|
}
|
|
69286
70057
|
function ensureOutputDir(outputDir) {
|
|
69287
70058
|
try {
|
|
69288
|
-
|
|
70059
|
+
fs56.mkdirSync(outputDir, { recursive: true });
|
|
69289
70060
|
} catch (error93) {
|
|
69290
70061
|
if (!error93 || error93.code !== "EEXIST") {
|
|
69291
70062
|
throw error93;
|
|
@@ -69379,10 +70150,10 @@ var sbom_generate = createSwarmTool({
|
|
|
69379
70150
|
for (const manifestFile of manifestFiles) {
|
|
69380
70151
|
try {
|
|
69381
70152
|
const fullPath = path68.isAbsolute(manifestFile) ? manifestFile : path68.join(workingDir, manifestFile);
|
|
69382
|
-
if (!
|
|
70153
|
+
if (!fs56.existsSync(fullPath)) {
|
|
69383
70154
|
continue;
|
|
69384
70155
|
}
|
|
69385
|
-
const content =
|
|
70156
|
+
const content = fs56.readFileSync(fullPath, "utf-8");
|
|
69386
70157
|
const components = detectComponents(manifestFile, content);
|
|
69387
70158
|
processedFiles.push(manifestFile);
|
|
69388
70159
|
if (components.length > 0) {
|
|
@@ -69396,7 +70167,7 @@ var sbom_generate = createSwarmTool({
|
|
|
69396
70167
|
const bomJson = serializeCycloneDX(bom);
|
|
69397
70168
|
const filename = generateSbomFilename();
|
|
69398
70169
|
const outputPath = path68.join(outputDir, filename);
|
|
69399
|
-
|
|
70170
|
+
fs56.writeFileSync(outputPath, bomJson, "utf-8");
|
|
69400
70171
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
69401
70172
|
try {
|
|
69402
70173
|
const timestamp = new Date().toISOString();
|
|
@@ -69438,7 +70209,7 @@ var sbom_generate = createSwarmTool({
|
|
|
69438
70209
|
// src/tools/schema-drift.ts
|
|
69439
70210
|
init_dist();
|
|
69440
70211
|
init_create_tool();
|
|
69441
|
-
import * as
|
|
70212
|
+
import * as fs57 from "fs";
|
|
69442
70213
|
import * as path69 from "path";
|
|
69443
70214
|
var SPEC_CANDIDATES = [
|
|
69444
70215
|
"openapi.json",
|
|
@@ -69480,19 +70251,19 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
69480
70251
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
69481
70252
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
69482
70253
|
}
|
|
69483
|
-
const stats =
|
|
70254
|
+
const stats = fs57.statSync(resolvedPath);
|
|
69484
70255
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
69485
70256
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
69486
70257
|
}
|
|
69487
|
-
if (!
|
|
70258
|
+
if (!fs57.existsSync(resolvedPath)) {
|
|
69488
70259
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
69489
70260
|
}
|
|
69490
70261
|
return resolvedPath;
|
|
69491
70262
|
}
|
|
69492
70263
|
for (const candidate of SPEC_CANDIDATES) {
|
|
69493
70264
|
const candidatePath = path69.resolve(cwd, candidate);
|
|
69494
|
-
if (
|
|
69495
|
-
const stats =
|
|
70265
|
+
if (fs57.existsSync(candidatePath)) {
|
|
70266
|
+
const stats = fs57.statSync(candidatePath);
|
|
69496
70267
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
69497
70268
|
return candidatePath;
|
|
69498
70269
|
}
|
|
@@ -69501,7 +70272,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
69501
70272
|
return null;
|
|
69502
70273
|
}
|
|
69503
70274
|
function parseSpec(specFile) {
|
|
69504
|
-
const content =
|
|
70275
|
+
const content = fs57.readFileSync(specFile, "utf-8");
|
|
69505
70276
|
const ext = path69.extname(specFile).toLowerCase();
|
|
69506
70277
|
if (ext === ".json") {
|
|
69507
70278
|
return parseJsonSpec(content);
|
|
@@ -69573,7 +70344,7 @@ function extractRoutes(cwd) {
|
|
|
69573
70344
|
function walkDir(dir) {
|
|
69574
70345
|
let entries;
|
|
69575
70346
|
try {
|
|
69576
|
-
entries =
|
|
70347
|
+
entries = fs57.readdirSync(dir, { withFileTypes: true });
|
|
69577
70348
|
} catch {
|
|
69578
70349
|
return;
|
|
69579
70350
|
}
|
|
@@ -69606,7 +70377,7 @@ function extractRoutes(cwd) {
|
|
|
69606
70377
|
}
|
|
69607
70378
|
function extractRoutesFromFile(filePath) {
|
|
69608
70379
|
const routes = [];
|
|
69609
|
-
const content =
|
|
70380
|
+
const content = fs57.readFileSync(filePath, "utf-8");
|
|
69610
70381
|
const lines = content.split(/\r?\n/);
|
|
69611
70382
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
69612
70383
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -69753,7 +70524,7 @@ var schema_drift = createSwarmTool({
|
|
|
69753
70524
|
// src/tools/search.ts
|
|
69754
70525
|
init_tool();
|
|
69755
70526
|
init_create_tool();
|
|
69756
|
-
import * as
|
|
70527
|
+
import * as fs58 from "fs";
|
|
69757
70528
|
import * as path70 from "path";
|
|
69758
70529
|
var DEFAULT_MAX_RESULTS = 100;
|
|
69759
70530
|
var DEFAULT_MAX_LINES = 200;
|
|
@@ -69791,8 +70562,8 @@ function containsWindowsAttacks3(str) {
|
|
|
69791
70562
|
function isPathInWorkspace3(filePath, workspace) {
|
|
69792
70563
|
try {
|
|
69793
70564
|
const resolvedPath = path70.resolve(workspace, filePath);
|
|
69794
|
-
const realWorkspace =
|
|
69795
|
-
const realResolvedPath =
|
|
70565
|
+
const realWorkspace = fs58.realpathSync(workspace);
|
|
70566
|
+
const realResolvedPath = fs58.realpathSync(resolvedPath);
|
|
69796
70567
|
const relativePath = path70.relative(realWorkspace, realResolvedPath);
|
|
69797
70568
|
if (relativePath.startsWith("..") || path70.isAbsolute(relativePath)) {
|
|
69798
70569
|
return false;
|
|
@@ -69812,7 +70583,7 @@ function findRgInEnvPath() {
|
|
|
69812
70583
|
continue;
|
|
69813
70584
|
const isWindows = process.platform === "win32";
|
|
69814
70585
|
const candidate = path70.join(dir, isWindows ? "rg.exe" : "rg");
|
|
69815
|
-
if (
|
|
70586
|
+
if (fs58.existsSync(candidate))
|
|
69816
70587
|
return candidate;
|
|
69817
70588
|
}
|
|
69818
70589
|
return null;
|
|
@@ -69939,7 +70710,7 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
69939
70710
|
return files;
|
|
69940
70711
|
}
|
|
69941
70712
|
try {
|
|
69942
|
-
const entries =
|
|
70713
|
+
const entries = fs58.readdirSync(dir, { withFileTypes: true });
|
|
69943
70714
|
for (const entry of entries) {
|
|
69944
70715
|
const fullPath = path70.join(dir, entry.name);
|
|
69945
70716
|
const relativePath = path70.relative(workspace, fullPath);
|
|
@@ -69989,7 +70760,7 @@ async function fallbackSearch(opts) {
|
|
|
69989
70760
|
}
|
|
69990
70761
|
let stats;
|
|
69991
70762
|
try {
|
|
69992
|
-
stats =
|
|
70763
|
+
stats = fs58.statSync(fullPath);
|
|
69993
70764
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
69994
70765
|
continue;
|
|
69995
70766
|
}
|
|
@@ -69998,7 +70769,7 @@ async function fallbackSearch(opts) {
|
|
|
69998
70769
|
}
|
|
69999
70770
|
let content;
|
|
70000
70771
|
try {
|
|
70001
|
-
content =
|
|
70772
|
+
content = fs58.readFileSync(fullPath, "utf-8");
|
|
70002
70773
|
} catch {
|
|
70003
70774
|
continue;
|
|
70004
70775
|
}
|
|
@@ -70110,7 +70881,7 @@ var search = createSwarmTool({
|
|
|
70110
70881
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
70111
70882
|
}, null, 2);
|
|
70112
70883
|
}
|
|
70113
|
-
if (!
|
|
70884
|
+
if (!fs58.existsSync(directory)) {
|
|
70114
70885
|
return JSON.stringify({
|
|
70115
70886
|
error: true,
|
|
70116
70887
|
type: "unknown",
|
|
@@ -70153,7 +70924,7 @@ init_secretscan();
|
|
|
70153
70924
|
// src/tools/suggest-patch.ts
|
|
70154
70925
|
init_tool();
|
|
70155
70926
|
init_create_tool();
|
|
70156
|
-
import * as
|
|
70927
|
+
import * as fs59 from "fs";
|
|
70157
70928
|
import * as path71 from "path";
|
|
70158
70929
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
70159
70930
|
function containsWindowsAttacks4(str) {
|
|
@@ -70169,11 +70940,11 @@ function containsWindowsAttacks4(str) {
|
|
|
70169
70940
|
function isPathInWorkspace4(filePath, workspace) {
|
|
70170
70941
|
try {
|
|
70171
70942
|
const resolvedPath = path71.resolve(workspace, filePath);
|
|
70172
|
-
if (!
|
|
70943
|
+
if (!fs59.existsSync(resolvedPath)) {
|
|
70173
70944
|
return true;
|
|
70174
70945
|
}
|
|
70175
|
-
const realWorkspace =
|
|
70176
|
-
const realResolvedPath =
|
|
70946
|
+
const realWorkspace = fs59.realpathSync(workspace);
|
|
70947
|
+
const realResolvedPath = fs59.realpathSync(resolvedPath);
|
|
70177
70948
|
const relativePath = path71.relative(realWorkspace, realResolvedPath);
|
|
70178
70949
|
if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
|
|
70179
70950
|
return false;
|
|
@@ -70347,7 +71118,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70347
71118
|
message: "changes cannot be empty"
|
|
70348
71119
|
}, null, 2);
|
|
70349
71120
|
}
|
|
70350
|
-
if (!
|
|
71121
|
+
if (!fs59.existsSync(directory)) {
|
|
70351
71122
|
return JSON.stringify({
|
|
70352
71123
|
success: false,
|
|
70353
71124
|
error: true,
|
|
@@ -70384,7 +71155,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70384
71155
|
continue;
|
|
70385
71156
|
}
|
|
70386
71157
|
const fullPath = path71.resolve(directory, change.file);
|
|
70387
|
-
if (!
|
|
71158
|
+
if (!fs59.existsSync(fullPath)) {
|
|
70388
71159
|
errors5.push({
|
|
70389
71160
|
success: false,
|
|
70390
71161
|
error: true,
|
|
@@ -70398,7 +71169,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70398
71169
|
}
|
|
70399
71170
|
let content;
|
|
70400
71171
|
try {
|
|
70401
|
-
content =
|
|
71172
|
+
content = fs59.readFileSync(fullPath, "utf-8");
|
|
70402
71173
|
} catch (err2) {
|
|
70403
71174
|
errors5.push({
|
|
70404
71175
|
success: false,
|
|
@@ -70478,7 +71249,7 @@ var suggestPatch = createSwarmTool({
|
|
|
70478
71249
|
init_dist();
|
|
70479
71250
|
init_manager();
|
|
70480
71251
|
init_detector();
|
|
70481
|
-
import * as
|
|
71252
|
+
import * as fs60 from "fs";
|
|
70482
71253
|
import * as path72 from "path";
|
|
70483
71254
|
init_create_tool();
|
|
70484
71255
|
var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
@@ -70575,7 +71346,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
70575
71346
|
}
|
|
70576
71347
|
let content;
|
|
70577
71348
|
try {
|
|
70578
|
-
content =
|
|
71349
|
+
content = fs60.readFileSync(fullPath, "utf8");
|
|
70579
71350
|
} catch {
|
|
70580
71351
|
result.skipped_reason = "file_read_error";
|
|
70581
71352
|
skippedCount++;
|
|
@@ -70655,7 +71426,7 @@ init_test_runner();
|
|
|
70655
71426
|
init_dist();
|
|
70656
71427
|
init_utils();
|
|
70657
71428
|
init_create_tool();
|
|
70658
|
-
import * as
|
|
71429
|
+
import * as fs61 from "fs";
|
|
70659
71430
|
import * as path73 from "path";
|
|
70660
71431
|
var MAX_TEXT_LENGTH = 200;
|
|
70661
71432
|
var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
|
|
@@ -70746,7 +71517,7 @@ function isSupportedExtension(filePath) {
|
|
|
70746
71517
|
function findSourceFiles2(dir, files = []) {
|
|
70747
71518
|
let entries;
|
|
70748
71519
|
try {
|
|
70749
|
-
entries =
|
|
71520
|
+
entries = fs61.readdirSync(dir);
|
|
70750
71521
|
} catch {
|
|
70751
71522
|
return files;
|
|
70752
71523
|
}
|
|
@@ -70758,7 +71529,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
70758
71529
|
const fullPath = path73.join(dir, entry);
|
|
70759
71530
|
let stat2;
|
|
70760
71531
|
try {
|
|
70761
|
-
stat2 =
|
|
71532
|
+
stat2 = fs61.statSync(fullPath);
|
|
70762
71533
|
} catch {
|
|
70763
71534
|
continue;
|
|
70764
71535
|
}
|
|
@@ -70851,7 +71622,7 @@ var todo_extract = createSwarmTool({
|
|
|
70851
71622
|
return JSON.stringify(errorResult, null, 2);
|
|
70852
71623
|
}
|
|
70853
71624
|
const scanPath = resolvedPath;
|
|
70854
|
-
if (!
|
|
71625
|
+
if (!fs61.existsSync(scanPath)) {
|
|
70855
71626
|
const errorResult = {
|
|
70856
71627
|
error: `path not found: ${pathsInput}`,
|
|
70857
71628
|
total: 0,
|
|
@@ -70861,7 +71632,7 @@ var todo_extract = createSwarmTool({
|
|
|
70861
71632
|
return JSON.stringify(errorResult, null, 2);
|
|
70862
71633
|
}
|
|
70863
71634
|
const filesToScan = [];
|
|
70864
|
-
const stat2 =
|
|
71635
|
+
const stat2 = fs61.statSync(scanPath);
|
|
70865
71636
|
if (stat2.isFile()) {
|
|
70866
71637
|
if (isSupportedExtension(scanPath)) {
|
|
70867
71638
|
filesToScan.push(scanPath);
|
|
@@ -70880,11 +71651,11 @@ var todo_extract = createSwarmTool({
|
|
|
70880
71651
|
const allEntries = [];
|
|
70881
71652
|
for (const filePath of filesToScan) {
|
|
70882
71653
|
try {
|
|
70883
|
-
const fileStat =
|
|
71654
|
+
const fileStat = fs61.statSync(filePath);
|
|
70884
71655
|
if (fileStat.size > MAX_FILE_SIZE_BYTES9) {
|
|
70885
71656
|
continue;
|
|
70886
71657
|
}
|
|
70887
|
-
const content =
|
|
71658
|
+
const content = fs61.readFileSync(filePath, "utf-8");
|
|
70888
71659
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
70889
71660
|
allEntries.push(...entries);
|
|
70890
71661
|
} catch {}
|
|
@@ -70913,18 +71684,18 @@ var todo_extract = createSwarmTool({
|
|
|
70913
71684
|
init_tool();
|
|
70914
71685
|
init_schema();
|
|
70915
71686
|
init_gate_evidence();
|
|
70916
|
-
import * as
|
|
71687
|
+
import * as fs63 from "fs";
|
|
70917
71688
|
import * as path75 from "path";
|
|
70918
71689
|
|
|
70919
71690
|
// src/hooks/diff-scope.ts
|
|
70920
|
-
import * as
|
|
71691
|
+
import * as fs62 from "fs";
|
|
70921
71692
|
import * as path74 from "path";
|
|
70922
71693
|
function getDeclaredScope(taskId, directory) {
|
|
70923
71694
|
try {
|
|
70924
71695
|
const planPath = path74.join(directory, ".swarm", "plan.json");
|
|
70925
|
-
if (!
|
|
71696
|
+
if (!fs62.existsSync(planPath))
|
|
70926
71697
|
return null;
|
|
70927
|
-
const raw =
|
|
71698
|
+
const raw = fs62.readFileSync(planPath, "utf-8");
|
|
70928
71699
|
const plan = JSON.parse(raw);
|
|
70929
71700
|
for (const phase of plan.phases ?? []) {
|
|
70930
71701
|
for (const task of phase.tasks ?? []) {
|
|
@@ -71002,6 +71773,7 @@ async function validateDiffScope(taskId, directory) {
|
|
|
71002
71773
|
|
|
71003
71774
|
// src/tools/update-task-status.ts
|
|
71004
71775
|
init_manager2();
|
|
71776
|
+
init_state();
|
|
71005
71777
|
init_telemetry();
|
|
71006
71778
|
init_create_tool();
|
|
71007
71779
|
var VALID_STATUSES2 = [
|
|
@@ -71052,7 +71824,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
71052
71824
|
const resolvedDir2 = workingDirectory;
|
|
71053
71825
|
try {
|
|
71054
71826
|
const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
|
|
71055
|
-
const planRaw =
|
|
71827
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71056
71828
|
const plan = JSON.parse(planRaw);
|
|
71057
71829
|
for (const planPhase of plan.phases ?? []) {
|
|
71058
71830
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -71119,7 +71891,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
71119
71891
|
try {
|
|
71120
71892
|
const resolvedDir2 = workingDirectory;
|
|
71121
71893
|
const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
|
|
71122
|
-
const planRaw =
|
|
71894
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71123
71895
|
const plan = JSON.parse(planRaw);
|
|
71124
71896
|
for (const planPhase of plan.phases ?? []) {
|
|
71125
71897
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -71314,9 +72086,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71314
72086
|
}
|
|
71315
72087
|
const resolvedDir = path75.resolve(normalizedDir);
|
|
71316
72088
|
try {
|
|
71317
|
-
const realPath =
|
|
72089
|
+
const realPath = fs63.realpathSync(resolvedDir);
|
|
71318
72090
|
const planPath = path75.join(realPath, ".swarm", "plan.json");
|
|
71319
|
-
if (!
|
|
72091
|
+
if (!fs63.existsSync(planPath)) {
|
|
71320
72092
|
return {
|
|
71321
72093
|
success: false,
|
|
71322
72094
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -71348,11 +72120,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71348
72120
|
if (args2.status === "in_progress") {
|
|
71349
72121
|
try {
|
|
71350
72122
|
const evidencePath = path75.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
71351
|
-
|
|
71352
|
-
const fd =
|
|
72123
|
+
fs63.mkdirSync(path75.dirname(evidencePath), { recursive: true });
|
|
72124
|
+
const fd = fs63.openSync(evidencePath, "wx");
|
|
71353
72125
|
let writeOk = false;
|
|
71354
72126
|
try {
|
|
71355
|
-
|
|
72127
|
+
fs63.writeSync(fd, JSON.stringify({
|
|
71356
72128
|
task_id: args2.task_id,
|
|
71357
72129
|
required_gates: ["reviewer", "test_engineer"],
|
|
71358
72130
|
gates: {},
|
|
@@ -71360,10 +72132,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71360
72132
|
}, null, 2));
|
|
71361
72133
|
writeOk = true;
|
|
71362
72134
|
} finally {
|
|
71363
|
-
|
|
72135
|
+
fs63.closeSync(fd);
|
|
71364
72136
|
if (!writeOk) {
|
|
71365
72137
|
try {
|
|
71366
|
-
|
|
72138
|
+
fs63.unlinkSync(evidencePath);
|
|
71367
72139
|
} catch {}
|
|
71368
72140
|
}
|
|
71369
72141
|
}
|
|
@@ -71374,7 +72146,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
71374
72146
|
let phaseRequiresReviewer = true;
|
|
71375
72147
|
try {
|
|
71376
72148
|
const planPath = path75.join(directory, ".swarm", "plan.json");
|
|
71377
|
-
const planRaw =
|
|
72149
|
+
const planRaw = fs63.readFileSync(planPath, "utf-8");
|
|
71378
72150
|
const plan = JSON.parse(planRaw);
|
|
71379
72151
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
71380
72152
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -71472,7 +72244,7 @@ var update_task_status = createSwarmTool({
|
|
|
71472
72244
|
init_tool();
|
|
71473
72245
|
init_utils2();
|
|
71474
72246
|
init_create_tool();
|
|
71475
|
-
import
|
|
72247
|
+
import fs64 from "fs";
|
|
71476
72248
|
import path76 from "path";
|
|
71477
72249
|
function normalizeVerdict(verdict) {
|
|
71478
72250
|
switch (verdict) {
|
|
@@ -71533,10 +72305,10 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
71533
72305
|
}
|
|
71534
72306
|
const evidenceDir = path76.dirname(validatedPath);
|
|
71535
72307
|
try {
|
|
71536
|
-
await
|
|
72308
|
+
await fs64.promises.mkdir(evidenceDir, { recursive: true });
|
|
71537
72309
|
const tempPath = path76.join(evidenceDir, `.${filename}.tmp`);
|
|
71538
|
-
await
|
|
71539
|
-
await
|
|
72310
|
+
await fs64.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
72311
|
+
await fs64.promises.rename(tempPath, validatedPath);
|
|
71540
72312
|
return JSON.stringify({
|
|
71541
72313
|
success: true,
|
|
71542
72314
|
phase,
|
|
@@ -71614,6 +72386,14 @@ ${footerLines.join(`
|
|
|
71614
72386
|
var _heartbeatTimers = new Map;
|
|
71615
72387
|
var OpenCodeSwarm = async (ctx) => {
|
|
71616
72388
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
72389
|
+
if (config3.full_auto?.enabled === true) {
|
|
72390
|
+
const criticModel = config3.full_auto.critic_model ?? config3.agents?.critic?.model ?? DEFAULT_MODELS.critic;
|
|
72391
|
+
const architectModel = config3.agents?.architect?.model ?? DEFAULT_MODELS.default;
|
|
72392
|
+
if (criticModel === architectModel) {
|
|
72393
|
+
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)");
|
|
72394
|
+
}
|
|
72395
|
+
}
|
|
72396
|
+
swarmState.fullAutoEnabledInConfig = config3.full_auto?.enabled === true;
|
|
71617
72397
|
swarmState.opencodeClient = ctx.client;
|
|
71618
72398
|
await loadSnapshot(ctx.directory);
|
|
71619
72399
|
initTelemetry(ctx.directory);
|
|
@@ -71652,6 +72432,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
71652
72432
|
const delegationHandler = createDelegationTrackerHook(config3, guardrailsConfig.enabled);
|
|
71653
72433
|
const authorityConfig = AuthorityConfigSchema.parse(config3.authority ?? {});
|
|
71654
72434
|
const guardrailsHooks = createGuardrailsHooks(ctx.directory, undefined, guardrailsConfig, authorityConfig);
|
|
72435
|
+
const fullAutoInterceptHook = createFullAutoInterceptHook(config3, ctx.directory);
|
|
71655
72436
|
const watchdogConfig = WatchdogConfigSchema.parse(config3.watchdog ?? {});
|
|
71656
72437
|
const advisoryInjector = (sessionId, message) => {
|
|
71657
72438
|
const s = swarmState.agentSessions.get(sessionId);
|
|
@@ -72034,6 +72815,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
72034
72815
|
pipelineHook["experimental.chat.messages.transform"],
|
|
72035
72816
|
contextBudgetHandler,
|
|
72036
72817
|
guardrailsHooks.messagesTransform,
|
|
72818
|
+
fullAutoInterceptHook?.messagesTransform,
|
|
72037
72819
|
delegationGateHooks.messagesTransform,
|
|
72038
72820
|
delegationSanitizerHook,
|
|
72039
72821
|
knowledgeInjectorHook,
|