@stackmemoryai/stackmemory 1.10.5 → 1.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/LICENSE +131 -64
- package/README.md +107 -24
- package/bin/claude-sm +16 -1
- package/bin/claude-smd +16 -1
- package/bin/codex-smd +16 -1
- package/bin/gemini-sm +16 -1
- package/bin/hermes-sm +21 -0
- package/bin/hermes-smd +21 -0
- package/bin/opencode-sm +16 -1
- package/dist/src/cli/claude-sm.js +266 -84
- package/dist/src/cli/codex-sm.js +225 -33
- package/dist/src/cli/commands/bench.js +209 -2
- package/dist/src/cli/commands/brain.js +206 -0
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/company-os.js +184 -0
- package/dist/src/cli/commands/context.js +5 -0
- package/dist/src/cli/commands/daemon.js +41 -0
- package/dist/src/cli/commands/handoff.js +40 -9
- package/dist/src/cli/commands/onboard.js +70 -3
- package/dist/src/cli/commands/operator.js +127 -0
- package/dist/src/cli/commands/optimize.js +117 -0
- package/dist/src/cli/commands/orchestrate.js +232 -5
- package/dist/src/cli/commands/orchestrator.js +315 -26
- package/dist/src/cli/commands/pack.js +322 -0
- package/dist/src/cli/commands/patterns.js +254 -0
- package/dist/src/cli/commands/portal.js +161 -0
- package/dist/src/cli/commands/scaffold.js +92 -0
- package/dist/src/cli/commands/search.js +40 -1
- package/dist/src/cli/commands/setup.js +178 -11
- package/dist/src/cli/commands/skills.js +10 -1
- package/dist/src/cli/commands/state.js +265 -0
- package/dist/src/cli/commands/sync.js +253 -0
- package/dist/src/cli/commands/tasks.js +130 -1
- package/dist/src/cli/commands/vision.js +221 -0
- package/dist/src/cli/gemini-sm.js +19 -29
- package/dist/src/cli/hermes-sm.js +224 -0
- package/dist/src/cli/index.js +105 -39
- package/dist/src/cli/opencode-sm.js +38 -21
- package/dist/src/cli/utils/determinism-watcher.js +66 -0
- package/dist/src/cli/utils/real-cli-bin.js +116 -0
- package/dist/src/core/brain/brain-store.js +187 -0
- package/dist/src/core/brain/brain-sync.js +193 -0
- package/dist/src/core/brain/index.js +78 -0
- package/dist/src/core/brain/types.js +10 -0
- package/dist/src/core/cache/content-cache.js +238 -0
- package/dist/src/{integrations/diffmem → core/cache}/index.js +5 -5
- package/dist/src/core/cache/token-estimator.js +39 -0
- package/dist/src/core/config/feature-flags.js +2 -6
- package/dist/src/core/context/frame-database.js +79 -27
- package/dist/src/core/context/recursive-context-manager.js +1 -1
- package/dist/src/core/context/rehydration.js +2 -1
- package/dist/src/core/cross-search/cross-project-search.js +269 -0
- package/dist/src/core/cross-search/index.js +10 -0
- package/dist/src/core/database/sqlite-adapter.js +14 -84
- package/dist/src/core/extensions/provider-adapter.js +5 -0
- package/dist/src/core/models/model-router.js +54 -2
- package/dist/src/core/models/provider-pricing.js +58 -4
- package/dist/src/core/monitoring/logger.js +2 -1
- package/dist/src/core/optimization/trace-optimizer.js +413 -0
- package/dist/src/core/patterns/index.js +22 -0
- package/dist/src/core/patterns/pattern-applier.js +39 -0
- package/dist/src/core/patterns/pattern-observer.js +157 -0
- package/dist/src/core/patterns/pattern-store.js +259 -0
- package/dist/src/core/patterns/types.js +19 -0
- package/dist/src/core/provenance/confidence-scorer.js +128 -0
- package/dist/src/core/provenance/index.js +40 -0
- package/dist/src/core/provenance/provenance-store.js +194 -0
- package/dist/src/core/provenance/types.js +82 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
- package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
- package/dist/src/core/session/project-handoff.js +64 -0
- package/dist/src/core/session/session-manager.js +28 -0
- package/dist/src/core/shared-state/canonical-store.js +564 -0
- package/dist/src/core/skill-packs/index.js +18 -0
- package/dist/src/core/skill-packs/parser.js +42 -0
- package/dist/src/core/skill-packs/registry.js +224 -0
- package/dist/src/core/skill-packs/types.js +79 -0
- package/dist/src/core/storage/cloud-sync-manager.js +116 -0
- package/dist/src/core/storage/cloud-sync.js +574 -0
- package/dist/src/core/storage/two-tier-storage.js +5 -1
- package/dist/src/core/tasks/master-tasks-template.js +43 -0
- package/dist/src/core/tasks/md-task-parser.js +138 -0
- package/dist/src/core/trace/trace-event-store.js +282 -0
- package/dist/src/core/vision/index.js +27 -0
- package/dist/src/core/vision/signals.js +79 -0
- package/dist/src/core/vision/types.js +22 -0
- package/dist/src/core/vision/vision-file.js +146 -0
- package/dist/src/core/vision/vision-loop.js +220 -0
- package/dist/src/core/wiki/wiki-compiler.js +103 -1
- package/dist/src/daemon/daemon-config.js +52 -0
- package/dist/src/daemon/services/desire-path-service.js +566 -0
- package/dist/src/daemon/services/github-service.js +126 -0
- package/dist/src/daemon/services/research-stream-service.js +320 -0
- package/dist/src/daemon/services/telemetry-service.js +192 -0
- package/dist/src/daemon/unified-daemon.js +58 -1
- package/dist/src/features/browser/cli-browser-agent.js +417 -0
- package/dist/src/features/browser/stagehand-workflows.js +578 -0
- package/dist/src/features/operator/adapter-factory.js +62 -0
- package/dist/src/features/operator/browser-adapter.js +109 -0
- package/dist/src/features/operator/desktop-adapter.js +125 -0
- package/dist/src/features/operator/index.js +39 -0
- package/dist/src/features/operator/llm-decision.js +137 -0
- package/dist/src/features/operator/operator-logger.js +92 -0
- package/dist/src/features/operator/overnight-runner.js +327 -0
- package/dist/src/features/operator/screen-adapter.js +91 -0
- package/dist/src/features/operator/session-manager.js +127 -0
- package/dist/src/features/operator/state-machine.js +227 -0
- package/dist/src/features/operator/task-queue.js +81 -0
- package/dist/src/features/portal/index.js +26 -0
- package/dist/src/features/portal/server.js +240 -0
- package/dist/src/features/portal/types.js +14 -0
- package/dist/src/features/portal/ui.js +195 -0
- package/dist/src/features/sweep/pty-wrapper.js +13 -5
- package/dist/src/features/tasks/task-aware-context.js +2 -1
- package/dist/src/features/tui/simple-monitor.js +0 -23
- package/dist/src/features/tui/swarm-monitor.js +8 -66
- package/dist/src/features/web/client/hooks/use-socket.js +12 -0
- package/dist/src/{core/merge/index.js → features/web/client/lib/utils.js} +8 -4
- package/dist/src/features/web/client/next-env.d.js +4 -0
- package/dist/src/features/web/client/stores/session-store.js +12 -0
- package/dist/src/features/web/server/gcp-billing.js +76 -0
- package/dist/src/features/web/server/index.js +10 -0
- package/dist/src/features/web/server/spend-calculator.js +228 -0
- package/dist/src/hooks/schemas.js +6 -1
- package/dist/src/integrations/anthropic/client.js +3 -2
- package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
- package/dist/src/integrations/claude-code/subagent-client.js +307 -11
- package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
- package/dist/src/integrations/github/pr-state.js +158 -0
- package/dist/src/integrations/linear/client.js +4 -1
- package/dist/src/integrations/linear/webhook-retry.js +196 -0
- package/dist/src/integrations/linear/webhook-server.js +18 -22
- package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
- package/dist/src/integrations/mcp/handlers/index.js +40 -84
- package/dist/src/integrations/mcp/server.js +542 -641
- package/dist/src/integrations/mcp/tool-alias-registry.js +297 -0
- package/dist/src/integrations/mcp/tool-definitions.js +152 -682
- package/dist/src/mcp/stackmemory-mcp-server.js +571 -231
- package/dist/src/orchestrators/multimodal/determinism.js +244 -0
- package/dist/src/orchestrators/multimodal/harness.js +149 -78
- package/dist/src/orchestrators/multimodal/providers.js +44 -3
- package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
- package/dist/src/utils/hook-installer.js +0 -8
- package/dist/src/utils/process-cleanup.js +1 -7
- package/docs/README.md +42 -0
- package/docs/guides/README_INSTALL.md +208 -0
- package/package.json +27 -9
- package/packs/coding/python-fastapi/instructions.md +60 -0
- package/packs/coding/python-fastapi/pack.yaml +28 -0
- package/packs/coding/typescript-react/instructions.md +47 -0
- package/packs/coding/typescript-react/pack.yaml +28 -0
- package/packs/core/commands/capture.md +32 -0
- package/packs/core/commands/learn.md +73 -0
- package/packs/core/commands/next.md +36 -0
- package/packs/core/commands/restart.md +58 -0
- package/packs/core/commands/restore.md +29 -0
- package/packs/core/commands/start.md +57 -0
- package/packs/core/commands/stop.md +65 -0
- package/packs/core/commands/summary.md +40 -0
- package/packs/core/manifest.json +24 -0
- package/packs/ops/decision-recovery/instructions.md +65 -0
- package/packs/ops/decision-recovery/pack.yaml +89 -0
- package/scripts/claude-code-wrapper.sh +11 -0
- package/scripts/claude-sm-setup.sh +12 -1
- package/scripts/codex-wrapper.sh +11 -0
- package/scripts/git-hooks/branch-context-manager.sh +11 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
- package/scripts/hooks/cleanup-shell.sh +12 -1
- package/scripts/hooks/task-complete.sh +12 -1
- package/scripts/install-code-execution-hooks.sh +12 -1
- package/scripts/install-sweep-hook.sh +12 -0
- package/scripts/install.sh +11 -0
- package/scripts/opencode-wrapper.sh +11 -0
- package/scripts/portal/cloud-init.yaml +69 -0
- package/scripts/portal/setup.sh +69 -0
- package/scripts/portal/stackmemory-portal.service +34 -0
- package/scripts/setup-claude-integration.sh +12 -1
- package/scripts/smoke-init-db.sh +23 -0
- package/scripts/stackmemory-daemon.sh +11 -0
- package/scripts/verify-dist.cjs +11 -4
- package/dist/src/cli/commands/ralph.js +0 -1053
- package/dist/src/cli/commands/team.js +0 -168
- package/dist/src/core/context/shared-context-layer.js +0 -620
- package/dist/src/core/context/stack-merge-resolver.js +0 -748
- package/dist/src/core/merge/conflict-detector.js +0 -430
- package/dist/src/core/merge/resolution-engine.js +0 -557
- package/dist/src/core/merge/stack-diff.js +0 -531
- package/dist/src/core/merge/unified-merge-resolver.js +0 -302
- package/dist/src/hooks/diffmem-hooks.js +0 -376
- package/dist/src/integrations/diffmem/client.js +0 -208
- package/dist/src/integrations/diffmem/config.js +0 -14
- package/dist/src/integrations/greptile/client.js +0 -101
- package/dist/src/integrations/greptile/config.js +0 -14
- package/dist/src/integrations/greptile/index.js +0 -11
- package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
- package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
- package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
- package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
- package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -391
- package/dist/src/integrations/ralph/index.js +0 -17
- package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -435
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
- package/dist/src/integrations/ralph/loopmax.js +0 -488
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
- package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
- package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
- package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1007
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
- package/scripts/ralph-loop-implementation.js +0 -404
- /package/dist/src/core/{merge → cache}/types.js +0 -0
- /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
- /package/dist/src/{integrations/greptile/types.js → core/trace/trace-event.js} +0 -0
- /package/dist/src/{integrations/ralph → features/operator}/types.js +0 -0
|
@@ -18,6 +18,7 @@ import Database from "better-sqlite3";
|
|
|
18
18
|
import { logger } from "../../core/monitoring/logger.js";
|
|
19
19
|
import { isProcessAlive } from "../../utils/process-cleanup.js";
|
|
20
20
|
import { Conductor } from "./orchestrator.js";
|
|
21
|
+
import { createVisionCommand } from "./vision.js";
|
|
21
22
|
import {
|
|
22
23
|
getAgentStatusDir,
|
|
23
24
|
getOutcomesLogPath
|
|
@@ -189,13 +190,13 @@ function progressBar(pct, width) {
|
|
|
189
190
|
return `${col}${"\u2501".repeat(filled)}${c.d}${"\u254C".repeat(empty)}${c.r}`;
|
|
190
191
|
}
|
|
191
192
|
function scanAgentStatuses() {
|
|
192
|
-
const
|
|
193
|
-
if (!existsSync(
|
|
194
|
-
const entries = readdirSync(
|
|
193
|
+
const agentsDir = join(homedir(), ".stackmemory", "conductor", "agents");
|
|
194
|
+
if (!existsSync(agentsDir)) return [];
|
|
195
|
+
const entries = readdirSync(agentsDir, { withFileTypes: true });
|
|
195
196
|
const statuses = [];
|
|
196
197
|
for (const entry of entries) {
|
|
197
198
|
if (!entry.isDirectory()) continue;
|
|
198
|
-
const statusPath = join(
|
|
199
|
+
const statusPath = join(agentsDir, entry.name, "status.json");
|
|
199
200
|
if (!existsSync(statusPath)) continue;
|
|
200
201
|
try {
|
|
201
202
|
const data = JSON.parse(readFileSync(statusPath, "utf-8"));
|
|
@@ -668,6 +669,7 @@ function createConductorCommands() {
|
|
|
668
669
|
}
|
|
669
670
|
cmd.help();
|
|
670
671
|
});
|
|
672
|
+
cmd.addCommand(createVisionCommand());
|
|
671
673
|
cmd.command("capture").description("Capture workspace context after an agent run").requiredOption("--issue <id>", "Issue identifier (e.g., STA-476)").option("--workspace <path>", "Workspace directory", process.cwd()).option("--attempt <n>", "Attempt number", "1").action(async (options) => {
|
|
672
674
|
const workspace = options.workspace;
|
|
673
675
|
const issueId = options.issue;
|
|
@@ -953,6 +955,7 @@ function createConductorCommands() {
|
|
|
953
955
|
console.log("");
|
|
954
956
|
});
|
|
955
957
|
cmd.command("finalize").description("Clean up completed/dead agents that conductor missed").option("--dry-run", "Show what would be done without doing it", false).action(async (options) => {
|
|
958
|
+
const agentsDir = join(homedir(), ".stackmemory", "conductor", "agents");
|
|
956
959
|
const statuses = scanAgentStatuses();
|
|
957
960
|
const needsFinalize = statuses.map((s) => ({ ...s, ...enrichStatus(s) })).filter((s) => {
|
|
958
961
|
return !s.alive || s.elapsed > STALE_FINALIZE_THRESHOLD_MS;
|
|
@@ -1038,6 +1041,221 @@ function createConductorCommands() {
|
|
|
1038
1041
|
);
|
|
1039
1042
|
}
|
|
1040
1043
|
});
|
|
1044
|
+
const isMerged = (repo, branch, lane) => {
|
|
1045
|
+
try {
|
|
1046
|
+
execSync(`git merge-base --is-ancestor "${branch}" "${lane}"`, {
|
|
1047
|
+
cwd: repo,
|
|
1048
|
+
stdio: "pipe",
|
|
1049
|
+
timeout: 5e3
|
|
1050
|
+
});
|
|
1051
|
+
return true;
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
const status = err.status;
|
|
1054
|
+
if (status !== 1) throw err;
|
|
1055
|
+
}
|
|
1056
|
+
try {
|
|
1057
|
+
const out = execSync(`git cherry "${lane}" "${branch}"`, {
|
|
1058
|
+
cwd: repo,
|
|
1059
|
+
encoding: "utf-8",
|
|
1060
|
+
timeout: 1e4
|
|
1061
|
+
}).trim();
|
|
1062
|
+
if (!out) return true;
|
|
1063
|
+
const lines = out.split("\n").filter(Boolean);
|
|
1064
|
+
return lines.every((l) => l.startsWith("-"));
|
|
1065
|
+
} catch {
|
|
1066
|
+
return false;
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
const bucketLaneBranches = (repo, lane) => {
|
|
1070
|
+
let all = [];
|
|
1071
|
+
try {
|
|
1072
|
+
all = execSync(`git branch --list 'worktree-agent-*'`, {
|
|
1073
|
+
cwd: repo,
|
|
1074
|
+
encoding: "utf-8",
|
|
1075
|
+
timeout: 1e4
|
|
1076
|
+
}).split("\n").map((s) => s.trim().replace(/^[*+]\s*/, "")).filter(Boolean);
|
|
1077
|
+
} catch {
|
|
1078
|
+
}
|
|
1079
|
+
const merged = [];
|
|
1080
|
+
const unmerged = [];
|
|
1081
|
+
for (const b of all) {
|
|
1082
|
+
(isMerged(repo, b, lane) ? merged : unmerged).push(b);
|
|
1083
|
+
}
|
|
1084
|
+
return { merged, unmerged };
|
|
1085
|
+
};
|
|
1086
|
+
const getWorktreeCleanliness = (repo, wtPath) => {
|
|
1087
|
+
try {
|
|
1088
|
+
const out = execSync(`git -C "${wtPath}" status --short`, {
|
|
1089
|
+
cwd: repo,
|
|
1090
|
+
encoding: "utf-8",
|
|
1091
|
+
timeout: 5e3
|
|
1092
|
+
});
|
|
1093
|
+
return out.trim().length > 0 ? "dirty" : "clean";
|
|
1094
|
+
} catch {
|
|
1095
|
+
return "unknown";
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
const laneCmd = cmd.command("lane").description(
|
|
1099
|
+
"Inspect or clean up worktree-agent-* branches against a lane"
|
|
1100
|
+
);
|
|
1101
|
+
laneCmd.command("status").description(
|
|
1102
|
+
"List worktree-agent-* branches and their merge state vs the lane"
|
|
1103
|
+
).option(
|
|
1104
|
+
"--lane <branch>",
|
|
1105
|
+
"Lane branch to compare against (default: current branch)"
|
|
1106
|
+
).option("--repo <path>", "Git repo root", process.cwd()).action((options) => {
|
|
1107
|
+
const repo = options.repo;
|
|
1108
|
+
const lane = options.lane || execSync("git branch --show-current", {
|
|
1109
|
+
cwd: repo,
|
|
1110
|
+
encoding: "utf-8"
|
|
1111
|
+
}).trim();
|
|
1112
|
+
if (!lane) {
|
|
1113
|
+
console.error(
|
|
1114
|
+
`${c.red}Could not resolve lane branch.${c.r} Pass --lane.`
|
|
1115
|
+
);
|
|
1116
|
+
process.exit(1);
|
|
1117
|
+
}
|
|
1118
|
+
const { merged, unmerged } = bucketLaneBranches(repo, lane);
|
|
1119
|
+
console.log(`
|
|
1120
|
+
${c.b}Lane:${c.r} ${c.cyan}${lane}${c.r}
|
|
1121
|
+
`);
|
|
1122
|
+
if (merged.length) {
|
|
1123
|
+
console.log(` ${c.green}merged (${merged.length}):${c.r}`);
|
|
1124
|
+
for (const b of merged) console.log(` ${c.gray}\u2713${c.r} ${b}`);
|
|
1125
|
+
}
|
|
1126
|
+
if (unmerged.length) {
|
|
1127
|
+
console.log(`
|
|
1128
|
+
${c.orange}unmerged (${unmerged.length}):${c.r}`);
|
|
1129
|
+
for (const b of unmerged) console.log(` ${c.orange}\u2022${c.r} ${b}`);
|
|
1130
|
+
}
|
|
1131
|
+
if (!merged.length && !unmerged.length) {
|
|
1132
|
+
console.log(` ${c.gray}No worktree-agent-* branches found.${c.r}`);
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
laneCmd.command("cleanup").description(
|
|
1136
|
+
"Remove worktree-agent-* branches and worktrees already merged into the lane"
|
|
1137
|
+
).option(
|
|
1138
|
+
"--lane <branch>",
|
|
1139
|
+
"Lane branch to compare against (default: current branch)"
|
|
1140
|
+
).option("--repo <path>", "Git repo root", process.cwd()).option("--dry-run", "Show what would be removed without doing it", false).option(
|
|
1141
|
+
"--force",
|
|
1142
|
+
"Remove worktrees even if they have uncommitted changes",
|
|
1143
|
+
false
|
|
1144
|
+
).action((options) => {
|
|
1145
|
+
const repo = options.repo;
|
|
1146
|
+
const lane = options.lane || execSync("git branch --show-current", {
|
|
1147
|
+
cwd: repo,
|
|
1148
|
+
encoding: "utf-8"
|
|
1149
|
+
}).trim();
|
|
1150
|
+
if (!lane) {
|
|
1151
|
+
console.error(
|
|
1152
|
+
`${c.red}Could not resolve lane branch.${c.r} Pass --lane.`
|
|
1153
|
+
);
|
|
1154
|
+
process.exit(1);
|
|
1155
|
+
}
|
|
1156
|
+
const { merged } = bucketLaneBranches(repo, lane);
|
|
1157
|
+
if (merged.length === 0) {
|
|
1158
|
+
console.log(
|
|
1159
|
+
`${c.green}Nothing to clean up for lane ${c.cyan}${lane}${c.r}.`
|
|
1160
|
+
);
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const worktreeMap = /* @__PURE__ */ new Map();
|
|
1164
|
+
try {
|
|
1165
|
+
const wt = execSync("git worktree list --porcelain", {
|
|
1166
|
+
cwd: repo,
|
|
1167
|
+
encoding: "utf-8",
|
|
1168
|
+
timeout: 1e4
|
|
1169
|
+
});
|
|
1170
|
+
let currentPath = "";
|
|
1171
|
+
for (const line of wt.split("\n")) {
|
|
1172
|
+
if (line.startsWith("worktree ")) {
|
|
1173
|
+
currentPath = line.slice("worktree ".length).trim();
|
|
1174
|
+
} else if (line.startsWith("branch ")) {
|
|
1175
|
+
const ref = line.slice("branch ".length).trim();
|
|
1176
|
+
const b = ref.replace(/^refs\/heads\//, "");
|
|
1177
|
+
if (currentPath) worktreeMap.set(b, currentPath);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
} catch {
|
|
1181
|
+
}
|
|
1182
|
+
console.log(
|
|
1183
|
+
`
|
|
1184
|
+
${c.b}Lane:${c.r} ${c.cyan}${lane}${c.r} ${c.d}(${merged.length} merged branches)${c.r}
|
|
1185
|
+
`
|
|
1186
|
+
);
|
|
1187
|
+
let skippedDirty = 0;
|
|
1188
|
+
let skippedUnknown = 0;
|
|
1189
|
+
for (const branch of merged) {
|
|
1190
|
+
const wtPath = worktreeMap.get(branch);
|
|
1191
|
+
const cleanliness = wtPath ? getWorktreeCleanliness(repo, wtPath) : "unknown";
|
|
1192
|
+
const dirty = cleanliness === "dirty";
|
|
1193
|
+
if (dirty && !options.force) {
|
|
1194
|
+
skippedDirty++;
|
|
1195
|
+
console.log(
|
|
1196
|
+
` ${c.orange}\u26A0${c.r} ${c.orange}dirty${c.r} ${wtPath} ${c.d}(skipping ${branch} \u2014 pass --force to remove)${c.r}`
|
|
1197
|
+
);
|
|
1198
|
+
continue;
|
|
1199
|
+
}
|
|
1200
|
+
if (wtPath && cleanliness === "unknown" && !options.force) {
|
|
1201
|
+
skippedUnknown++;
|
|
1202
|
+
console.log(
|
|
1203
|
+
` ${c.orange}\u26A0${c.r} ${c.orange}unknown${c.r} ${wtPath} ${c.d}(skipping ${branch} \u2014 could not verify clean state; pass --force to remove)${c.r}`
|
|
1204
|
+
);
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
const dirtyTag = dirty ? ` ${c.orange}[dirty]${c.r}` : "";
|
|
1208
|
+
const unknownTag = cleanliness === "unknown" ? ` ${c.orange}[unknown]${c.r}` : "";
|
|
1209
|
+
const action = wtPath ? `${c.gray}worktree remove${c.r} ${wtPath}${dirtyTag}${unknownTag} + ${c.gray}branch -D${c.r} ${branch}` : `${c.gray}branch -D${c.r} ${branch}`;
|
|
1210
|
+
console.log(` ${c.green}\u2713${c.r} ${action}`);
|
|
1211
|
+
if (options.dryRun) continue;
|
|
1212
|
+
if (wtPath) {
|
|
1213
|
+
try {
|
|
1214
|
+
execSync(`git worktree remove "${wtPath}" --force`, {
|
|
1215
|
+
cwd: repo,
|
|
1216
|
+
stdio: "pipe",
|
|
1217
|
+
timeout: 15e3
|
|
1218
|
+
});
|
|
1219
|
+
} catch (err) {
|
|
1220
|
+
console.log(
|
|
1221
|
+
` ${c.red}worktree remove failed:${c.r} ${err.message}`
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
try {
|
|
1226
|
+
execSync(`git branch -D "${branch}"`, {
|
|
1227
|
+
cwd: repo,
|
|
1228
|
+
stdio: "pipe",
|
|
1229
|
+
timeout: 5e3
|
|
1230
|
+
});
|
|
1231
|
+
} catch (err) {
|
|
1232
|
+
console.log(
|
|
1233
|
+
` ${c.red}branch -D failed:${c.r} ${err.message}`
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
if (!options.dryRun) {
|
|
1238
|
+
try {
|
|
1239
|
+
execSync("git worktree prune", {
|
|
1240
|
+
cwd: repo,
|
|
1241
|
+
stdio: "pipe",
|
|
1242
|
+
timeout: 1e4
|
|
1243
|
+
});
|
|
1244
|
+
} catch {
|
|
1245
|
+
}
|
|
1246
|
+
const skipNote = skippedDirty ? ` ${c.orange}(${skippedDirty} dirty skipped \u2014 pass --force)${c.r}` : "";
|
|
1247
|
+
const unknownNote = skippedUnknown ? ` ${c.orange}(${skippedUnknown} unknown skipped \u2014 pass --force)${c.r}` : "";
|
|
1248
|
+
console.log(`
|
|
1249
|
+
${c.green}Done.${c.r}${skipNote}${unknownNote}`);
|
|
1250
|
+
} else {
|
|
1251
|
+
const skipNote = skippedDirty ? ` ${c.orange}(${skippedDirty} dirty would be skipped \u2014 pass --force to include)${c.r}` : "";
|
|
1252
|
+
const unknownNote = skippedUnknown ? ` ${c.orange}(${skippedUnknown} unknown would be skipped \u2014 pass --force to include)${c.r}` : "";
|
|
1253
|
+
console.log(
|
|
1254
|
+
`
|
|
1255
|
+
${c.d}Dry run \u2014 no changes made. Remove --dry-run to execute.${c.r}${skipNote}${unknownNote}`
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1041
1259
|
cmd.command("logs").description("Tail agent output log").argument("<issue-id>", "Issue identifier (e.g., STA-499)").option("-f, --follow", "Follow the log (tail -f)", false).option("-n, --lines <n>", "Number of lines to show", "50").action(async (issueId, options) => {
|
|
1042
1260
|
const logPath = join(getAgentStatusDir(issueId), "output.log");
|
|
1043
1261
|
if (!existsSync(logPath)) {
|
|
@@ -1521,6 +1739,13 @@ function createConductorCommands() {
|
|
|
1521
1739
|
).option(
|
|
1522
1740
|
"--no-pr",
|
|
1523
1741
|
"Disable automatic GitHub PR creation after agent success"
|
|
1742
|
+
).option(
|
|
1743
|
+
"--workspace-mode <mode>",
|
|
1744
|
+
'Workspace mode: "auto" (detect GitButler), "gitbutler", or "worktree"',
|
|
1745
|
+
"auto"
|
|
1746
|
+
).option(
|
|
1747
|
+
"--lane <branch>",
|
|
1748
|
+
"Optional lane branch. When set, conductor uses git worktrees rooted at the lane as worktree-agent-<id> and suppresses PRs (lane is human-curated)."
|
|
1524
1749
|
).action(async (options) => {
|
|
1525
1750
|
ensureDefaultPromptTemplate();
|
|
1526
1751
|
const conductor = new Conductor({
|
|
@@ -1537,7 +1762,9 @@ function createConductorCommands() {
|
|
|
1537
1762
|
turnTimeoutMs: parseInt(options.turnTimeout, 10),
|
|
1538
1763
|
agentMode: options.mode === "adapter" ? "adapter" : "cli",
|
|
1539
1764
|
model: options.model,
|
|
1540
|
-
autoPR: options.pr
|
|
1765
|
+
autoPR: options.lane ? false : options.pr,
|
|
1766
|
+
workspaceMode: options.workspaceMode,
|
|
1767
|
+
laneBranch: options.lane
|
|
1541
1768
|
});
|
|
1542
1769
|
await conductor.start();
|
|
1543
1770
|
});
|