opencode-swarm 7.13.1 → 7.14.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/cli/index.js +144 -15
- package/dist/commands/deep-dive.d.ts +5 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/evidence-schema.d.ts +13 -13
- package/dist/config/schema.d.ts +4 -4
- package/dist/index.js +422 -123
- package/dist/tools/convene-council.d.ts +3 -3
- package/dist/tools/submit-phase-council-verdicts.d.ts +3 -3
- package/package.json +1 -1
- package/dist/__tests__/acknowledge-spec-drift.test.d.ts +0 -1
- package/dist/__tests__/cli-version.adversarial.test.d.ts +0 -1
- package/dist/__tests__/cli-version.test.d.ts +0 -1
- package/dist/__tests__/conflict-resolution.test.d.ts +0 -1
- package/dist/__tests__/convene-general-council.test.d.ts +0 -12
- package/dist/__tests__/critic_drift_verifier-whitelist.test.d.ts +0 -1
- package/dist/__tests__/critic_hallucination_verifier-whitelist.test.d.ts +0 -1
- package/dist/__tests__/disagreement-detector.test.d.ts +0 -7
- package/dist/__tests__/evidence-lock.adversarial.test.d.ts +0 -8
- package/dist/__tests__/evidence-lock.test.d.ts +0 -6
- package/dist/__tests__/gate-evidence.adversarial.test.d.ts +0 -7
- package/dist/__tests__/general-council-service.test.d.ts +0 -7
- package/dist/__tests__/lint-spec.test.d.ts +0 -1
- package/dist/__tests__/preflight-phase.test.d.ts +0 -1
- package/dist/__tests__/qa-gate-hardening.test.d.ts +0 -12
- package/dist/__tests__/req-coverage.test.d.ts +0 -1
- package/dist/__tests__/security-adversarial.test.d.ts +0 -1
- package/dist/__tests__/sounding-board-parser.test.d.ts +0 -1
- package/dist/__tests__/spec-hash.test.d.ts +0 -1
- package/dist/__tests__/spec-schema.test.d.ts +0 -1
- package/dist/__tests__/web-search-provider.test.d.ts +0 -6
- package/dist/__tests__/write-drift-evidence-requirement-coverage.test.d.ts +0 -4
- package/dist/adversarial-tests.test.d.ts +0 -1
- package/dist/agents/architect-permission.adversarial.test.d.ts +0 -5
- package/dist/agents/architect.commands-list.adversarial.test.d.ts +0 -1
- package/dist/agents/architect.commands-list.test.d.ts +0 -1
- package/dist/agents/architect.dark-matter.test.d.ts +0 -1
- package/dist/agents/architect.designer-gate.test.d.ts +0 -1
- package/dist/agents/architect.skip-aliases.test.d.ts +0 -1
- package/dist/agents/coder.test.d.ts +0 -1
- package/dist/agents/council-prompts.test.d.ts +0 -9
- package/dist/agents/council-registration.test.d.ts +0 -23
- package/dist/agents/explorer-consumer-contract.test.d.ts +0 -1
- package/dist/agents/explorer-role-boundary.test.d.ts +0 -1
- package/dist/agents/prompt-namespace.test.d.ts +0 -1
- package/dist/agents/reviewer.test.d.ts +0 -1
- package/dist/agents/test-engineer.adversarial.test.d.ts +0 -5
- package/dist/agents/test-engineer.security.test.d.ts +0 -1
- package/dist/background/trigger.vulnerability.test.d.ts +0 -1
- package/dist/commands/archive.error-handling.test.d.ts +0 -9
- package/dist/commands/benchmark.error-handling.test.d.ts +0 -7
- package/dist/commands/brainstorm.test.d.ts +0 -1
- package/dist/commands/clashes-with-native-cc.test.d.ts +0 -10
- package/dist/commands/command-adapters.security.test.d.ts +0 -14
- package/dist/commands/command-names.test.d.ts +0 -1
- package/dist/commands/commands.test.d.ts +0 -1
- package/dist/commands/conflict-registry.structural.test.d.ts +0 -1
- package/dist/commands/conflict-registry.test.d.ts +0 -5
- package/dist/commands/council.test.d.ts +0 -4
- package/dist/commands/curate.test.d.ts +0 -1
- package/dist/commands/dark-matter.error-handling.test.d.ts +0 -1
- package/dist/commands/first-run.test.d.ts +0 -11
- package/dist/commands/full-auto-config-guard.test.d.ts +0 -7
- package/dist/commands/full-auto-discoverability.test.d.ts +0 -8
- package/dist/commands/full-auto-registration.test.d.ts +0 -5
- package/dist/commands/full-auto-sessionid.test.d.ts +0 -5
- package/dist/commands/full-auto.regression.test.d.ts +0 -10
- package/dist/commands/full-auto.test.d.ts +0 -6
- package/dist/commands/handoff.error-handling.adversarial.test.d.ts +0 -1
- package/dist/commands/handoff.error-handling.test.d.ts +0 -1
- package/dist/commands/index.help-text.test.d.ts +0 -1
- package/dist/commands/index.not-found.adversarial.test.d.ts +0 -12
- package/dist/commands/index.not-found.test.d.ts +0 -11
- package/dist/commands/qa-gates.test.d.ts +0 -1
- package/dist/commands/registration-parity.test.d.ts +0 -1
- package/dist/commands/registry-documentation.test.d.ts +0 -1
- package/dist/commands/registry-type.test.d.ts +0 -1
- package/dist/commands/registry.find-similar.adversarial.test.d.ts +0 -1
- package/dist/commands/registry.find-similar.test.d.ts +0 -1
- package/dist/commands/registry.test.d.ts +0 -1
- package/dist/commands/shortcut-routing.test.d.ts +0 -11
- package/dist/commands/simulate.report-write.adversarial.test.d.ts +0 -1
- package/dist/commands/simulate.report-write.test.d.ts +0 -1
- package/dist/commands/turbo-registration.test.d.ts +0 -5
- package/dist/commands/turbo-sessionid.test.d.ts +0 -5
- package/dist/commands/turbo.regression.test.d.ts +0 -11
- package/dist/commands/turbo.test.d.ts +0 -5
- package/dist/config/constants.architect-whitelist.test.d.ts +0 -1
- package/dist/config/constants.security.test.d.ts +0 -1
- package/dist/council/__tests__/council-evidence-writer.adversarial.test.d.ts +0 -6
- package/dist/db/global-db.test.d.ts +0 -7
- package/dist/db/project-db.test.d.ts +0 -4
- package/dist/db/qa-gate-profile.test.d.ts +0 -4
- package/dist/diff/__tests__/semantic-classifier.test.d.ts +0 -1
- package/dist/diff/__tests__/summary-generator.test.d.ts +0 -1
- package/dist/gate-evidence.test.d.ts +0 -1
- package/dist/hooks/__tests__/repo-graph-builder.test.d.ts +0 -12
- package/dist/hooks/__tests__/semantic-diff-injection.test.d.ts +0 -1
- package/dist/hooks/agent-activity.test.d.ts +0 -1
- package/dist/hooks/cc-command-intercept.test.d.ts +0 -1
- package/dist/hooks/curator-drift-advisory.test.d.ts +0 -1
- package/dist/hooks/delegation-gate.evidence.test.d.ts +0 -4
- package/dist/hooks/delegation-gate.getEvidenceTaskId.test.d.ts +0 -20
- package/dist/hooks/delegation-gate.plan-fallback-security.test.d.ts +0 -13
- package/dist/hooks/delegation-gate.plan-fallback.test.d.ts +0 -5
- package/dist/hooks/delegation-gate.seed-state.test.d.ts +0 -1
- package/dist/hooks/delegation-gate.turbo-evidence.test.d.ts +0 -8
- package/dist/hooks/delegation-gate.verify.test.d.ts +0 -11
- package/dist/hooks/delegation-ledger.test.d.ts +0 -11
- package/dist/hooks/diff-scope.test.d.ts +0 -1
- package/dist/hooks/incremental-verify.test.d.ts +0 -1
- package/dist/hooks/loop-detector.test.d.ts +0 -1
- package/dist/hooks/scope-guard-throw-behavior.test.d.ts +0 -15
- package/dist/hooks/scope-guard.adversarial.test.d.ts +0 -1
- package/dist/hooks/scope-guard.test.d.ts +0 -14
- package/dist/hooks/self-review.test.d.ts +0 -14
- package/dist/hooks/slop-detector.adversarial.test.d.ts +0 -1
- package/dist/hooks/slop-detector.test.d.ts +0 -1
- package/dist/hooks/spawn-helper.test.d.ts +0 -1
- package/dist/hooks/watchdog.integration.test.d.ts +0 -9
- package/dist/index.adversarial-bootstrap.test.d.ts +0 -1
- package/dist/index.bootstrap-adversarial.test.d.ts +0 -1
- package/dist/index.bootstrap-directory.test.d.ts +0 -1
- package/dist/model-fallback.adversarial.test.d.ts +0 -22
- package/dist/model-fallback.test.d.ts +0 -12
- package/dist/mutation/__tests__/engine.adversarial.test.d.ts +0 -1
- package/dist/mutation/__tests__/engine.test.d.ts +0 -1
- package/dist/mutation/__tests__/equivalence.adversarial.test.d.ts +0 -1
- package/dist/mutation/__tests__/equivalence.test.d.ts +0 -1
- package/dist/mutation/__tests__/gate.adversarial.test.d.ts +0 -1
- package/dist/mutation/__tests__/gate.test.d.ts +0 -1
- package/dist/mutation/__tests__/generator.test.d.ts +0 -1
- package/dist/parallel/dispatcher/noop-dispatcher.test.d.ts +0 -10
- package/dist/plan/checkpoint.test.d.ts +0 -1
- package/dist/plan/ledger-integrity.test.d.ts +0 -5
- package/dist/plan/ledger-snapshot-adversarial.test.d.ts +0 -1
- package/dist/plan/ledger.test.d.ts +0 -1
- package/dist/plan/manager.cas-backoff.test.d.ts +0 -10
- package/dist/plan/manager.ledger-aware.test.d.ts +0 -1
- package/dist/plan/manager.loadplan-validation-guard.test.d.ts +0 -13
- package/dist/plan/manager.update-task-status.test.d.ts +0 -1
- package/dist/plan/migration-revert.regression.test.d.ts +0 -8
- package/dist/prm/__tests__/course-correction.test.d.ts +0 -1
- package/dist/prm/__tests__/escalation-queue-drain.test.d.ts +0 -1
- package/dist/prm/__tests__/escalation.test.d.ts +0 -1
- package/dist/prm/__tests__/index.test.d.ts +0 -1
- package/dist/prm/__tests__/integration.test.d.ts +0 -1
- package/dist/prm/__tests__/pattern-detector.test.d.ts +0 -5
- package/dist/prm/__tests__/replay.test.d.ts +0 -1
- package/dist/prm/__tests__/trajectory-store.test.d.ts +0 -7
- package/dist/sast/semgrep.test.d.ts +0 -1
- package/dist/scope/scope-persistence.test.d.ts +0 -13
- package/dist/services/compaction-service.test.d.ts +0 -1
- package/dist/services/config-doctor.security.test.d.ts +0 -1
- package/dist/services/config-doctor.test.d.ts +0 -1
- package/dist/services/status-service.turbo-indicator.test.d.ts +0 -5
- package/dist/services/tool-doctor.test.d.ts +0 -1
- package/dist/state.agent-run-context.test.d.ts +0 -10
- package/dist/state.rehydrate.test.d.ts +0 -1
- package/dist/state.rehydration-adversarial.test.d.ts +0 -1
- package/dist/state.rehydration-integration.test.d.ts +0 -1
- package/dist/state.session-restart.test.d.ts +0 -7
- package/dist/state.telemetry.test.d.ts +0 -1
- package/dist/telemetry.test.d.ts +0 -1
- package/dist/test-impact/__tests__/analyzer-import-fix.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/analyzer-import-fix.test.d.ts +0 -1
- package/dist/test-impact/__tests__/analyzer.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/analyzer.test.d.ts +0 -1
- package/dist/test-impact/__tests__/council-fixes.test.d.ts +0 -1
- package/dist/test-impact/__tests__/failure-classifier.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/failure-classifier.test.d.ts +0 -1
- package/dist/test-impact/__tests__/flaky-detector.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/flaky-detector.test.d.ts +0 -1
- package/dist/test-impact/__tests__/history-store.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/history-store.test.d.ts +0 -1
- package/dist/test-impact/__tests__/test-impact.adversarial.test.d.ts +0 -1
- package/dist/test-impact/__tests__/test-impact.test.d.ts +0 -1
- package/dist/tools/__tests__/barrel-exports.test.d.ts +0 -1
- package/dist/tools/__tests__/diff-ast-fallback.test.d.ts +0 -1
- package/dist/tools/__tests__/diff-markdown-summary.test.d.ts +0 -1
- package/dist/tools/__tests__/diff-semantic.test.d.ts +0 -1
- package/dist/tools/__tests__/diff-summary.adversarial.test.d.ts +0 -1
- package/dist/tools/__tests__/diff-summary.test.d.ts +0 -1
- package/dist/tools/__tests__/mutation-test.adversarial.test.d.ts +0 -1
- package/dist/tools/__tests__/mutation-test.sourcefiles.test.d.ts +0 -1
- package/dist/tools/__tests__/mutation-test.test.d.ts +0 -1
- package/dist/tools/__tests__/repo-graph-walk.test.d.ts +0 -16
- package/dist/tools/__tests__/test-runner-history.test.d.ts +0 -1
- package/dist/tools/__tests__/test-runner-impact.adversarial.test.d.ts +0 -1
- package/dist/tools/__tests__/test-runner-impact.test.d.ts +0 -1
- package/dist/tools/__tests__/test-runner-source-files.test.d.ts +0 -1
- package/dist/tools/barrel-export-check-gate-status.test.d.ts +0 -6
- package/dist/tools/batch-symbols.test.d.ts +0 -1
- package/dist/tools/check-gate-status.adversarial.test.d.ts +0 -1
- package/dist/tools/check-gate-status.gates.test.d.ts +0 -1
- package/dist/tools/check-gate-status.plugin-registration.test.d.ts +0 -1
- package/dist/tools/curator-analyze.test.d.ts +0 -1
- package/dist/tools/knowledge-tools.integration.test.d.ts +0 -1
- package/dist/tools/mutation-test.security.test.d.ts +0 -1
- package/dist/tools/plugin-registration-adversarial.test.d.ts +0 -1
- package/dist/tools/resolve-working-directory.test.d.ts +0 -1
- package/dist/tools/save-plan.subdirectory-rejection.test.d.ts +0 -1
- package/dist/tools/search.adversarial.test.d.ts +0 -1
- package/dist/tools/search.test.d.ts +0 -1
- package/dist/tools/suggest-patch.adversarial.test.d.ts +0 -1
- package/dist/tools/suggest-patch.test.d.ts +0 -1
- package/dist/tools/test-runner.security-adversarial.test.d.ts +0 -5
- package/dist/tools/update-task-status.adversarial.test.d.ts +0 -13
- package/dist/tools/update-task-status.gates.test.d.ts +0 -1
- package/dist/tools/update-task-status.test.d.ts +0 -1
- package/dist/tools/update-task-status.turbo-bypass.test.d.ts +0 -1
- package/dist/tools/verify-six-tools-registration.test.d.ts +0 -9
- package/dist/tools/write-mutation-evidence.test.d.ts +0 -1
- package/dist/transient-retry.test.d.ts +0 -10
- package/dist/utils/__tests__/bun-compat.test.d.ts +0 -11
- package/dist/utils/__tests__/timeout.test.d.ts +0 -12
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.
|
|
36
|
+
version: "7.14.0",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -46041,6 +46041,118 @@ var init_dark_matter = __esm(() => {
|
|
|
46041
46041
|
init_co_change_analyzer();
|
|
46042
46042
|
});
|
|
46043
46043
|
|
|
46044
|
+
// src/commands/deep-dive.ts
|
|
46045
|
+
function sanitizeScope(raw) {
|
|
46046
|
+
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
46047
|
+
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
46048
|
+
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
46049
|
+
if (normalized.length <= MAX_SCOPE_LEN)
|
|
46050
|
+
return normalized;
|
|
46051
|
+
return `${normalized.slice(0, MAX_SCOPE_LEN)}…`;
|
|
46052
|
+
}
|
|
46053
|
+
function isValidPositiveInteger(raw) {
|
|
46054
|
+
if (!raw || !/^\d+$/.test(raw))
|
|
46055
|
+
return false;
|
|
46056
|
+
const n = Number(raw);
|
|
46057
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0)
|
|
46058
|
+
return false;
|
|
46059
|
+
return true;
|
|
46060
|
+
}
|
|
46061
|
+
function parseArgs2(args2) {
|
|
46062
|
+
const result = {
|
|
46063
|
+
profile: DEFAULT_PROFILE,
|
|
46064
|
+
maxExplorers: DEFAULT_MAX_EXPLORERS,
|
|
46065
|
+
output: "markdown",
|
|
46066
|
+
updateMain: true,
|
|
46067
|
+
allowDirty: false,
|
|
46068
|
+
rest: []
|
|
46069
|
+
};
|
|
46070
|
+
let i2 = 0;
|
|
46071
|
+
while (i2 < args2.length) {
|
|
46072
|
+
const token = args2[i2];
|
|
46073
|
+
if (token === "--profile") {
|
|
46074
|
+
if (i2 + 1 >= args2.length) {
|
|
46075
|
+
return { ...result, error: `Flag "${token}" requires a value` };
|
|
46076
|
+
}
|
|
46077
|
+
const value = args2[++i2];
|
|
46078
|
+
if (!PROFILES.has(value)) {
|
|
46079
|
+
return {
|
|
46080
|
+
...result,
|
|
46081
|
+
error: `Invalid profile "${value}". Must be one of: standard, security, ux, architecture, full.`
|
|
46082
|
+
};
|
|
46083
|
+
}
|
|
46084
|
+
result.profile = value;
|
|
46085
|
+
} else if (token === "--max-explorers") {
|
|
46086
|
+
if (i2 + 1 >= args2.length) {
|
|
46087
|
+
return { ...result, error: `Flag "${token}" requires a value` };
|
|
46088
|
+
}
|
|
46089
|
+
const value = args2[++i2];
|
|
46090
|
+
if (!isValidPositiveInteger(value) || value.includes(".") || value.startsWith("0x") || value.startsWith("0X") || Number(value) < 1 || Number(value) > 8) {
|
|
46091
|
+
return {
|
|
46092
|
+
...result,
|
|
46093
|
+
error: `Invalid --max-explorers value "${value}". Must be an integer between 1 and 8.`
|
|
46094
|
+
};
|
|
46095
|
+
}
|
|
46096
|
+
result.maxExplorers = Number(value);
|
|
46097
|
+
result.maxExplorersExplicit = true;
|
|
46098
|
+
} else if (token === "--json") {
|
|
46099
|
+
result.output = "json";
|
|
46100
|
+
} else if (token === "--skip-update") {
|
|
46101
|
+
result.updateMain = false;
|
|
46102
|
+
} else if (token === "--allow-dirty") {
|
|
46103
|
+
result.allowDirty = true;
|
|
46104
|
+
} else if (token.startsWith("--")) {
|
|
46105
|
+
return { ...result, error: `Unknown flag "${token}"` };
|
|
46106
|
+
} else {
|
|
46107
|
+
result.rest.push(token);
|
|
46108
|
+
}
|
|
46109
|
+
i2++;
|
|
46110
|
+
}
|
|
46111
|
+
return result;
|
|
46112
|
+
}
|
|
46113
|
+
async function handleDeepDiveCommand(_directory, args2) {
|
|
46114
|
+
const parsed = parseArgs2(args2);
|
|
46115
|
+
if (parsed.error) {
|
|
46116
|
+
return `Error: ${parsed.error}
|
|
46117
|
+
|
|
46118
|
+
${USAGE2}`;
|
|
46119
|
+
}
|
|
46120
|
+
const scope = sanitizeScope(parsed.rest.join(" "));
|
|
46121
|
+
if (!scope) {
|
|
46122
|
+
return USAGE2;
|
|
46123
|
+
}
|
|
46124
|
+
if (parsed.profile === "full" && !parsed.maxExplorersExplicit) {
|
|
46125
|
+
parsed.maxExplorers = FULL_PROFILE_DEFAULT_MAX_EXPLORERS;
|
|
46126
|
+
}
|
|
46127
|
+
const header = `[MODE: DEEP_DIVE profile=${parsed.profile} max_explorers=${parsed.maxExplorers} output=${parsed.output} update_main=${parsed.updateMain} allow_dirty=${parsed.allowDirty}] ${scope}`;
|
|
46128
|
+
return header;
|
|
46129
|
+
}
|
|
46130
|
+
var MAX_SCOPE_LEN = 2000, PROFILES, DEFAULT_PROFILE = "standard", DEFAULT_MAX_EXPLORERS = 6, FULL_PROFILE_DEFAULT_MAX_EXPLORERS = 8, USAGE2 = `Usage: /swarm deep-dive <scope> [--profile standard|security|ux|architecture|full] [--max-explorers N] [--json] [--skip-update] [--allow-dirty]
|
|
46131
|
+
|
|
46132
|
+
Run a bounded, evidence-backed deep dive on an application section.
|
|
46133
|
+
|
|
46134
|
+
Examples:
|
|
46135
|
+
/swarm deep-dive auth
|
|
46136
|
+
/swarm deep dive src/commands --profile architecture
|
|
46137
|
+
/swarm deep-dive "settings page" --profile ux
|
|
46138
|
+
/swarm deep-dive src/security --profile security --max-explorers 5
|
|
46139
|
+
|
|
46140
|
+
Flags:
|
|
46141
|
+
--profile <name> standard, security, ux, architecture, or full
|
|
46142
|
+
--max-explorers <N> explorer runs per wave, 1..8
|
|
46143
|
+
--json include machine-readable JSON in the final report
|
|
46144
|
+
--skip-update skip the repo update-to-main preflight
|
|
46145
|
+
--allow-dirty allow audit to proceed with dirty worktree`;
|
|
46146
|
+
var init_deep_dive = __esm(() => {
|
|
46147
|
+
PROFILES = new Set([
|
|
46148
|
+
"standard",
|
|
46149
|
+
"security",
|
|
46150
|
+
"ux",
|
|
46151
|
+
"architecture",
|
|
46152
|
+
"full"
|
|
46153
|
+
]);
|
|
46154
|
+
});
|
|
46155
|
+
|
|
46044
46156
|
// src/config/cache-paths.ts
|
|
46045
46157
|
import * as os5 from "node:os";
|
|
46046
46158
|
import * as path25 from "node:path";
|
|
@@ -50995,7 +51107,7 @@ function validateAndSanitizeUrl(rawUrl) {
|
|
|
50995
51107
|
return { error: "Invalid URL format" };
|
|
50996
51108
|
}
|
|
50997
51109
|
}
|
|
50998
|
-
function
|
|
51110
|
+
function parseArgs3(args2) {
|
|
50999
51111
|
const out2 = {
|
|
51000
51112
|
plan: false,
|
|
51001
51113
|
trace: false,
|
|
@@ -51086,24 +51198,24 @@ function parseGitRemoteUrl(remoteUrl) {
|
|
|
51086
51198
|
return null;
|
|
51087
51199
|
}
|
|
51088
51200
|
function handleIssueCommand(_directory, args2) {
|
|
51089
|
-
const parsed =
|
|
51201
|
+
const parsed = parseArgs3(args2);
|
|
51090
51202
|
const rawInput = parsed.rest.join(" ").trim();
|
|
51091
51203
|
if (!rawInput) {
|
|
51092
|
-
return
|
|
51204
|
+
return USAGE3;
|
|
51093
51205
|
}
|
|
51094
51206
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
51095
51207
|
const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput);
|
|
51096
51208
|
if (!issueInfo) {
|
|
51097
51209
|
return `Error: Could not parse issue reference from "${rawInput}"
|
|
51098
51210
|
|
|
51099
|
-
${
|
|
51211
|
+
${USAGE3}`;
|
|
51100
51212
|
}
|
|
51101
51213
|
const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
|
|
51102
51214
|
const result = validateAndSanitizeUrl(issueUrl);
|
|
51103
51215
|
if ("error" in result) {
|
|
51104
51216
|
return `Error: ${result.error}
|
|
51105
51217
|
|
|
51106
|
-
${
|
|
51218
|
+
${USAGE3}`;
|
|
51107
51219
|
}
|
|
51108
51220
|
const flags2 = [];
|
|
51109
51221
|
if (parsed.plan)
|
|
@@ -51115,9 +51227,9 @@ ${USAGE2}`;
|
|
|
51115
51227
|
const flagsStr = flags2.length > 0 ? ` ${flags2.join(" ")}` : "";
|
|
51116
51228
|
return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
|
|
51117
51229
|
}
|
|
51118
|
-
var MAX_URL_LEN = 2048,
|
|
51230
|
+
var MAX_URL_LEN = 2048, USAGE3;
|
|
51119
51231
|
var init_issue = __esm(() => {
|
|
51120
|
-
|
|
51232
|
+
USAGE3 = [
|
|
51121
51233
|
"Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
|
|
51122
51234
|
"",
|
|
51123
51235
|
"Ingest a GitHub issue into the swarm workflow.",
|
|
@@ -51734,7 +51846,7 @@ function validateAndSanitizeUrl2(rawUrl) {
|
|
|
51734
51846
|
return { error: "Invalid URL format" };
|
|
51735
51847
|
}
|
|
51736
51848
|
}
|
|
51737
|
-
function
|
|
51849
|
+
function parseArgs4(args2) {
|
|
51738
51850
|
const out2 = { council: false, rest: [] };
|
|
51739
51851
|
for (const token of args2) {
|
|
51740
51852
|
if (token === "--council") {
|
|
@@ -51818,31 +51930,31 @@ function parseGitRemoteUrl2(remoteUrl) {
|
|
|
51818
51930
|
return null;
|
|
51819
51931
|
}
|
|
51820
51932
|
function handlePrReviewCommand(_directory, args2) {
|
|
51821
|
-
const parsed =
|
|
51933
|
+
const parsed = parseArgs4(args2);
|
|
51822
51934
|
const rawInput = parsed.rest.join(" ").trim();
|
|
51823
51935
|
if (!rawInput) {
|
|
51824
|
-
return
|
|
51936
|
+
return USAGE4;
|
|
51825
51937
|
}
|
|
51826
51938
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
51827
51939
|
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
|
|
51828
51940
|
if (!prInfo) {
|
|
51829
51941
|
return `Error: Could not parse PR reference from "${rawInput}"
|
|
51830
51942
|
|
|
51831
|
-
${
|
|
51943
|
+
${USAGE4}`;
|
|
51832
51944
|
}
|
|
51833
51945
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
51834
51946
|
const result = validateAndSanitizeUrl2(prUrl);
|
|
51835
51947
|
if ("error" in result) {
|
|
51836
51948
|
return `Error: ${result.error}
|
|
51837
51949
|
|
|
51838
|
-
${
|
|
51950
|
+
${USAGE4}`;
|
|
51839
51951
|
}
|
|
51840
51952
|
const councilFlag = parsed.council ? "council=true" : "council=false";
|
|
51841
51953
|
return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
|
|
51842
51954
|
}
|
|
51843
|
-
var MAX_URL_LEN2 = 2048,
|
|
51955
|
+
var MAX_URL_LEN2 = 2048, USAGE4;
|
|
51844
51956
|
var init_pr_review = __esm(() => {
|
|
51845
|
-
|
|
51957
|
+
USAGE4 = [
|
|
51846
51958
|
"Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
|
|
51847
51959
|
"",
|
|
51848
51960
|
"Run a full swarm PR review on a GitHub pull request.",
|
|
@@ -57572,6 +57684,7 @@ __export(exports_commands, {
|
|
|
57572
57684
|
handleEvidenceCommand: () => handleEvidenceCommand,
|
|
57573
57685
|
handleDoctorCommand: () => handleDoctorCommand,
|
|
57574
57686
|
handleDiagnoseCommand: () => handleDiagnoseCommand,
|
|
57687
|
+
handleDeepDiveCommand: () => handleDeepDiveCommand,
|
|
57575
57688
|
handleDarkMatterCommand: () => handleDarkMatterCommand,
|
|
57576
57689
|
handleCurateCommand: () => handleCurateCommand,
|
|
57577
57690
|
handleCouncilCommand: () => handleCouncilCommand,
|
|
@@ -57775,6 +57888,7 @@ var init_commands = __esm(() => {
|
|
|
57775
57888
|
init_council();
|
|
57776
57889
|
init_curate();
|
|
57777
57890
|
init_dark_matter();
|
|
57891
|
+
init_deep_dive();
|
|
57778
57892
|
init_diagnose();
|
|
57779
57893
|
init_doctor();
|
|
57780
57894
|
init_evidence();
|
|
@@ -57992,6 +58106,7 @@ var init_registry = __esm(() => {
|
|
|
57992
58106
|
init_council();
|
|
57993
58107
|
init_curate();
|
|
57994
58108
|
init_dark_matter();
|
|
58109
|
+
init_deep_dive();
|
|
57995
58110
|
init_diagnose();
|
|
57996
58111
|
init_doctor();
|
|
57997
58112
|
init_evidence();
|
|
@@ -58271,6 +58386,20 @@ var init_registry = __esm(() => {
|
|
|
58271
58386
|
details: "Launches a structured PR review: reconstructs PR intent via obligation extraction cascade, runs 6 parallel explorer lanes (correctness, security, dependencies, docs-intent-vs-actual, tests, performance-architecture), validates findings through independent reviewer confirmation, applies critic challenge to HIGH/CRITICAL findings, synthesizes structured report. --council variant fires adversarial multi-model review. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolves against origin remote).",
|
|
58272
58387
|
category: "agent"
|
|
58273
58388
|
},
|
|
58389
|
+
"deep-dive": {
|
|
58390
|
+
handler: async (ctx) => handleDeepDiveCommand(ctx.directory, ctx.args),
|
|
58391
|
+
description: "Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",
|
|
58392
|
+
args: "<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",
|
|
58393
|
+
details: "Runs a read-only deep audit of the specified scope using parallel explorer waves (8-file cap per mission, ~3500 line guardrail), always 2 parallel reviewers for verification, and sequential critic challenge on HIGH/CRITICAL findings. Profiles select explorer lanes: standard (5 lanes), security, ux, architecture, full (all 8 lanes). Emits a structured findings report without mutating source code.",
|
|
58394
|
+
category: "agent"
|
|
58395
|
+
},
|
|
58396
|
+
"deep dive": {
|
|
58397
|
+
handler: async (ctx) => handleDeepDiveCommand(ctx.directory, ctx.args),
|
|
58398
|
+
description: "Alias for /swarm deep-dive — launch deep codebase audit",
|
|
58399
|
+
args: "<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",
|
|
58400
|
+
category: "agent",
|
|
58401
|
+
aliasOf: "deep-dive"
|
|
58402
|
+
},
|
|
58274
58403
|
issue: {
|
|
58275
58404
|
handler: async (ctx) => handleIssueCommand(ctx.directory, ctx.args),
|
|
58276
58405
|
description: "Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",
|
|
@@ -59767,7 +59896,130 @@ Do NOT share other agents' responses at this stage.
|
|
|
59767
59896
|
- CITE THE STRONGEST SOURCES: link key claims with [title](url) format from the source list in the synthesis. Pick the most reputable source per claim; do not cite duplicates.
|
|
59768
59897
|
- BE CONCISE: a few short paragraphs plus a bulleted summary. Expand only when the question genuinely requires it.
|
|
59769
59898
|
- HARD CONSTRAINTS: You MUST NOT invent claims not present in the council's responses. You MUST NOT add new web research. You MUST NOT favor a position based on confidence alone.
|
|
59770
|
-
|
|
59899
|
+
Preface the answer with one line listing the participating models (reviewer model as generalist, critic model as skeptic, SME model as domain expert). Do NOT present raw per-member JSON.
|
|
59900
|
+
|
|
59901
|
+
### MODE: DEEP_DIVE
|
|
59902
|
+
Activates when: architect receives \`[MODE: DEEP_DIVE profile=X max_explorers=N output=X update_main=X allow_dirty=X] <scope>\` signal from the deep-dive command handler.
|
|
59903
|
+
|
|
59904
|
+
Purpose: Perform a read-only deep audit of the specified codebase scope using parallel explorer waves, always 2 parallel reviewers, and sequential critic challenge. This mode does NOT mutate source code, does NOT delegate to coder, and does NOT call declare_scope.
|
|
59905
|
+
|
|
59906
|
+
#### STEP 0 — PARSE HEADER
|
|
59907
|
+
Parse the MODE: DEEP_DIVE header to extract:
|
|
59908
|
+
- \`scope\`: the codebase area to audit (e.g., "auth", "payment flow", "src/hooks/")
|
|
59909
|
+
- \`profile\`: one of standard | security | ux | architecture | full (default: standard)
|
|
59910
|
+
- \`max_explorers\`: integer 1..8 (default: 6, or 8 for full profile)
|
|
59911
|
+
- \`output\`: markdown | json (default: markdown)
|
|
59912
|
+
- \`update_main\`: boolean (default: true) — whether to fetch/ff-only main before starting
|
|
59913
|
+
- \`allow_dirty\`: boolean (default: false) — whether to proceed with uncommitted changes
|
|
59914
|
+
|
|
59915
|
+
If the header is malformed or missing required fields, report the error and stop.
|
|
59916
|
+
|
|
59917
|
+
#### STEP 1 — REPO READINESS
|
|
59918
|
+
1. Check git working tree status. If dirty and \`allow_dirty\` is false, warn the user and ask whether to proceed. Do NOT proceed automatically.
|
|
59919
|
+
2. If \`update_main\` is true and tree is clean: check current branch. If not on \`main\`, report current branch to user and ASK FOR CONFIRMATION before switching. Only after explicit user approval: \`git fetch origin main && git checkout main && git merge --ff-only origin/main\`. If ff-only fails, warn the user and ask before proceeding.
|
|
59920
|
+
3. Record the current HEAD commit hash for the report.
|
|
59921
|
+
|
|
59922
|
+
#### STEP 2 — SCOPE RESOLUTION
|
|
59923
|
+
Use the following tools to map the audit scope:
|
|
59924
|
+
1. \`repo_map\` with action "build" to establish the code graph
|
|
59925
|
+
2. \`repo_map\` with action "localization" for the scope target
|
|
59926
|
+
3. \`symbols\` and \`batch_symbols\` on key files identified by localization
|
|
59927
|
+
4. \`imports\` to trace dependency boundaries
|
|
59928
|
+
5. \`doc_scan\` if documentation coverage is relevant
|
|
59929
|
+
6. \`knowledge_recall\` with query matching the scope domain
|
|
59930
|
+
|
|
59931
|
+
Produce a SCOPE MAP: list of files, modules, and interfaces within the audit boundary. Cap at 50 files total.
|
|
59932
|
+
|
|
59933
|
+
#### STEP 3 — EXPLORER MISSIONS (Parallel Waves)
|
|
59934
|
+
Dispatch explorer waves using parallel Task calls. Each wave contains up to \`max_explorers\` missions.
|
|
59935
|
+
|
|
59936
|
+
**File caps per mission:**
|
|
59937
|
+
- 8 files maximum per mission
|
|
59938
|
+
- ~3500 total lines across all files in a mission
|
|
59939
|
+
- Group files by import proximity (files that import each other go in the same mission)
|
|
59940
|
+
|
|
59941
|
+
**Profile-based lane selection — each profile activates specific lanes:**
|
|
59942
|
+
|
|
59943
|
+
| Lane | Template | standard | security | ux | architecture | full |
|
|
59944
|
+
|------|----------|----------|----------|----|-------------|------|
|
|
59945
|
+
| SCOPE_MAP | Map structure, exports, boundaries | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
59946
|
+
| WIRING_DATAFLOW | Trace data flow, API contracts, state propagation | ✓ | ✓ | | ✓ | ✓ |
|
|
59947
|
+
| RUNTIME_BEHAVIOR | Error handling, edge cases, lifecycle, async patterns | ✓ | | | ✓ | ✓ |
|
|
59948
|
+
| UX_FLOW | User-facing behavior, accessibility, responsiveness | | | ✓ | | ✓ |
|
|
59949
|
+
| SECURITY_TRUST | Auth boundaries, input validation, trust transitions | | ✓ | | | ✓ |
|
|
59950
|
+
| TEST_COVERAGE | Coverage gaps, flaky tests, missing assertions | ✓ | | | | ✓ |
|
|
59951
|
+
| PERFORMANCE_RELIABILITY | Resource leaks, N+1 queries, race conditions | | | | ✓ | ✓ |
|
|
59952
|
+
| DOCS_CONFIG_DEPLOYMENT | Config consistency, docs accuracy, deployment drift | | | | | ✓ |
|
|
59953
|
+
|
|
59954
|
+
Each explorer mission receives:
|
|
59955
|
+
- Lane template name and description
|
|
59956
|
+
- Assigned files (8 max, grouped by import proximity)
|
|
59957
|
+
- The scope map context from Step 2
|
|
59958
|
+
- Instruction: "You are performing a [LANE] audit. Report findings as candidate observations with severity (INFO/LOW/MEDIUM/HIGH/CRITICAL), location, and evidence."
|
|
59959
|
+
|
|
59960
|
+
Explorer missions are dispatched in parallel waves. Wait for ALL missions in a wave to complete before dispatching the next wave.
|
|
59961
|
+
|
|
59962
|
+
Explorers generate CANDIDATE FINDINGS only — they do NOT make verdicts. All findings are unverified until Step 5.
|
|
59963
|
+
|
|
59964
|
+
#### STEP 4 — NORMALIZE CANDIDATES
|
|
59965
|
+
1. Collect all candidate findings from all explorer missions.
|
|
59966
|
+
2. Deduplicate: merge findings that reference the same location and issue.
|
|
59967
|
+
3. Assign DD-C001 through DD-CNNN identifiers to unique findings.
|
|
59968
|
+
4. Cap at 10 findings per shard (see Step 5 for sharding).
|
|
59969
|
+
5. Sort by severity (CRITICAL → HIGH → MEDIUM → LOW → INFO).
|
|
59970
|
+
|
|
59971
|
+
#### STEP 5 — ALWAYS 2 PARALLEL REVIEWERS
|
|
59972
|
+
Split the verified candidates into 2 shards of ≤10 candidates each. Dispatch 2 parallel \`{{AGENT_PREFIX}}reviewer\` calls.
|
|
59973
|
+
|
|
59974
|
+
Each reviewer receives:
|
|
59975
|
+
- Their shard of candidates (up to 10)
|
|
59976
|
+
- The scope map context
|
|
59977
|
+
- The original scope description
|
|
59978
|
+
- Instruction: "Verify or reject each candidate finding. For each: verdict (VERIFIED / REJECTED / NEEDS_MORE_EVIDENCE), confidence (0-1), and brief reasoning."
|
|
59979
|
+
|
|
59980
|
+
Reviewers MUST NOT suggest fixes — they verify findings only.
|
|
59981
|
+
|
|
59982
|
+
#### STEP 5b — REVIEWER MERGE/DEDUP
|
|
59983
|
+
After both reviewers return, perform a lightweight sync pass:
|
|
59984
|
+
1. Cross-reference findings between reviewers — flag correlations
|
|
59985
|
+
2. Deduplicate any findings both reviewers verified independently
|
|
59986
|
+
3. For NEEDS_MORE_EVIDENCE findings: if the other reviewer verified a related finding, merge
|
|
59987
|
+
4. Produce a unified findings list with verified/rejected status
|
|
59988
|
+
|
|
59989
|
+
#### STEP 6 — CRITIC CHALLENGE (HIGH/CRITICAL only)
|
|
59990
|
+
For verified findings rated HIGH or CRITICAL, dispatch sequential critic passes:
|
|
59991
|
+
|
|
59992
|
+
**Pass 1 — False-positive / root-cause challenge:**
|
|
59993
|
+
- \`{{AGENT_PREFIX}}critic\` receives each HIGH/CRITICAL finding
|
|
59994
|
+
- Challenge: "Is this a false positive? Is the root cause correctly identified? Provide verdict: SURVIVES / DOWNGRADE / REJECT"
|
|
59995
|
+
- Only findings that SURVIVE proceed to Pass 2
|
|
59996
|
+
|
|
59997
|
+
**Pass 2 — Impact / severity challenge:**
|
|
59998
|
+
- \`{{AGENT_PREFIX}}critic\` receives surviving findings
|
|
59999
|
+
- Challenge: "Is the severity correctly rated? Could this be lower impact than claimed? Provide verdict: SURVIVES / DOWNGRADE / REJECT"
|
|
60000
|
+
- Final severity is the critic's assessed severity
|
|
60001
|
+
|
|
60002
|
+
CRITICAL: Do NOT challenge MEDIUM/LOW/INFO findings. Only HIGH and CRITICAL go through critic review.
|
|
60003
|
+
|
|
60004
|
+
#### STEP 7 — FINAL REPORT
|
|
60005
|
+
Assemble and present the audit report:
|
|
60006
|
+
|
|
60007
|
+
1. **Wiring Map**: Visual summary of the scope's module structure and data flow
|
|
60008
|
+
2. **Functionality Assessment**: High-level summary of what the scope does and how well
|
|
60009
|
+
3. **Verified Findings Table**: DD-ID, severity, location, description, evidence
|
|
60010
|
+
4. **Rejected Candidates**: Brief list with rejection reasons
|
|
60011
|
+
5. **Enhancements**: Non-blocking improvement suggestions
|
|
60012
|
+
6. **Recommended Implementation Phases**: If findings suggest follow-up work, outline phases
|
|
60013
|
+
7. **JSON Block** (when output=json): Structured machine-readable findings
|
|
60014
|
+
|
|
60015
|
+
IMPORTANT CONSTRAINTS for MODE: DEEP_DIVE:
|
|
60016
|
+
- Do NOT mutate source code under any circumstances
|
|
60017
|
+
- Do NOT delegate to coder
|
|
60018
|
+
- Do NOT call declare_scope
|
|
60019
|
+
- Do NOT create or modify any files outside .swarm/
|
|
60020
|
+
- No final finding may appear in the report without reviewer verification
|
|
60021
|
+
- Explorers generate candidate findings only — reviewers verify or reject
|
|
60022
|
+
- Critics challenge only HIGH/CRITICAL findings — do NOT waste cycles on lower severity
|
|
59771
60023
|
|
|
59772
60024
|
### MODE: ISSUE_INGEST
|
|
59773
60025
|
Activates when: user invokes \`/swarm issue <url>\`; OR architect receives \`[MODE: ISSUE_INGEST issue="<url>"]\` signal.
|
|
@@ -67021,7 +67273,14 @@ __export(exports_doc_scan, {
|
|
|
67021
67273
|
});
|
|
67022
67274
|
import * as crypto7 from "node:crypto";
|
|
67023
67275
|
import * as fs47 from "node:fs";
|
|
67024
|
-
import {
|
|
67276
|
+
import {
|
|
67277
|
+
mkdir as mkdir11,
|
|
67278
|
+
readdir as readdir5,
|
|
67279
|
+
readFile as readFile11,
|
|
67280
|
+
realpath as realpath2,
|
|
67281
|
+
stat as stat6,
|
|
67282
|
+
writeFile as writeFile10
|
|
67283
|
+
} from "node:fs/promises";
|
|
67025
67284
|
import * as path70 from "node:path";
|
|
67026
67285
|
function normalizeSeparators(filePath) {
|
|
67027
67286
|
return filePath.replace(/\\/g, "/");
|
|
@@ -67102,8 +67361,8 @@ async function scanDocIndex(directory) {
|
|
|
67102
67361
|
for (const file3 of existingManifest.files) {
|
|
67103
67362
|
try {
|
|
67104
67363
|
const fullPath = path70.join(directory, file3.path);
|
|
67105
|
-
const
|
|
67106
|
-
if (
|
|
67364
|
+
const stat7 = fs47.statSync(fullPath);
|
|
67365
|
+
if (stat7.mtimeMs > file3.mtime) {
|
|
67107
67366
|
cacheValid = false;
|
|
67108
67367
|
break;
|
|
67109
67368
|
}
|
|
@@ -67117,66 +67376,90 @@ async function scanDocIndex(directory) {
|
|
|
67117
67376
|
}
|
|
67118
67377
|
}
|
|
67119
67378
|
} catch {}
|
|
67379
|
+
const resolvedDirectory = await realpath2(directory).catch(() => directory);
|
|
67120
67380
|
const discoveredFiles = [];
|
|
67121
|
-
let
|
|
67122
|
-
|
|
67123
|
-
|
|
67124
|
-
} catch {
|
|
67125
|
-
const manifest2 = {
|
|
67126
|
-
schema_version: 1,
|
|
67127
|
-
scanned_at: new Date().toISOString(),
|
|
67128
|
-
files: []
|
|
67129
|
-
};
|
|
67130
|
-
return { manifest: manifest2, cached: false };
|
|
67131
|
-
}
|
|
67132
|
-
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
67133
|
-
for (const entry of entries) {
|
|
67134
|
-
const fullPath = path70.join(directory, entry);
|
|
67135
|
-
let stat6;
|
|
67381
|
+
let rootReadable = false;
|
|
67382
|
+
const walkDir = async (dir) => {
|
|
67383
|
+
let entries;
|
|
67136
67384
|
try {
|
|
67137
|
-
|
|
67385
|
+
entries = await readdir5(dir, { withFileTypes: true });
|
|
67386
|
+
if (dir === directory)
|
|
67387
|
+
rootReadable = true;
|
|
67138
67388
|
} catch {
|
|
67139
|
-
|
|
67389
|
+
return;
|
|
67140
67390
|
}
|
|
67141
|
-
|
|
67142
|
-
|
|
67143
|
-
|
|
67144
|
-
|
|
67145
|
-
|
|
67146
|
-
if (
|
|
67147
|
-
|
|
67148
|
-
|
|
67391
|
+
for (const entry of entries) {
|
|
67392
|
+
if (discoveredFiles.length >= MAX_INDEXED_FILES)
|
|
67393
|
+
return;
|
|
67394
|
+
const isDir = entry.isDirectory();
|
|
67395
|
+
let isFile = entry.isFile();
|
|
67396
|
+
if (entry.isSymbolicLink()) {
|
|
67397
|
+
try {
|
|
67398
|
+
const symlinkPath = path70.join(dir, entry.name);
|
|
67399
|
+
const resolved = await realpath2(symlinkPath);
|
|
67400
|
+
const rel = path70.relative(resolvedDirectory, resolved);
|
|
67401
|
+
if (rel.startsWith("..") || path70.isAbsolute(rel))
|
|
67402
|
+
continue;
|
|
67403
|
+
const targetStat = await stat6(symlinkPath);
|
|
67404
|
+
isFile = targetStat.isFile();
|
|
67405
|
+
} catch {
|
|
67406
|
+
continue;
|
|
67407
|
+
}
|
|
67149
67408
|
}
|
|
67150
|
-
|
|
67151
|
-
|
|
67152
|
-
|
|
67153
|
-
|
|
67154
|
-
|
|
67155
|
-
skipThisFile = true;
|
|
67156
|
-
break;
|
|
67409
|
+
if (isDir) {
|
|
67410
|
+
if (!SKIP_DIRECTORIES3.has(entry.name)) {
|
|
67411
|
+
await walkDir(path70.join(dir, entry.name));
|
|
67412
|
+
}
|
|
67413
|
+
continue;
|
|
67157
67414
|
}
|
|
67415
|
+
if (!isFile)
|
|
67416
|
+
continue;
|
|
67417
|
+
const fullPath = path70.join(dir, entry.name);
|
|
67418
|
+
const relPath = normalizeSeparators(path70.relative(directory, fullPath));
|
|
67419
|
+
let skipThisFile = false;
|
|
67420
|
+
for (const pattern of SKIP_PATTERNS) {
|
|
67421
|
+
if (pattern.test(relPath)) {
|
|
67422
|
+
skipThisFile = true;
|
|
67423
|
+
break;
|
|
67424
|
+
}
|
|
67425
|
+
}
|
|
67426
|
+
if (skipThisFile)
|
|
67427
|
+
continue;
|
|
67428
|
+
if (!matchesDocPattern(relPath, allPatterns))
|
|
67429
|
+
continue;
|
|
67430
|
+
let fileStat;
|
|
67431
|
+
try {
|
|
67432
|
+
fileStat = await stat6(fullPath);
|
|
67433
|
+
} catch {
|
|
67434
|
+
continue;
|
|
67435
|
+
}
|
|
67436
|
+
let content;
|
|
67437
|
+
try {
|
|
67438
|
+
content = await readFile11(fullPath, "utf-8");
|
|
67439
|
+
} catch {
|
|
67440
|
+
continue;
|
|
67441
|
+
}
|
|
67442
|
+
const { title, summary } = extractTitleAndSummary(content, path70.basename(relPath));
|
|
67443
|
+
discoveredFiles.push({
|
|
67444
|
+
path: relPath,
|
|
67445
|
+
title,
|
|
67446
|
+
summary,
|
|
67447
|
+
lines: content.split(`
|
|
67448
|
+
`).length,
|
|
67449
|
+
mtime: fileStat.mtimeMs
|
|
67450
|
+
});
|
|
67158
67451
|
}
|
|
67159
|
-
|
|
67160
|
-
|
|
67161
|
-
|
|
67162
|
-
|
|
67163
|
-
|
|
67164
|
-
|
|
67165
|
-
|
|
67166
|
-
|
|
67167
|
-
|
|
67168
|
-
|
|
67169
|
-
}
|
|
67170
|
-
const { title, summary } = extractTitleAndSummary(content, path70.basename(entry));
|
|
67171
|
-
const lineCount = content.split(`
|
|
67172
|
-
`).length;
|
|
67173
|
-
discoveredFiles.push({
|
|
67174
|
-
path: entry,
|
|
67175
|
-
title,
|
|
67176
|
-
summary,
|
|
67177
|
-
lines: lineCount,
|
|
67178
|
-
mtime: stat6.mtimeMs
|
|
67179
|
-
});
|
|
67452
|
+
};
|
|
67453
|
+
await walkDir(directory);
|
|
67454
|
+
if (!rootReadable) {
|
|
67455
|
+
return {
|
|
67456
|
+
manifest: {
|
|
67457
|
+
schema_version: 1,
|
|
67458
|
+
scanned_at: new Date().toISOString(),
|
|
67459
|
+
files: []
|
|
67460
|
+
},
|
|
67461
|
+
cached: false
|
|
67462
|
+
};
|
|
67180
67463
|
}
|
|
67181
67464
|
discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
|
|
67182
67465
|
let truncated = false;
|
|
@@ -67325,7 +67608,13 @@ var init_doc_scan = __esm(() => {
|
|
|
67325
67608
|
"dist",
|
|
67326
67609
|
"build",
|
|
67327
67610
|
".next",
|
|
67328
|
-
"vendor"
|
|
67611
|
+
"vendor",
|
|
67612
|
+
"bazel-out",
|
|
67613
|
+
"bazel-bin",
|
|
67614
|
+
"bazel-genfiles",
|
|
67615
|
+
"bazel-testlogs",
|
|
67616
|
+
".gradle",
|
|
67617
|
+
"target"
|
|
67329
67618
|
]);
|
|
67330
67619
|
SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/];
|
|
67331
67620
|
CONSTRAINT_PATTERNS = [
|
|
@@ -74786,6 +75075,12 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
74786
75075
|
output.system.push(text);
|
|
74787
75076
|
injectedTokens += tokens;
|
|
74788
75077
|
};
|
|
75078
|
+
if (_input.sessionID) {
|
|
75079
|
+
const sessionAgent = swarmState.activeAgent.get(_input.sessionID);
|
|
75080
|
+
if (sessionAgent && OPENCODE_NATIVE_AGENTS.has(sessionAgent.toLowerCase())) {
|
|
75081
|
+
return;
|
|
75082
|
+
}
|
|
75083
|
+
}
|
|
74789
75084
|
const maxInjectionTokens = config3.context_budget?.max_injection_tokens ?? 4000;
|
|
74790
75085
|
let injectedTokens = 0;
|
|
74791
75086
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
@@ -76448,22 +76743,22 @@ function classifyPathRisk(filePath, context) {
|
|
|
76448
76743
|
}
|
|
76449
76744
|
})();
|
|
76450
76745
|
const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
|
|
76451
|
-
const
|
|
76746
|
+
const relative16 = path72.relative(context.directory, absolute).replace(/\\/g, "/");
|
|
76452
76747
|
let withinDeclaredScope = null;
|
|
76453
76748
|
if (Array.isArray(context.declaredScope)) {
|
|
76454
76749
|
withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
|
|
76455
76750
|
const s = normalizePath3(scope);
|
|
76456
76751
|
if (!s)
|
|
76457
76752
|
return false;
|
|
76458
|
-
return
|
|
76753
|
+
return relative16 === s || relative16.startsWith(`${s}/`);
|
|
76459
76754
|
});
|
|
76460
76755
|
}
|
|
76461
76756
|
const highRiskBuild = HIGH_RISK_BUILD_PATHS.some((entry) => {
|
|
76462
76757
|
const e = normalizePath3(entry);
|
|
76463
76758
|
if (e.endsWith("/")) {
|
|
76464
|
-
return
|
|
76759
|
+
return relative16.startsWith(e);
|
|
76465
76760
|
}
|
|
76466
|
-
return
|
|
76761
|
+
return relative16 === e || relative16.startsWith(`${e}/`);
|
|
76467
76762
|
});
|
|
76468
76763
|
return {
|
|
76469
76764
|
withinProjectRoot,
|
|
@@ -78932,8 +79227,8 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
78932
79227
|
continue;
|
|
78933
79228
|
const filePath = path79.join(dirPath, entry.name);
|
|
78934
79229
|
try {
|
|
78935
|
-
const
|
|
78936
|
-
if (now -
|
|
79230
|
+
const stat8 = await fs57.stat(filePath);
|
|
79231
|
+
if (now - stat8.mtimeMs > cutoffMs) {
|
|
78937
79232
|
await fs57.unlink(filePath);
|
|
78938
79233
|
}
|
|
78939
79234
|
} catch {}
|
|
@@ -80773,8 +81068,8 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
80773
81068
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
80774
81069
|
const resolvedPath = path84.resolve(directory, normalizedPath);
|
|
80775
81070
|
const projectRoot = path84.resolve(directory);
|
|
80776
|
-
const
|
|
80777
|
-
const withinProject =
|
|
81071
|
+
const relative19 = path84.relative(projectRoot, resolvedPath);
|
|
81072
|
+
const withinProject = relative19 === "" || !relative19.startsWith("..") && !path84.isAbsolute(relative19);
|
|
80778
81073
|
if (!withinProject) {
|
|
80779
81074
|
blockedTasks.push({
|
|
80780
81075
|
task_id: task.id,
|
|
@@ -80949,8 +81244,8 @@ function estimateCyclomaticComplexity(content) {
|
|
|
80949
81244
|
}
|
|
80950
81245
|
function getComplexityForFile(filePath) {
|
|
80951
81246
|
try {
|
|
80952
|
-
const
|
|
80953
|
-
if (
|
|
81247
|
+
const stat8 = fs63.statSync(filePath);
|
|
81248
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES4) {
|
|
80954
81249
|
return null;
|
|
80955
81250
|
}
|
|
80956
81251
|
const content = fs63.readFileSync(filePath, "utf-8");
|
|
@@ -81151,8 +81446,8 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
81151
81446
|
continue;
|
|
81152
81447
|
}
|
|
81153
81448
|
try {
|
|
81154
|
-
const
|
|
81155
|
-
if (
|
|
81449
|
+
const stat8 = fs63.statSync(fullPath);
|
|
81450
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES4) {
|
|
81156
81451
|
continue;
|
|
81157
81452
|
}
|
|
81158
81453
|
const content = fs63.readFileSync(fullPath, "utf-8");
|
|
@@ -81612,8 +81907,8 @@ async function getGitChurn(days, directory) {
|
|
|
81612
81907
|
}
|
|
81613
81908
|
function getComplexityForFile2(filePath) {
|
|
81614
81909
|
try {
|
|
81615
|
-
const
|
|
81616
|
-
if (
|
|
81910
|
+
const stat8 = fs64.statSync(filePath);
|
|
81911
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES5) {
|
|
81617
81912
|
return null;
|
|
81618
81913
|
}
|
|
81619
81914
|
const content = fs64.readFileSync(filePath, "utf-8");
|
|
@@ -81809,7 +82104,7 @@ import {
|
|
|
81809
82104
|
appendFileSync as appendFileSync9,
|
|
81810
82105
|
existsSync as existsSync45,
|
|
81811
82106
|
mkdirSync as mkdirSync21,
|
|
81812
|
-
readFileSync as
|
|
82107
|
+
readFileSync as readFileSync36,
|
|
81813
82108
|
writeFileSync as writeFileSync14
|
|
81814
82109
|
} from "node:fs";
|
|
81815
82110
|
import { join as join72 } from "node:path";
|
|
@@ -81852,7 +82147,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
81852
82147
|
const existingRoot = Object.create(null);
|
|
81853
82148
|
if (existsSync45(filePath)) {
|
|
81854
82149
|
try {
|
|
81855
|
-
const parsed = JSON.parse(
|
|
82150
|
+
const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
|
|
81856
82151
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
81857
82152
|
safeAssignOwnProps(existingRoot, parsed);
|
|
81858
82153
|
}
|
|
@@ -82119,7 +82414,7 @@ function buildPhaseCouncilFeedback(phaseNumber, phaseSummary, verdict, vetoedBy,
|
|
|
82119
82414
|
}
|
|
82120
82415
|
|
|
82121
82416
|
// src/council/criteria-store.ts
|
|
82122
|
-
import { existsSync as existsSync46, mkdirSync as mkdirSync22, readFileSync as
|
|
82417
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync22, readFileSync as readFileSync37, writeFileSync as writeFileSync15 } from "node:fs";
|
|
82123
82418
|
import { join as join73 } from "node:path";
|
|
82124
82419
|
var COUNCIL_DIR = ".swarm/council";
|
|
82125
82420
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
@@ -82137,7 +82432,7 @@ function readCriteria(workingDir, taskId) {
|
|
|
82137
82432
|
if (!existsSync46(filePath))
|
|
82138
82433
|
return null;
|
|
82139
82434
|
try {
|
|
82140
|
-
const parsed = JSON.parse(
|
|
82435
|
+
const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
|
|
82141
82436
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
82142
82437
|
return parsed;
|
|
82143
82438
|
}
|
|
@@ -83785,8 +84080,8 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
83785
84080
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
83786
84081
|
continue;
|
|
83787
84082
|
}
|
|
83788
|
-
const
|
|
83789
|
-
if (!
|
|
84083
|
+
const stat8 = fs69.lstatSync(filePath);
|
|
84084
|
+
if (!stat8.isFile()) {
|
|
83790
84085
|
continue;
|
|
83791
84086
|
}
|
|
83792
84087
|
} catch {
|
|
@@ -84470,9 +84765,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84470
84765
|
continue;
|
|
84471
84766
|
}
|
|
84472
84767
|
const fullPath = path93.join(dir, entry);
|
|
84473
|
-
let
|
|
84768
|
+
let stat8;
|
|
84474
84769
|
try {
|
|
84475
|
-
|
|
84770
|
+
stat8 = fs71.statSync(fullPath);
|
|
84476
84771
|
} catch (e) {
|
|
84477
84772
|
stats.fileErrors.push({
|
|
84478
84773
|
path: fullPath,
|
|
@@ -84480,9 +84775,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
84480
84775
|
});
|
|
84481
84776
|
continue;
|
|
84482
84777
|
}
|
|
84483
|
-
if (
|
|
84778
|
+
if (stat8.isDirectory()) {
|
|
84484
84779
|
findSourceFiles2(fullPath, files, stats);
|
|
84485
|
-
} else if (
|
|
84780
|
+
} else if (stat8.isFile()) {
|
|
84486
84781
|
const ext = path93.extname(fullPath).toLowerCase();
|
|
84487
84782
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
84488
84783
|
files.push(fullPath);
|
|
@@ -84577,8 +84872,8 @@ var imports = createSwarmTool({
|
|
|
84577
84872
|
if (consumers.length >= MAX_CONSUMERS)
|
|
84578
84873
|
break;
|
|
84579
84874
|
try {
|
|
84580
|
-
const
|
|
84581
|
-
if (
|
|
84875
|
+
const stat8 = fs71.statSync(filePath);
|
|
84876
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES7) {
|
|
84582
84877
|
skippedFileCount++;
|
|
84583
84878
|
continue;
|
|
84584
84879
|
}
|
|
@@ -88154,8 +88449,8 @@ async function placeholderScan(input, directory) {
|
|
|
88154
88449
|
}
|
|
88155
88450
|
let content;
|
|
88156
88451
|
try {
|
|
88157
|
-
const
|
|
88158
|
-
if (
|
|
88452
|
+
const stat8 = fs76.statSync(fullPath);
|
|
88453
|
+
if (stat8.size > MAX_FILE_SIZE) {
|
|
88159
88454
|
continue;
|
|
88160
88455
|
}
|
|
88161
88456
|
content = fs76.readFileSync(fullPath, "utf-8");
|
|
@@ -90021,13 +90316,13 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
90021
90316
|
resolved = path102.resolve(baseDir, inputPath);
|
|
90022
90317
|
}
|
|
90023
90318
|
const workspaceResolved = path102.resolve(workspaceDir);
|
|
90024
|
-
let
|
|
90319
|
+
let relative23;
|
|
90025
90320
|
if (isWinAbs) {
|
|
90026
|
-
|
|
90321
|
+
relative23 = path102.win32.relative(workspaceResolved, resolved);
|
|
90027
90322
|
} else {
|
|
90028
|
-
|
|
90323
|
+
relative23 = path102.relative(workspaceResolved, resolved);
|
|
90029
90324
|
}
|
|
90030
|
-
if (
|
|
90325
|
+
if (relative23.startsWith("..")) {
|
|
90031
90326
|
return "path traversal detected";
|
|
90032
90327
|
}
|
|
90033
90328
|
return null;
|
|
@@ -90270,14 +90565,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
90270
90565
|
skippedFiles++;
|
|
90271
90566
|
continue;
|
|
90272
90567
|
}
|
|
90273
|
-
let
|
|
90568
|
+
let stat8;
|
|
90274
90569
|
try {
|
|
90275
|
-
|
|
90570
|
+
stat8 = fs80.statSync(file3);
|
|
90276
90571
|
} catch {
|
|
90277
90572
|
skippedFiles++;
|
|
90278
90573
|
continue;
|
|
90279
90574
|
}
|
|
90280
|
-
if (
|
|
90575
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES9) {
|
|
90281
90576
|
skippedFiles++;
|
|
90282
90577
|
continue;
|
|
90283
90578
|
}
|
|
@@ -91042,8 +91337,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91042
91337
|
for (const entry of entries) {
|
|
91043
91338
|
const entryPath = path104.join(evidenceDir, entry);
|
|
91044
91339
|
try {
|
|
91045
|
-
const
|
|
91046
|
-
if (!
|
|
91340
|
+
const stat8 = fs81.statSync(entryPath);
|
|
91341
|
+
if (!stat8.isDirectory()) {
|
|
91047
91342
|
continue;
|
|
91048
91343
|
}
|
|
91049
91344
|
} catch {
|
|
@@ -91063,11 +91358,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
91063
91358
|
if (!resolvedPath.startsWith(evidenceDirResolved + path104.sep)) {
|
|
91064
91359
|
continue;
|
|
91065
91360
|
}
|
|
91066
|
-
const
|
|
91067
|
-
if (!
|
|
91361
|
+
const stat8 = fs81.lstatSync(evidenceFilePath);
|
|
91362
|
+
if (!stat8.isFile()) {
|
|
91068
91363
|
continue;
|
|
91069
91364
|
}
|
|
91070
|
-
if (
|
|
91365
|
+
if (stat8.size > MAX_FILE_SIZE_BYTES9) {
|
|
91071
91366
|
continue;
|
|
91072
91367
|
}
|
|
91073
91368
|
} catch {
|
|
@@ -91489,8 +91784,8 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
91489
91784
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
91490
91785
|
const specPath = path105.join(targetWorkspace, ".swarm", "spec.md");
|
|
91491
91786
|
try {
|
|
91492
|
-
const
|
|
91493
|
-
specMtime =
|
|
91787
|
+
const stat8 = await fs82.promises.stat(specPath);
|
|
91788
|
+
specMtime = stat8.mtime.toISOString();
|
|
91494
91789
|
const content = await fs82.promises.readFile(specPath, "utf8");
|
|
91495
91790
|
specHash = crypto10.createHash("sha256").update(content).digest("hex");
|
|
91496
91791
|
} catch {
|
|
@@ -94266,7 +94561,7 @@ init_loader();
|
|
|
94266
94561
|
import {
|
|
94267
94562
|
existsSync as existsSync65,
|
|
94268
94563
|
mkdirSync as mkdirSync28,
|
|
94269
|
-
readFileSync as
|
|
94564
|
+
readFileSync as readFileSync54,
|
|
94270
94565
|
renameSync as renameSync18,
|
|
94271
94566
|
unlinkSync as unlinkSync14,
|
|
94272
94567
|
writeFileSync as writeFileSync22
|
|
@@ -94403,7 +94698,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
94403
94698
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
94404
94699
|
const mutationGatePath = path112.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
94405
94700
|
try {
|
|
94406
|
-
const raw =
|
|
94701
|
+
const raw = readFileSync54(mutationGatePath, "utf-8");
|
|
94407
94702
|
const parsed = JSON.parse(raw);
|
|
94408
94703
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
94409
94704
|
if (!gateEntry) {
|
|
@@ -96027,15 +96322,15 @@ function findSourceFiles3(dir, files = []) {
|
|
|
96027
96322
|
continue;
|
|
96028
96323
|
}
|
|
96029
96324
|
const fullPath = path118.join(dir, entry);
|
|
96030
|
-
let
|
|
96325
|
+
let stat8;
|
|
96031
96326
|
try {
|
|
96032
|
-
|
|
96327
|
+
stat8 = fs90.statSync(fullPath);
|
|
96033
96328
|
} catch {
|
|
96034
96329
|
continue;
|
|
96035
96330
|
}
|
|
96036
|
-
if (
|
|
96331
|
+
if (stat8.isDirectory()) {
|
|
96037
96332
|
findSourceFiles3(fullPath, files);
|
|
96038
|
-
} else if (
|
|
96333
|
+
} else if (stat8.isFile()) {
|
|
96039
96334
|
if (isSupportedExtension(fullPath)) {
|
|
96040
96335
|
files.push(fullPath);
|
|
96041
96336
|
}
|
|
@@ -96132,8 +96427,8 @@ var todo_extract = createSwarmTool({
|
|
|
96132
96427
|
return JSON.stringify(errorResult, null, 2);
|
|
96133
96428
|
}
|
|
96134
96429
|
const filesToScan = [];
|
|
96135
|
-
const
|
|
96136
|
-
if (
|
|
96430
|
+
const stat8 = fs90.statSync(scanPath);
|
|
96431
|
+
if (stat8.isFile()) {
|
|
96137
96432
|
if (isSupportedExtension(scanPath)) {
|
|
96138
96433
|
filesToScan.push(scanPath);
|
|
96139
96434
|
} else {
|
|
@@ -98161,6 +98456,10 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
98161
98456
|
template: "/swarm pr-review $ARGUMENTS",
|
|
98162
98457
|
description: "Use /swarm pr-review to launch deep PR review with multi-lane analysis"
|
|
98163
98458
|
},
|
|
98459
|
+
"swarm-deep-dive": {
|
|
98460
|
+
template: "/swarm deep-dive $ARGUMENTS",
|
|
98461
|
+
description: "Use /swarm deep-dive to launch a read-only deep audit with parallel explorer waves, dual reviewers, and critic challenge"
|
|
98462
|
+
},
|
|
98164
98463
|
"swarm-issue": {
|
|
98165
98464
|
template: "/swarm issue $ARGUMENTS",
|
|
98166
98465
|
description: "Use /swarm issue to ingest a GitHub issue into the swarm workflow"
|