opencode-swarm-plugin 0.56.1 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/claude-plugin/agents/background-worker.md +1 -0
- package/claude-plugin/agents/coordinator.md +1 -0
- package/claude-plugin/agents/worker.md +1 -0
- package/claude-plugin/bin/swarm-mcp-server.ts +47 -8
- package/claude-plugin/dist/agent-mail.d.ts +480 -0
- package/claude-plugin/dist/agent-mail.d.ts.map +1 -0
- package/claude-plugin/dist/anti-patterns.d.ts +257 -0
- package/claude-plugin/dist/anti-patterns.d.ts.map +1 -0
- package/claude-plugin/dist/bin/swarm.js +373128 -0
- package/claude-plugin/dist/cass-tools.d.ts +74 -0
- package/claude-plugin/dist/cass-tools.d.ts.map +1 -0
- package/claude-plugin/dist/claude-plugin/claude-plugin-assets.d.ts +10 -0
- package/claude-plugin/dist/claude-plugin/claude-plugin-assets.d.ts.map +1 -0
- package/claude-plugin/dist/compaction-hook.d.ts +178 -0
- package/claude-plugin/dist/compaction-hook.d.ts.map +1 -0
- package/claude-plugin/dist/compaction-observability.d.ts +173 -0
- package/claude-plugin/dist/compaction-observability.d.ts.map +1 -0
- package/claude-plugin/dist/compaction-prompt-scoring.d.ts +125 -0
- package/claude-plugin/dist/compaction-prompt-scoring.d.ts.map +1 -0
- package/claude-plugin/dist/compaction-prompt-scoring.js +139 -0
- package/claude-plugin/dist/contributor-tools.d.ts +42 -0
- package/claude-plugin/dist/contributor-tools.d.ts.map +1 -0
- package/claude-plugin/dist/coordinator-guard.d.ts +79 -0
- package/claude-plugin/dist/coordinator-guard.d.ts.map +1 -0
- package/claude-plugin/dist/dashboard.d.ts +82 -0
- package/claude-plugin/dist/dashboard.d.ts.map +1 -0
- package/claude-plugin/dist/decision-trace-integration.d.ts +204 -0
- package/claude-plugin/dist/decision-trace-integration.d.ts.map +1 -0
- package/claude-plugin/dist/error-enrichment.d.ts +49 -0
- package/claude-plugin/dist/error-enrichment.d.ts.map +1 -0
- package/claude-plugin/dist/eval-capture.d.ts +494 -0
- package/claude-plugin/dist/eval-capture.d.ts.map +1 -0
- package/claude-plugin/dist/eval-capture.js +12844 -0
- package/claude-plugin/dist/eval-gates.d.ts +84 -0
- package/claude-plugin/dist/eval-gates.d.ts.map +1 -0
- package/claude-plugin/dist/eval-history.d.ts +117 -0
- package/claude-plugin/dist/eval-history.d.ts.map +1 -0
- package/claude-plugin/dist/eval-learning.d.ts +216 -0
- package/claude-plugin/dist/eval-learning.d.ts.map +1 -0
- package/claude-plugin/dist/eval-runner.d.ts +134 -0
- package/claude-plugin/dist/eval-runner.d.ts.map +1 -0
- package/claude-plugin/dist/examples/plugin-wrapper-template.ts +3341 -0
- package/claude-plugin/dist/export-tools.d.ts +76 -0
- package/claude-plugin/dist/export-tools.d.ts.map +1 -0
- package/claude-plugin/dist/hive.d.ts +949 -0
- package/claude-plugin/dist/hive.d.ts.map +1 -0
- package/claude-plugin/dist/hive.js +15009 -0
- package/claude-plugin/dist/hivemind-tools.d.ts +479 -0
- package/claude-plugin/dist/hivemind-tools.d.ts.map +1 -0
- package/claude-plugin/dist/hooks/atomic-write.d.ts +21 -0
- package/claude-plugin/dist/hooks/atomic-write.d.ts.map +1 -0
- package/claude-plugin/dist/hooks/constants.d.ts +28 -0
- package/claude-plugin/dist/hooks/constants.d.ts.map +1 -0
- package/claude-plugin/dist/hooks/index.d.ts +16 -0
- package/claude-plugin/dist/hooks/index.d.ts.map +1 -0
- package/claude-plugin/dist/hooks/session-start.d.ts +30 -0
- package/claude-plugin/dist/hooks/session-start.d.ts.map +1 -0
- package/claude-plugin/dist/hooks/tool-complete.d.ts +54 -0
- package/claude-plugin/dist/hooks/tool-complete.d.ts.map +1 -0
- package/claude-plugin/dist/index.d.ts +2017 -0
- package/claude-plugin/dist/index.d.ts.map +1 -0
- package/claude-plugin/dist/index.js +73453 -0
- package/claude-plugin/dist/learning.d.ts +700 -0
- package/claude-plugin/dist/learning.d.ts.map +1 -0
- package/claude-plugin/dist/logger.d.ts +38 -0
- package/claude-plugin/dist/logger.d.ts.map +1 -0
- package/claude-plugin/dist/mandate-promotion.d.ts +93 -0
- package/claude-plugin/dist/mandate-promotion.d.ts.map +1 -0
- package/claude-plugin/dist/mandate-storage.d.ts +209 -0
- package/claude-plugin/dist/mandate-storage.d.ts.map +1 -0
- package/claude-plugin/dist/mandates.d.ts +230 -0
- package/claude-plugin/dist/mandates.d.ts.map +1 -0
- package/claude-plugin/dist/memory-tools.d.ts +281 -0
- package/claude-plugin/dist/memory-tools.d.ts.map +1 -0
- package/claude-plugin/dist/memory.d.ts +164 -0
- package/claude-plugin/dist/memory.d.ts.map +1 -0
- package/claude-plugin/dist/model-selection.d.ts +37 -0
- package/claude-plugin/dist/model-selection.d.ts.map +1 -0
- package/claude-plugin/dist/observability-health.d.ts +87 -0
- package/claude-plugin/dist/observability-health.d.ts.map +1 -0
- package/claude-plugin/dist/observability-tools.d.ts +184 -0
- package/claude-plugin/dist/observability-tools.d.ts.map +1 -0
- package/claude-plugin/dist/output-guardrails.d.ts +125 -0
- package/claude-plugin/dist/output-guardrails.d.ts.map +1 -0
- package/claude-plugin/dist/pattern-maturity.d.ts +246 -0
- package/claude-plugin/dist/pattern-maturity.d.ts.map +1 -0
- package/claude-plugin/dist/planning-guardrails.d.ts +183 -0
- package/claude-plugin/dist/planning-guardrails.d.ts.map +1 -0
- package/claude-plugin/dist/plugin.d.ts +22 -0
- package/claude-plugin/dist/plugin.d.ts.map +1 -0
- package/claude-plugin/dist/plugin.js +72295 -0
- package/claude-plugin/dist/post-compaction-tracker.d.ts +133 -0
- package/claude-plugin/dist/post-compaction-tracker.d.ts.map +1 -0
- package/claude-plugin/dist/query-tools.d.ts +90 -0
- package/claude-plugin/dist/query-tools.d.ts.map +1 -0
- package/claude-plugin/dist/rate-limiter.d.ts +218 -0
- package/claude-plugin/dist/rate-limiter.d.ts.map +1 -0
- package/claude-plugin/dist/regression-detection.d.ts +58 -0
- package/claude-plugin/dist/regression-detection.d.ts.map +1 -0
- package/claude-plugin/dist/replay-tools.d.ts +28 -0
- package/claude-plugin/dist/replay-tools.d.ts.map +1 -0
- package/claude-plugin/dist/repo-crawl.d.ts +146 -0
- package/claude-plugin/dist/repo-crawl.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/cell-events.d.ts +1352 -0
- package/claude-plugin/dist/schemas/cell-events.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/cell.d.ts +413 -0
- package/claude-plugin/dist/schemas/cell.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/evaluation.d.ts +161 -0
- package/claude-plugin/dist/schemas/evaluation.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/index.d.ts +46 -0
- package/claude-plugin/dist/schemas/index.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/mandate.d.ts +336 -0
- package/claude-plugin/dist/schemas/mandate.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/swarm-context.d.ts +131 -0
- package/claude-plugin/dist/schemas/swarm-context.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/task.d.ts +189 -0
- package/claude-plugin/dist/schemas/task.d.ts.map +1 -0
- package/claude-plugin/dist/schemas/worker-handoff.d.ts +78 -0
- package/claude-plugin/dist/schemas/worker-handoff.d.ts.map +1 -0
- package/claude-plugin/dist/sessions/agent-discovery.d.ts +59 -0
- package/claude-plugin/dist/sessions/agent-discovery.d.ts.map +1 -0
- package/claude-plugin/dist/sessions/index.d.ts +10 -0
- package/claude-plugin/dist/sessions/index.d.ts.map +1 -0
- package/claude-plugin/dist/skills.d.ts +490 -0
- package/claude-plugin/dist/skills.d.ts.map +1 -0
- package/claude-plugin/dist/storage.d.ts +260 -0
- package/claude-plugin/dist/storage.d.ts.map +1 -0
- package/claude-plugin/dist/structured.d.ts +206 -0
- package/claude-plugin/dist/structured.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-adversarial-review.d.ts +104 -0
- package/claude-plugin/dist/swarm-adversarial-review.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-decompose.d.ts +297 -0
- package/claude-plugin/dist/swarm-decompose.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-insights.d.ts +390 -0
- package/claude-plugin/dist/swarm-insights.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-mail.d.ts +274 -0
- package/claude-plugin/dist/swarm-mail.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-orchestrate.d.ts +924 -0
- package/claude-plugin/dist/swarm-orchestrate.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-prompts.d.ts +467 -0
- package/claude-plugin/dist/swarm-prompts.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-prompts.js +45283 -0
- package/claude-plugin/dist/swarm-research.d.ts +125 -0
- package/claude-plugin/dist/swarm-research.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-review.d.ts +214 -0
- package/claude-plugin/dist/swarm-review.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-signature.d.ts +106 -0
- package/claude-plugin/dist/swarm-signature.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-strategies.d.ts +113 -0
- package/claude-plugin/dist/swarm-strategies.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-validation.d.ts +127 -0
- package/claude-plugin/dist/swarm-validation.d.ts.map +1 -0
- package/claude-plugin/dist/swarm-worktree.d.ts +185 -0
- package/claude-plugin/dist/swarm-worktree.d.ts.map +1 -0
- package/claude-plugin/dist/swarm.d.ts +590 -0
- package/claude-plugin/dist/swarm.d.ts.map +1 -0
- package/claude-plugin/dist/tool-availability.d.ts +91 -0
- package/claude-plugin/dist/tool-availability.d.ts.map +1 -0
- package/claude-plugin/dist/utils/tree-renderer.d.ts +61 -0
- package/claude-plugin/dist/utils/tree-renderer.d.ts.map +1 -0
- package/claude-plugin/dist/validators/index.d.ts +7 -0
- package/claude-plugin/dist/validators/index.d.ts.map +1 -0
- package/claude-plugin/dist/validators/schema-validator.d.ts +58 -0
- package/claude-plugin/dist/validators/schema-validator.d.ts.map +1 -0
- package/claude-plugin/skills/always-on-guidance/SKILL.md +44 -0
- package/dist/agent-mail.d.ts +4 -4
- package/dist/agent-mail.d.ts.map +1 -1
- package/dist/bin/swarm.js +467 -12
- package/dist/claude-plugin/claude-plugin-assets.d.ts +10 -0
- package/dist/claude-plugin/claude-plugin-assets.d.ts.map +1 -0
- package/dist/compaction-hook.d.ts +1 -1
- package/dist/compaction-hook.d.ts.map +1 -1
- package/dist/index.js +370 -260
- package/dist/plugin.js +369 -259
- package/dist/skills.d.ts +15 -0
- package/dist/skills.d.ts.map +1 -1
- package/dist/swarm-mail.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +3 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-prompts.js +79 -2
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -26934,6 +26934,7 @@ __export(exports_skills, {
|
|
|
26934
26934
|
invalidateSkillsCache: () => invalidateSkillsCache,
|
|
26935
26935
|
getSkillsContextForSwarm: () => getSkillsContextForSwarm,
|
|
26936
26936
|
getSkill: () => getSkill,
|
|
26937
|
+
getAlwaysOnGuidanceSkill: () => getAlwaysOnGuidanceSkill,
|
|
26937
26938
|
findRelevantSkills: () => findRelevantSkills,
|
|
26938
26939
|
discoverSkills: () => discoverSkills
|
|
26939
26940
|
});
|
|
@@ -26949,6 +26950,44 @@ import {
|
|
|
26949
26950
|
} from "path";
|
|
26950
26951
|
import { fileURLToPath } from "url";
|
|
26951
26952
|
import { getSwarmMailLibSQL as getSwarmMailLibSQL3, createEvent as createEvent2 } from "swarm-mail";
|
|
26953
|
+
function resolveGuidanceModel(model) {
|
|
26954
|
+
if (!model)
|
|
26955
|
+
return "unknown";
|
|
26956
|
+
const normalized = model.toLowerCase();
|
|
26957
|
+
if (normalized.includes("gpt-5.2")) {
|
|
26958
|
+
return "gpt-5.2-code";
|
|
26959
|
+
}
|
|
26960
|
+
if (normalized.includes("opus-4-5") || normalized.includes("opus 4.5")) {
|
|
26961
|
+
return "opus-4.5";
|
|
26962
|
+
}
|
|
26963
|
+
return "unknown";
|
|
26964
|
+
}
|
|
26965
|
+
function getAlwaysOnGuidanceSkill(options2) {
|
|
26966
|
+
const roleGuidance = ALWAYS_ON_ROLE_GUIDANCE[options2.role];
|
|
26967
|
+
const modelBucket = resolveGuidanceModel(options2.model);
|
|
26968
|
+
let modelGuidance = "";
|
|
26969
|
+
if (modelBucket === "gpt-5.2-code") {
|
|
26970
|
+
modelGuidance = `### Model-Specific Guidance
|
|
26971
|
+
${GPT_5_2_GUIDANCE}`;
|
|
26972
|
+
} else if (modelBucket === "opus-4.5") {
|
|
26973
|
+
modelGuidance = `### Model-Specific Guidance
|
|
26974
|
+
${OPUS_4_5_GUIDANCE}`;
|
|
26975
|
+
} else {
|
|
26976
|
+
modelGuidance = `### Model-Specific Guidance
|
|
26977
|
+
${GPT_5_2_GUIDANCE}
|
|
26978
|
+
|
|
26979
|
+
${OPUS_4_5_GUIDANCE}`;
|
|
26980
|
+
}
|
|
26981
|
+
return [
|
|
26982
|
+
ALWAYS_ON_GUIDANCE_HEADER,
|
|
26983
|
+
ALWAYS_ON_TOOL_PRIORITY,
|
|
26984
|
+
ALWAYS_ON_RULE_FOLLOWING,
|
|
26985
|
+
roleGuidance,
|
|
26986
|
+
modelGuidance
|
|
26987
|
+
].join(`
|
|
26988
|
+
|
|
26989
|
+
`);
|
|
26990
|
+
}
|
|
26952
26991
|
async function emitSkillLoadedEvent(data) {
|
|
26953
26992
|
try {
|
|
26954
26993
|
const projectPath = skillsProjectDirectory;
|
|
@@ -27348,10 +27387,38 @@ async function findRelevantSkills(taskDescription) {
|
|
|
27348
27387
|
}
|
|
27349
27388
|
return relevant;
|
|
27350
27389
|
}
|
|
27351
|
-
var import_gray_matter,
|
|
27390
|
+
var import_gray_matter, ALWAYS_ON_GUIDANCE_HEADER = "## Always-On Guidance Skill", ALWAYS_ON_TOOL_PRIORITY = `### Tool Priority Order
|
|
27391
|
+
1. Swarm plugin tools (\`hive_*\`, \`swarm_*\`, \`swarmmail_*\`, \`structured_*\`)
|
|
27392
|
+
2. \`Read\`/\`Edit\` for file operations
|
|
27393
|
+
3. \`ast-grep\` for structural search
|
|
27394
|
+
4. \`Glob\`/\`Grep\` for discovery
|
|
27395
|
+
5. \`Task\` subagents for exploration
|
|
27396
|
+
6. \`Bash\` only for system commands
|
|
27397
|
+
|
|
27398
|
+
**Never use Bash for file read/write/edit/search.**`, ALWAYS_ON_RULE_FOLLOWING = `### Rule-Following Guardrails
|
|
27399
|
+
- Follow explicit tool constraints and approval modes
|
|
27400
|
+
- Do not invent tool output or files; ask when unsure
|
|
27401
|
+
- Keep changes scoped to assigned files and requirements`, ALWAYS_ON_ROLE_GUIDANCE, GPT_5_2_GUIDANCE = `#### GPT-5.2-code (Strict)
|
|
27402
|
+
- Follow instructions literally and exactly
|
|
27403
|
+
- Enforce tool priority order; fail closed if a tool is missing
|
|
27404
|
+
- Read before Edit; no speculative changes or output`, OPUS_4_5_GUIDANCE = `#### Opus 4.5 (Concise)
|
|
27405
|
+
- Be concise and deliberate while obeying mandates
|
|
27406
|
+
- Follow tool priorities without shortcuts
|
|
27407
|
+
- Prefer direct answers over speculation`, skillsProjectDirectory, skillsCache = null, PROJECT_SKILL_DIRECTORIES, skills_list, skills_use, skills_execute, skills_read, DEFAULT_SKILLS_DIR = ".opencode/skill", skills_create, skills_update, skills_delete, skills_add_script, skills_init, skillsTools;
|
|
27352
27408
|
var init_skills = __esm(() => {
|
|
27353
27409
|
init_dist();
|
|
27354
27410
|
import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
27411
|
+
ALWAYS_ON_ROLE_GUIDANCE = {
|
|
27412
|
+
coordinator: `### Coordinator Enforcement
|
|
27413
|
+
- Coordinator role: orchestrate, decompose, spawn workers
|
|
27414
|
+
- **Never** edit files or reserve locks directly
|
|
27415
|
+
- Coordinator override: use \`swarmmail_release_all\` only for stale/orphaned reservations (announce in Swarm Mail)
|
|
27416
|
+
- Review work with \`swarm_review\` before accepting`,
|
|
27417
|
+
worker: `### Worker Enforcement
|
|
27418
|
+
- Worker role: implement changes within reserved files
|
|
27419
|
+
- Reserve files before edits and follow TDD (RED → GREEN → REFACTOR)
|
|
27420
|
+
- Complete with \`swarm_complete\`, not \`hive_close\``
|
|
27421
|
+
};
|
|
27355
27422
|
skillsProjectDirectory = process.cwd();
|
|
27356
27423
|
PROJECT_SKILL_DIRECTORIES = [
|
|
27357
27424
|
".opencode/skill",
|
|
@@ -60505,8 +60572,8 @@ import {
|
|
|
60505
60572
|
import { join as join4 } from "path";
|
|
60506
60573
|
import { tmpdir } from "os";
|
|
60507
60574
|
var AGENT_MAIL_URL = "http://127.0.0.1:8765";
|
|
60508
|
-
var DEFAULT_TTL_SECONDS = 3600;
|
|
60509
60575
|
var MAX_INBOX_LIMIT = 5;
|
|
60576
|
+
var DEFAULT_OPENCODE_MODEL = "openai/gpt-5.2-codex";
|
|
60510
60577
|
var agentMailProjectDirectory = null;
|
|
60511
60578
|
function setAgentMailProjectDirectory(directory) {
|
|
60512
60579
|
agentMailProjectDirectory = directory;
|
|
@@ -60916,7 +60983,7 @@ async function reRegisterAgent(projectKey, agentName, taskDescription) {
|
|
|
60916
60983
|
await mcpCall("register_agent", {
|
|
60917
60984
|
project_key: projectKey,
|
|
60918
60985
|
program: "opencode",
|
|
60919
|
-
model:
|
|
60986
|
+
model: DEFAULT_OPENCODE_MODEL,
|
|
60920
60987
|
name: agentName,
|
|
60921
60988
|
task_description: taskDescription || "Re-registered after server restart"
|
|
60922
60989
|
});
|
|
@@ -61005,7 +61072,7 @@ var agentmail_init = tool({
|
|
|
61005
61072
|
const agent = await mcpCall("register_agent", {
|
|
61006
61073
|
project_key: projectPath,
|
|
61007
61074
|
program: "opencode",
|
|
61008
|
-
model:
|
|
61075
|
+
model: DEFAULT_OPENCODE_MODEL,
|
|
61009
61076
|
name: args.agent_name,
|
|
61010
61077
|
task_description: args.task_description || ""
|
|
61011
61078
|
});
|
|
@@ -61148,18 +61215,21 @@ var agentmail_reserve = tool({
|
|
|
61148
61215
|
description: "Reserve file paths for exclusive editing",
|
|
61149
61216
|
args: {
|
|
61150
61217
|
paths: tool.schema.array(tool.schema.string()).describe("File paths or globs to reserve (e.g., src/auth/**)"),
|
|
61151
|
-
ttl_seconds: tool.schema.number().
|
|
61218
|
+
ttl_seconds: tool.schema.number().int().positive().describe("Time to live in seconds (required)"),
|
|
61152
61219
|
exclusive: tool.schema.boolean().optional().describe("Exclusive lock (default: true)"),
|
|
61153
61220
|
reason: tool.schema.string().optional().describe("Reason for reservation (include bead ID)")
|
|
61154
61221
|
},
|
|
61155
61222
|
async execute(args, ctx) {
|
|
61156
61223
|
const state = requireState(ctx.sessionID);
|
|
61157
61224
|
await checkRateLimit(state.agentName, "reserve");
|
|
61225
|
+
if (!args.ttl_seconds || args.ttl_seconds <= 0) {
|
|
61226
|
+
throw new AgentMailError("ttl_seconds is required for file reservations", "file_reservation_paths");
|
|
61227
|
+
}
|
|
61158
61228
|
const result = await mcpCall("file_reservation_paths", {
|
|
61159
61229
|
project_key: state.projectKey,
|
|
61160
61230
|
agent_name: state.agentName,
|
|
61161
61231
|
paths: args.paths,
|
|
61162
|
-
ttl_seconds: args.ttl_seconds
|
|
61232
|
+
ttl_seconds: args.ttl_seconds,
|
|
61163
61233
|
exclusive: args.exclusive ?? true,
|
|
61164
61234
|
reason: args.reason || ""
|
|
61165
61235
|
});
|
|
@@ -61197,11 +61267,13 @@ var agentmail_release = tool({
|
|
|
61197
61267
|
async execute(args, ctx) {
|
|
61198
61268
|
const state = requireState(ctx.sessionID);
|
|
61199
61269
|
await checkRateLimit(state.agentName, "release");
|
|
61270
|
+
const shouldUseStoredIds = !args.paths && (!args.reservation_ids || args.reservation_ids.length === 0);
|
|
61271
|
+
const reservationIds = shouldUseStoredIds && state.reservations.length > 0 ? state.reservations : args.reservation_ids;
|
|
61200
61272
|
const result = await mcpCall("release_file_reservations", {
|
|
61201
61273
|
project_key: state.projectKey,
|
|
61202
61274
|
agent_name: state.agentName,
|
|
61203
61275
|
paths: args.paths,
|
|
61204
|
-
file_reservation_ids:
|
|
61276
|
+
file_reservation_ids: reservationIds
|
|
61205
61277
|
});
|
|
61206
61278
|
state.reservations = [];
|
|
61207
61279
|
setState(ctx.sessionID, state);
|
|
@@ -61327,6 +61399,260 @@ import {
|
|
|
61327
61399
|
checkSwarmHealth as checkSwarmHealth2,
|
|
61328
61400
|
getActiveReservations
|
|
61329
61401
|
} from "swarm-mail";
|
|
61402
|
+
|
|
61403
|
+
// src/planning-guardrails.ts
|
|
61404
|
+
init_eval_capture();
|
|
61405
|
+
var FILE_MODIFICATION_PATTERNS = [
|
|
61406
|
+
/\bimplement\b/i,
|
|
61407
|
+
/\bcreate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
61408
|
+
/\badd\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
61409
|
+
/\bupdate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
61410
|
+
/\bmodify\b/i,
|
|
61411
|
+
/\brefactor\b/i,
|
|
61412
|
+
/\bextract\b/i,
|
|
61413
|
+
/\bmigrate\b/i,
|
|
61414
|
+
/\bconvert\b/i,
|
|
61415
|
+
/\brewrite\b/i,
|
|
61416
|
+
/\bfix\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
61417
|
+
/\bwrite\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
61418
|
+
/src\//i,
|
|
61419
|
+
/lib\//i,
|
|
61420
|
+
/packages?\//i,
|
|
61421
|
+
/components?\//i
|
|
61422
|
+
];
|
|
61423
|
+
var TRACKING_PATTERNS = [
|
|
61424
|
+
/\breview\b/i,
|
|
61425
|
+
/\bcheck\b/i,
|
|
61426
|
+
/\bverify\b/i,
|
|
61427
|
+
/\btest\b.*pass/i,
|
|
61428
|
+
/\brun\b.*test/i,
|
|
61429
|
+
/\bdeploy\b/i,
|
|
61430
|
+
/\bmerge\b/i,
|
|
61431
|
+
/\bpr\b/i,
|
|
61432
|
+
/\bpush\b/i,
|
|
61433
|
+
/\bcommit\b/i
|
|
61434
|
+
];
|
|
61435
|
+
function analyzeTodoWrite(args) {
|
|
61436
|
+
const todos = args.todos;
|
|
61437
|
+
if (!todos || !Array.isArray(todos) || todos.length < 6) {
|
|
61438
|
+
return {
|
|
61439
|
+
looksLikeParallelWork: false,
|
|
61440
|
+
fileModificationCount: 0,
|
|
61441
|
+
totalCount: todos?.length ?? 0
|
|
61442
|
+
};
|
|
61443
|
+
}
|
|
61444
|
+
let fileModificationCount = 0;
|
|
61445
|
+
for (const todo of todos) {
|
|
61446
|
+
if (typeof todo !== "object" || todo === null)
|
|
61447
|
+
continue;
|
|
61448
|
+
const content = todo.content ?? "";
|
|
61449
|
+
const isFileModification = FILE_MODIFICATION_PATTERNS.some((pattern) => pattern.test(content));
|
|
61450
|
+
const isTracking = TRACKING_PATTERNS.some((pattern) => pattern.test(content));
|
|
61451
|
+
if (isFileModification && !isTracking) {
|
|
61452
|
+
fileModificationCount++;
|
|
61453
|
+
}
|
|
61454
|
+
}
|
|
61455
|
+
const ratio = fileModificationCount / todos.length;
|
|
61456
|
+
const looksLikeParallelWork = ratio >= 0.5 && fileModificationCount >= 4;
|
|
61457
|
+
if (looksLikeParallelWork) {
|
|
61458
|
+
return {
|
|
61459
|
+
looksLikeParallelWork: true,
|
|
61460
|
+
fileModificationCount,
|
|
61461
|
+
totalCount: todos.length,
|
|
61462
|
+
warning: `⚠️ This looks like a multi-file implementation plan (${fileModificationCount}/${todos.length} items are file modifications).
|
|
61463
|
+
|
|
61464
|
+
Consider using swarm instead:
|
|
61465
|
+
swarm_decompose → hive_create_epic → parallel task spawns
|
|
61466
|
+
|
|
61467
|
+
TodoWrite is for tracking progress, not parallelizable implementation work.
|
|
61468
|
+
Swarm workers can complete these ${fileModificationCount} tasks in parallel.
|
|
61469
|
+
|
|
61470
|
+
(Continuing with todowrite - this is just a suggestion)`
|
|
61471
|
+
};
|
|
61472
|
+
}
|
|
61473
|
+
return {
|
|
61474
|
+
looksLikeParallelWork: false,
|
|
61475
|
+
fileModificationCount,
|
|
61476
|
+
totalCount: todos.length
|
|
61477
|
+
};
|
|
61478
|
+
}
|
|
61479
|
+
function shouldAnalyzeTool(toolName) {
|
|
61480
|
+
return toolName === "todowrite" || toolName === "TodoWrite";
|
|
61481
|
+
}
|
|
61482
|
+
var VIOLATION_PATTERNS = {
|
|
61483
|
+
FILE_MODIFICATION_TOOLS: ["edit", "write"],
|
|
61484
|
+
RESERVATION_TOOLS: ["swarmmail_reserve", "agentmail_reserve"],
|
|
61485
|
+
TEST_EXECUTION_PATTERNS: [
|
|
61486
|
+
/\bbun\s+test\b/i,
|
|
61487
|
+
/\bnpm\s+(run\s+)?test/i,
|
|
61488
|
+
/\byarn\s+(run\s+)?test/i,
|
|
61489
|
+
/\bpnpm\s+(run\s+)?test/i,
|
|
61490
|
+
/\bjest\b/i,
|
|
61491
|
+
/\bvitest\b/i,
|
|
61492
|
+
/\bmocha\b/i,
|
|
61493
|
+
/\bava\b/i,
|
|
61494
|
+
/\btape\b/i,
|
|
61495
|
+
/\.test\.(ts|js|tsx|jsx)\b/i,
|
|
61496
|
+
/\.spec\.(ts|js|tsx|jsx)\b/i
|
|
61497
|
+
]
|
|
61498
|
+
};
|
|
61499
|
+
function detectCoordinatorViolation(params) {
|
|
61500
|
+
const { sessionId, epicId, toolName, toolArgs, agentContext, checkNoSpawn = false } = params;
|
|
61501
|
+
if (agentContext !== "coordinator") {
|
|
61502
|
+
return { isViolation: false };
|
|
61503
|
+
}
|
|
61504
|
+
if (VIOLATION_PATTERNS.FILE_MODIFICATION_TOOLS.includes(toolName)) {
|
|
61505
|
+
const file2 = toolArgs.filePath || "";
|
|
61506
|
+
const payload = { tool: toolName, file: file2 };
|
|
61507
|
+
captureCoordinatorEvent({
|
|
61508
|
+
session_id: sessionId,
|
|
61509
|
+
epic_id: epicId,
|
|
61510
|
+
timestamp: new Date().toISOString(),
|
|
61511
|
+
event_type: "VIOLATION",
|
|
61512
|
+
violation_type: "coordinator_edited_file",
|
|
61513
|
+
payload
|
|
61514
|
+
});
|
|
61515
|
+
return {
|
|
61516
|
+
isViolation: true,
|
|
61517
|
+
violationType: "coordinator_edited_file",
|
|
61518
|
+
message: `⚠️ Coordinator should not edit files directly. Coordinators should spawn workers to implement changes.`,
|
|
61519
|
+
payload
|
|
61520
|
+
};
|
|
61521
|
+
}
|
|
61522
|
+
if (toolName === "bash") {
|
|
61523
|
+
const command = toolArgs.command || "";
|
|
61524
|
+
const isTestCommand = VIOLATION_PATTERNS.TEST_EXECUTION_PATTERNS.some((pattern) => pattern.test(command));
|
|
61525
|
+
if (isTestCommand) {
|
|
61526
|
+
const payload = { tool: toolName, command };
|
|
61527
|
+
captureCoordinatorEvent({
|
|
61528
|
+
session_id: sessionId,
|
|
61529
|
+
epic_id: epicId,
|
|
61530
|
+
timestamp: new Date().toISOString(),
|
|
61531
|
+
event_type: "VIOLATION",
|
|
61532
|
+
violation_type: "coordinator_ran_tests",
|
|
61533
|
+
payload
|
|
61534
|
+
});
|
|
61535
|
+
return {
|
|
61536
|
+
isViolation: true,
|
|
61537
|
+
violationType: "coordinator_ran_tests",
|
|
61538
|
+
message: `⚠️ Coordinator should not run tests directly. Workers run tests as part of their implementation verification.`,
|
|
61539
|
+
payload
|
|
61540
|
+
};
|
|
61541
|
+
}
|
|
61542
|
+
}
|
|
61543
|
+
if (VIOLATION_PATTERNS.RESERVATION_TOOLS.includes(toolName)) {
|
|
61544
|
+
const paths = toolArgs.paths || [];
|
|
61545
|
+
const payload = { tool: toolName, paths };
|
|
61546
|
+
captureCoordinatorEvent({
|
|
61547
|
+
session_id: sessionId,
|
|
61548
|
+
epic_id: epicId,
|
|
61549
|
+
timestamp: new Date().toISOString(),
|
|
61550
|
+
event_type: "VIOLATION",
|
|
61551
|
+
violation_type: "coordinator_reserved_files",
|
|
61552
|
+
payload
|
|
61553
|
+
});
|
|
61554
|
+
return {
|
|
61555
|
+
isViolation: true,
|
|
61556
|
+
violationType: "coordinator_reserved_files",
|
|
61557
|
+
message: `⚠️ Coordinator should not reserve files. Workers reserve files before editing to prevent conflicts.`,
|
|
61558
|
+
payload
|
|
61559
|
+
};
|
|
61560
|
+
}
|
|
61561
|
+
if (toolName === "hive_create_epic" && checkNoSpawn) {
|
|
61562
|
+
const epicTitle = toolArgs.epic_title || "";
|
|
61563
|
+
const subtasks = toolArgs.subtasks || [];
|
|
61564
|
+
const payload = { epic_title: epicTitle, subtask_count: subtasks.length };
|
|
61565
|
+
captureCoordinatorEvent({
|
|
61566
|
+
session_id: sessionId,
|
|
61567
|
+
epic_id: epicId,
|
|
61568
|
+
timestamp: new Date().toISOString(),
|
|
61569
|
+
event_type: "VIOLATION",
|
|
61570
|
+
violation_type: "no_worker_spawned",
|
|
61571
|
+
payload
|
|
61572
|
+
});
|
|
61573
|
+
return {
|
|
61574
|
+
isViolation: true,
|
|
61575
|
+
violationType: "no_worker_spawned",
|
|
61576
|
+
message: `⚠️ Coordinator created decomposition without spawning workers. After hive_create_epic, use swarm_spawn_subtask for each task.`,
|
|
61577
|
+
payload
|
|
61578
|
+
};
|
|
61579
|
+
}
|
|
61580
|
+
if (toolName === "swarm_complete" || toolName === "hive_close") {
|
|
61581
|
+
const payload = { tool: toolName };
|
|
61582
|
+
captureCoordinatorEvent({
|
|
61583
|
+
session_id: sessionId,
|
|
61584
|
+
epic_id: epicId,
|
|
61585
|
+
timestamp: new Date().toISOString(),
|
|
61586
|
+
event_type: "VIOLATION",
|
|
61587
|
+
violation_type: "worker_completed_without_review",
|
|
61588
|
+
payload
|
|
61589
|
+
});
|
|
61590
|
+
return {
|
|
61591
|
+
isViolation: true,
|
|
61592
|
+
violationType: "worker_completed_without_review",
|
|
61593
|
+
message: `⚠️ Coordinator should not complete worker tasks directly. Coordinators should review worker output using swarm_review and swarm_review_feedback.`,
|
|
61594
|
+
payload
|
|
61595
|
+
};
|
|
61596
|
+
}
|
|
61597
|
+
return { isViolation: false };
|
|
61598
|
+
}
|
|
61599
|
+
var coordinatorContexts = new Map;
|
|
61600
|
+
var globalCoordinatorContext = {
|
|
61601
|
+
isCoordinator: false
|
|
61602
|
+
};
|
|
61603
|
+
function setCoordinatorContext(ctx) {
|
|
61604
|
+
const sessionId = ctx.sessionId;
|
|
61605
|
+
if (sessionId) {
|
|
61606
|
+
const existing = coordinatorContexts.get(sessionId) || { isCoordinator: false };
|
|
61607
|
+
coordinatorContexts.set(sessionId, {
|
|
61608
|
+
...existing,
|
|
61609
|
+
...ctx,
|
|
61610
|
+
activatedAt: ctx.isCoordinator ? Date.now() : existing.activatedAt
|
|
61611
|
+
});
|
|
61612
|
+
} else {
|
|
61613
|
+
globalCoordinatorContext = {
|
|
61614
|
+
...globalCoordinatorContext,
|
|
61615
|
+
...ctx,
|
|
61616
|
+
activatedAt: ctx.isCoordinator ? Date.now() : globalCoordinatorContext.activatedAt
|
|
61617
|
+
};
|
|
61618
|
+
}
|
|
61619
|
+
}
|
|
61620
|
+
function getCoordinatorContext(sessionId) {
|
|
61621
|
+
if (sessionId) {
|
|
61622
|
+
return { ...coordinatorContexts.get(sessionId) || { isCoordinator: false } };
|
|
61623
|
+
}
|
|
61624
|
+
return { ...globalCoordinatorContext };
|
|
61625
|
+
}
|
|
61626
|
+
function clearCoordinatorContext(sessionId) {
|
|
61627
|
+
if (sessionId) {
|
|
61628
|
+
coordinatorContexts.delete(sessionId);
|
|
61629
|
+
} else {
|
|
61630
|
+
globalCoordinatorContext = {
|
|
61631
|
+
isCoordinator: false
|
|
61632
|
+
};
|
|
61633
|
+
}
|
|
61634
|
+
}
|
|
61635
|
+
function isInCoordinatorContext(sessionId) {
|
|
61636
|
+
const ctx = sessionId ? coordinatorContexts.get(sessionId) : globalCoordinatorContext;
|
|
61637
|
+
if (!ctx || !ctx.isCoordinator) {
|
|
61638
|
+
return false;
|
|
61639
|
+
}
|
|
61640
|
+
const COORDINATOR_TIMEOUT_MS = 4 * 60 * 60 * 1000;
|
|
61641
|
+
if (ctx.activatedAt) {
|
|
61642
|
+
const elapsed = Date.now() - ctx.activatedAt;
|
|
61643
|
+
if (elapsed > COORDINATOR_TIMEOUT_MS) {
|
|
61644
|
+
if (sessionId) {
|
|
61645
|
+
coordinatorContexts.delete(sessionId);
|
|
61646
|
+
} else {
|
|
61647
|
+
globalCoordinatorContext = { isCoordinator: false };
|
|
61648
|
+
}
|
|
61649
|
+
return false;
|
|
61650
|
+
}
|
|
61651
|
+
}
|
|
61652
|
+
return true;
|
|
61653
|
+
}
|
|
61654
|
+
|
|
61655
|
+
// src/swarm-mail.ts
|
|
61330
61656
|
import {
|
|
61331
61657
|
existsSync as existsSync5,
|
|
61332
61658
|
mkdirSync as mkdirSync4,
|
|
@@ -61382,6 +61708,21 @@ function clearSessionState(sessionID) {
|
|
|
61382
61708
|
}
|
|
61383
61709
|
} catch {}
|
|
61384
61710
|
}
|
|
61711
|
+
function hasCoordinatorOverride(sessionID) {
|
|
61712
|
+
return isInCoordinatorContext(sessionID) || isInCoordinatorContext();
|
|
61713
|
+
}
|
|
61714
|
+
function formatCoordinatorOverrideError(params) {
|
|
61715
|
+
return JSON.stringify({
|
|
61716
|
+
error: "Coordinator-only override. Ask the coordinator to use this tool for stale or orphaned reservations.",
|
|
61717
|
+
guard: "coordinator_only",
|
|
61718
|
+
required_context: "coordinator",
|
|
61719
|
+
tool: params.tool,
|
|
61720
|
+
agent_name: params.state.agentName,
|
|
61721
|
+
project_key: params.state.projectKey,
|
|
61722
|
+
session_id: params.sessionID,
|
|
61723
|
+
suggestion: "If reservations are stale, notify the coordinator via swarmmail_send before releasing."
|
|
61724
|
+
}, null, 2);
|
|
61725
|
+
}
|
|
61385
61726
|
var swarmmail_init = tool({
|
|
61386
61727
|
description: "Initialize Swarm Mail session. Creates agent identity and registers with the embedded event store.",
|
|
61387
61728
|
args: {
|
|
@@ -61636,6 +61977,13 @@ var swarmmail_release_all = tool({
|
|
|
61636
61977
|
if (!state) {
|
|
61637
61978
|
return JSON.stringify({ error: "Session not initialized. Call swarmmail_init first." }, null, 2);
|
|
61638
61979
|
}
|
|
61980
|
+
if (!hasCoordinatorOverride(sessionID)) {
|
|
61981
|
+
return formatCoordinatorOverrideError({
|
|
61982
|
+
tool: "swarmmail_release_all",
|
|
61983
|
+
state,
|
|
61984
|
+
sessionID
|
|
61985
|
+
});
|
|
61986
|
+
}
|
|
61639
61987
|
try {
|
|
61640
61988
|
const result = await releaseAllSwarmFiles({
|
|
61641
61989
|
projectPath: state.projectKey,
|
|
@@ -61666,6 +62014,13 @@ var swarmmail_release_agent = tool({
|
|
|
61666
62014
|
if (!state) {
|
|
61667
62015
|
return JSON.stringify({ error: "Session not initialized. Call swarmmail_init first." }, null, 2);
|
|
61668
62016
|
}
|
|
62017
|
+
if (!hasCoordinatorOverride(sessionID)) {
|
|
62018
|
+
return formatCoordinatorOverrideError({
|
|
62019
|
+
tool: "swarmmail_release_agent",
|
|
62020
|
+
state,
|
|
62021
|
+
sessionID
|
|
62022
|
+
});
|
|
62023
|
+
}
|
|
61669
62024
|
try {
|
|
61670
62025
|
const result = await releaseSwarmFilesForAgent({
|
|
61671
62026
|
projectPath: state.projectKey,
|
|
@@ -68015,7 +68370,8 @@ var swarm_spawn_subtask = tool({
|
|
|
68015
68370
|
files: args2.files,
|
|
68016
68371
|
shared_context: args2.shared_context,
|
|
68017
68372
|
project_path: args2.project_path,
|
|
68018
|
-
recovery_context: args2.recovery_context
|
|
68373
|
+
recovery_context: args2.recovery_context,
|
|
68374
|
+
model: args2.model
|
|
68019
68375
|
});
|
|
68020
68376
|
const { selectWorkerModel: selectWorkerModel2 } = await Promise.resolve().then(() => exports_model_selection);
|
|
68021
68377
|
const subtask = {
|
|
@@ -70779,258 +71135,6 @@ function createMetrics(result, toolName) {
|
|
|
70779
71135
|
};
|
|
70780
71136
|
}
|
|
70781
71137
|
|
|
70782
|
-
// src/planning-guardrails.ts
|
|
70783
|
-
init_eval_capture();
|
|
70784
|
-
var FILE_MODIFICATION_PATTERNS = [
|
|
70785
|
-
/\bimplement\b/i,
|
|
70786
|
-
/\bcreate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
70787
|
-
/\badd\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
70788
|
-
/\bupdate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
70789
|
-
/\bmodify\b/i,
|
|
70790
|
-
/\brefactor\b/i,
|
|
70791
|
-
/\bextract\b/i,
|
|
70792
|
-
/\bmigrate\b/i,
|
|
70793
|
-
/\bconvert\b/i,
|
|
70794
|
-
/\brewrite\b/i,
|
|
70795
|
-
/\bfix\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
70796
|
-
/\bwrite\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
70797
|
-
/src\//i,
|
|
70798
|
-
/lib\//i,
|
|
70799
|
-
/packages?\//i,
|
|
70800
|
-
/components?\//i
|
|
70801
|
-
];
|
|
70802
|
-
var TRACKING_PATTERNS = [
|
|
70803
|
-
/\breview\b/i,
|
|
70804
|
-
/\bcheck\b/i,
|
|
70805
|
-
/\bverify\b/i,
|
|
70806
|
-
/\btest\b.*pass/i,
|
|
70807
|
-
/\brun\b.*test/i,
|
|
70808
|
-
/\bdeploy\b/i,
|
|
70809
|
-
/\bmerge\b/i,
|
|
70810
|
-
/\bpr\b/i,
|
|
70811
|
-
/\bpush\b/i,
|
|
70812
|
-
/\bcommit\b/i
|
|
70813
|
-
];
|
|
70814
|
-
function analyzeTodoWrite(args2) {
|
|
70815
|
-
const todos = args2.todos;
|
|
70816
|
-
if (!todos || !Array.isArray(todos) || todos.length < 6) {
|
|
70817
|
-
return {
|
|
70818
|
-
looksLikeParallelWork: false,
|
|
70819
|
-
fileModificationCount: 0,
|
|
70820
|
-
totalCount: todos?.length ?? 0
|
|
70821
|
-
};
|
|
70822
|
-
}
|
|
70823
|
-
let fileModificationCount = 0;
|
|
70824
|
-
for (const todo of todos) {
|
|
70825
|
-
if (typeof todo !== "object" || todo === null)
|
|
70826
|
-
continue;
|
|
70827
|
-
const content = todo.content ?? "";
|
|
70828
|
-
const isFileModification = FILE_MODIFICATION_PATTERNS.some((pattern2) => pattern2.test(content));
|
|
70829
|
-
const isTracking = TRACKING_PATTERNS.some((pattern2) => pattern2.test(content));
|
|
70830
|
-
if (isFileModification && !isTracking) {
|
|
70831
|
-
fileModificationCount++;
|
|
70832
|
-
}
|
|
70833
|
-
}
|
|
70834
|
-
const ratio = fileModificationCount / todos.length;
|
|
70835
|
-
const looksLikeParallelWork = ratio >= 0.5 && fileModificationCount >= 4;
|
|
70836
|
-
if (looksLikeParallelWork) {
|
|
70837
|
-
return {
|
|
70838
|
-
looksLikeParallelWork: true,
|
|
70839
|
-
fileModificationCount,
|
|
70840
|
-
totalCount: todos.length,
|
|
70841
|
-
warning: `⚠️ This looks like a multi-file implementation plan (${fileModificationCount}/${todos.length} items are file modifications).
|
|
70842
|
-
|
|
70843
|
-
Consider using swarm instead:
|
|
70844
|
-
swarm_decompose → hive_create_epic → parallel task spawns
|
|
70845
|
-
|
|
70846
|
-
TodoWrite is for tracking progress, not parallelizable implementation work.
|
|
70847
|
-
Swarm workers can complete these ${fileModificationCount} tasks in parallel.
|
|
70848
|
-
|
|
70849
|
-
(Continuing with todowrite - this is just a suggestion)`
|
|
70850
|
-
};
|
|
70851
|
-
}
|
|
70852
|
-
return {
|
|
70853
|
-
looksLikeParallelWork: false,
|
|
70854
|
-
fileModificationCount,
|
|
70855
|
-
totalCount: todos.length
|
|
70856
|
-
};
|
|
70857
|
-
}
|
|
70858
|
-
function shouldAnalyzeTool(toolName) {
|
|
70859
|
-
return toolName === "todowrite" || toolName === "TodoWrite";
|
|
70860
|
-
}
|
|
70861
|
-
var VIOLATION_PATTERNS = {
|
|
70862
|
-
FILE_MODIFICATION_TOOLS: ["edit", "write"],
|
|
70863
|
-
RESERVATION_TOOLS: ["swarmmail_reserve", "agentmail_reserve"],
|
|
70864
|
-
TEST_EXECUTION_PATTERNS: [
|
|
70865
|
-
/\bbun\s+test\b/i,
|
|
70866
|
-
/\bnpm\s+(run\s+)?test/i,
|
|
70867
|
-
/\byarn\s+(run\s+)?test/i,
|
|
70868
|
-
/\bpnpm\s+(run\s+)?test/i,
|
|
70869
|
-
/\bjest\b/i,
|
|
70870
|
-
/\bvitest\b/i,
|
|
70871
|
-
/\bmocha\b/i,
|
|
70872
|
-
/\bava\b/i,
|
|
70873
|
-
/\btape\b/i,
|
|
70874
|
-
/\.test\.(ts|js|tsx|jsx)\b/i,
|
|
70875
|
-
/\.spec\.(ts|js|tsx|jsx)\b/i
|
|
70876
|
-
]
|
|
70877
|
-
};
|
|
70878
|
-
function detectCoordinatorViolation(params) {
|
|
70879
|
-
const { sessionId, epicId, toolName, toolArgs, agentContext, checkNoSpawn = false } = params;
|
|
70880
|
-
if (agentContext !== "coordinator") {
|
|
70881
|
-
return { isViolation: false };
|
|
70882
|
-
}
|
|
70883
|
-
if (VIOLATION_PATTERNS.FILE_MODIFICATION_TOOLS.includes(toolName)) {
|
|
70884
|
-
const file2 = toolArgs.filePath || "";
|
|
70885
|
-
const payload = { tool: toolName, file: file2 };
|
|
70886
|
-
captureCoordinatorEvent({
|
|
70887
|
-
session_id: sessionId,
|
|
70888
|
-
epic_id: epicId,
|
|
70889
|
-
timestamp: new Date().toISOString(),
|
|
70890
|
-
event_type: "VIOLATION",
|
|
70891
|
-
violation_type: "coordinator_edited_file",
|
|
70892
|
-
payload
|
|
70893
|
-
});
|
|
70894
|
-
return {
|
|
70895
|
-
isViolation: true,
|
|
70896
|
-
violationType: "coordinator_edited_file",
|
|
70897
|
-
message: `⚠️ Coordinator should not edit files directly. Coordinators should spawn workers to implement changes.`,
|
|
70898
|
-
payload
|
|
70899
|
-
};
|
|
70900
|
-
}
|
|
70901
|
-
if (toolName === "bash") {
|
|
70902
|
-
const command = toolArgs.command || "";
|
|
70903
|
-
const isTestCommand = VIOLATION_PATTERNS.TEST_EXECUTION_PATTERNS.some((pattern2) => pattern2.test(command));
|
|
70904
|
-
if (isTestCommand) {
|
|
70905
|
-
const payload = { tool: toolName, command };
|
|
70906
|
-
captureCoordinatorEvent({
|
|
70907
|
-
session_id: sessionId,
|
|
70908
|
-
epic_id: epicId,
|
|
70909
|
-
timestamp: new Date().toISOString(),
|
|
70910
|
-
event_type: "VIOLATION",
|
|
70911
|
-
violation_type: "coordinator_ran_tests",
|
|
70912
|
-
payload
|
|
70913
|
-
});
|
|
70914
|
-
return {
|
|
70915
|
-
isViolation: true,
|
|
70916
|
-
violationType: "coordinator_ran_tests",
|
|
70917
|
-
message: `⚠️ Coordinator should not run tests directly. Workers run tests as part of their implementation verification.`,
|
|
70918
|
-
payload
|
|
70919
|
-
};
|
|
70920
|
-
}
|
|
70921
|
-
}
|
|
70922
|
-
if (VIOLATION_PATTERNS.RESERVATION_TOOLS.includes(toolName)) {
|
|
70923
|
-
const paths = toolArgs.paths || [];
|
|
70924
|
-
const payload = { tool: toolName, paths };
|
|
70925
|
-
captureCoordinatorEvent({
|
|
70926
|
-
session_id: sessionId,
|
|
70927
|
-
epic_id: epicId,
|
|
70928
|
-
timestamp: new Date().toISOString(),
|
|
70929
|
-
event_type: "VIOLATION",
|
|
70930
|
-
violation_type: "coordinator_reserved_files",
|
|
70931
|
-
payload
|
|
70932
|
-
});
|
|
70933
|
-
return {
|
|
70934
|
-
isViolation: true,
|
|
70935
|
-
violationType: "coordinator_reserved_files",
|
|
70936
|
-
message: `⚠️ Coordinator should not reserve files. Workers reserve files before editing to prevent conflicts.`,
|
|
70937
|
-
payload
|
|
70938
|
-
};
|
|
70939
|
-
}
|
|
70940
|
-
if (toolName === "hive_create_epic" && checkNoSpawn) {
|
|
70941
|
-
const epicTitle = toolArgs.epic_title || "";
|
|
70942
|
-
const subtasks = toolArgs.subtasks || [];
|
|
70943
|
-
const payload = { epic_title: epicTitle, subtask_count: subtasks.length };
|
|
70944
|
-
captureCoordinatorEvent({
|
|
70945
|
-
session_id: sessionId,
|
|
70946
|
-
epic_id: epicId,
|
|
70947
|
-
timestamp: new Date().toISOString(),
|
|
70948
|
-
event_type: "VIOLATION",
|
|
70949
|
-
violation_type: "no_worker_spawned",
|
|
70950
|
-
payload
|
|
70951
|
-
});
|
|
70952
|
-
return {
|
|
70953
|
-
isViolation: true,
|
|
70954
|
-
violationType: "no_worker_spawned",
|
|
70955
|
-
message: `⚠️ Coordinator created decomposition without spawning workers. After hive_create_epic, use swarm_spawn_subtask for each task.`,
|
|
70956
|
-
payload
|
|
70957
|
-
};
|
|
70958
|
-
}
|
|
70959
|
-
if (toolName === "swarm_complete" || toolName === "hive_close") {
|
|
70960
|
-
const payload = { tool: toolName };
|
|
70961
|
-
captureCoordinatorEvent({
|
|
70962
|
-
session_id: sessionId,
|
|
70963
|
-
epic_id: epicId,
|
|
70964
|
-
timestamp: new Date().toISOString(),
|
|
70965
|
-
event_type: "VIOLATION",
|
|
70966
|
-
violation_type: "worker_completed_without_review",
|
|
70967
|
-
payload
|
|
70968
|
-
});
|
|
70969
|
-
return {
|
|
70970
|
-
isViolation: true,
|
|
70971
|
-
violationType: "worker_completed_without_review",
|
|
70972
|
-
message: `⚠️ Coordinator should not complete worker tasks directly. Coordinators should review worker output using swarm_review and swarm_review_feedback.`,
|
|
70973
|
-
payload
|
|
70974
|
-
};
|
|
70975
|
-
}
|
|
70976
|
-
return { isViolation: false };
|
|
70977
|
-
}
|
|
70978
|
-
var coordinatorContexts = new Map;
|
|
70979
|
-
var globalCoordinatorContext = {
|
|
70980
|
-
isCoordinator: false
|
|
70981
|
-
};
|
|
70982
|
-
function setCoordinatorContext(ctx) {
|
|
70983
|
-
const sessionId = ctx.sessionId;
|
|
70984
|
-
if (sessionId) {
|
|
70985
|
-
const existing = coordinatorContexts.get(sessionId) || { isCoordinator: false };
|
|
70986
|
-
coordinatorContexts.set(sessionId, {
|
|
70987
|
-
...existing,
|
|
70988
|
-
...ctx,
|
|
70989
|
-
activatedAt: ctx.isCoordinator ? Date.now() : existing.activatedAt
|
|
70990
|
-
});
|
|
70991
|
-
} else {
|
|
70992
|
-
globalCoordinatorContext = {
|
|
70993
|
-
...globalCoordinatorContext,
|
|
70994
|
-
...ctx,
|
|
70995
|
-
activatedAt: ctx.isCoordinator ? Date.now() : globalCoordinatorContext.activatedAt
|
|
70996
|
-
};
|
|
70997
|
-
}
|
|
70998
|
-
}
|
|
70999
|
-
function getCoordinatorContext(sessionId) {
|
|
71000
|
-
if (sessionId) {
|
|
71001
|
-
return { ...coordinatorContexts.get(sessionId) || { isCoordinator: false } };
|
|
71002
|
-
}
|
|
71003
|
-
return { ...globalCoordinatorContext };
|
|
71004
|
-
}
|
|
71005
|
-
function clearCoordinatorContext(sessionId) {
|
|
71006
|
-
if (sessionId) {
|
|
71007
|
-
coordinatorContexts.delete(sessionId);
|
|
71008
|
-
} else {
|
|
71009
|
-
globalCoordinatorContext = {
|
|
71010
|
-
isCoordinator: false
|
|
71011
|
-
};
|
|
71012
|
-
}
|
|
71013
|
-
}
|
|
71014
|
-
function isInCoordinatorContext(sessionId) {
|
|
71015
|
-
const ctx = sessionId ? coordinatorContexts.get(sessionId) : globalCoordinatorContext;
|
|
71016
|
-
if (!ctx || !ctx.isCoordinator) {
|
|
71017
|
-
return false;
|
|
71018
|
-
}
|
|
71019
|
-
const COORDINATOR_TIMEOUT_MS = 4 * 60 * 60 * 1000;
|
|
71020
|
-
if (ctx.activatedAt) {
|
|
71021
|
-
const elapsed = Date.now() - ctx.activatedAt;
|
|
71022
|
-
if (elapsed > COORDINATOR_TIMEOUT_MS) {
|
|
71023
|
-
if (sessionId) {
|
|
71024
|
-
coordinatorContexts.delete(sessionId);
|
|
71025
|
-
} else {
|
|
71026
|
-
globalCoordinatorContext = { isCoordinator: false };
|
|
71027
|
-
}
|
|
71028
|
-
return false;
|
|
71029
|
-
}
|
|
71030
|
-
}
|
|
71031
|
-
return true;
|
|
71032
|
-
}
|
|
71033
|
-
|
|
71034
71138
|
// src/coordinator-guard.ts
|
|
71035
71139
|
class CoordinatorGuardError extends Error {
|
|
71036
71140
|
violationType;
|
|
@@ -71298,6 +71402,7 @@ var logger = getLogger();
|
|
|
71298
71402
|
|
|
71299
71403
|
// src/compaction-hook.ts
|
|
71300
71404
|
init_eval_capture();
|
|
71405
|
+
init_skills();
|
|
71301
71406
|
var _logger;
|
|
71302
71407
|
function getLog() {
|
|
71303
71408
|
if (!_logger) {
|
|
@@ -71319,6 +71424,9 @@ Context was compacted but the swarm is still running. **YOU ARE THE COORDINATOR.
|
|
|
71319
71424
|
|
|
71320
71425
|
Your role is ORCHESTRATION, not implementation. The resume steps above (if present) tell you exactly what to do first.
|
|
71321
71426
|
|
|
71427
|
+
## \uD83D\uDD27 ALWAYS-ON GUIDANCE
|
|
71428
|
+
${getAlwaysOnGuidanceSkill({ role: "coordinator" })}
|
|
71429
|
+
|
|
71322
71430
|
---
|
|
71323
71431
|
|
|
71324
71432
|
## \uD83C\uDFAF WHAT GOOD LOOKS LIKE (Behavioral Examples)
|
|
@@ -71375,10 +71483,12 @@ You are the **COORDINATOR**. Your job is ORCHESTRATION, not implementation.
|
|
|
71375
71483
|
### What Coordinators Do:
|
|
71376
71484
|
- ✅ Spawn workers for implementation tasks
|
|
71377
71485
|
- ✅ Monitor worker progress via \`swarm_status\` and \`swarmmail_inbox\`
|
|
71486
|
+
- ✅ Use \`swarmmail_release_all\` to clear stale/orphaned reservations (coordinator override)
|
|
71378
71487
|
- ✅ Review completed work with \`swarm_review\`
|
|
71379
71488
|
- ✅ Unblock dependencies and resolve conflicts
|
|
71380
71489
|
- ✅ Close the loop when epics complete
|
|
71381
71490
|
|
|
71491
|
+
|
|
71382
71492
|
### What Coordinators NEVER Do:
|
|
71383
71493
|
- ❌ **NEVER** edit or write files directly
|
|
71384
71494
|
- ❌ **NEVER** run tests with \`bash\`
|