refactor(v2): remove builder-agent dev-agent/worktree/swap flow

The dev-agent-in-worktree approach for source self-modification is abandoned
in favor of a direct draft/activate flow with OS-level RO enforcement
(planned, not yet implemented). Strip the whole subgraph:
src/builder-agent/, pending-swaps DB module + migration 006, builder-agent
MCP tools, and all host wiring (startup sweep, approval routing, deadman,
worktree mount, freeze gate). Tool descriptions in self-mod.ts / agents.ts
no longer cross-reference create_dev_agent. CLAUDE.md + v2-checklist updated
to describe the new direction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-15 21:14:39 +03:00
parent 20a24dfd13
commit 81d45b5be9
29 changed files with 9 additions and 3644 deletions

View File

@@ -9,12 +9,10 @@ import path from 'path';
import { OneCLI } from '@onecli-sh/sdk';
import { worktreePathFor } from './builder-agent/worktree.js';
import { CONTAINER_IMAGE, DATA_DIR, GROUPS_DIR, IDLE_TIMEOUT, ONECLI_URL, TIMEZONE } from './config.js';
import { readContainerConfig, writeContainerConfig } from './container-config.js';
import { CONTAINER_RUNTIME_BIN, hostGatewayArgs, readonlyMountArgs, stopContainer } from './container-runtime.js';
import { getAgentGroup } from './db/agent-groups.js';
import { getSwapForDevAgent } from './db/pending-swaps.js';
import { getAdminsOfAgentGroup, getGlobalAdmins, getOwners } from './db/user-roles.js';
import { initGroupFilesystem } from './group-init.js';
import { stopTypingRefresh } from './delivery.js';
@@ -89,24 +87,6 @@ async function spawnContainer(session: Session): Promise<void> {
return;
}
// Freeze gate: if this agent group is the dev_agent of an in-flight
// swap that has already been submitted for approval (commit_sha set),
// refuse to spawn the container. The dev agent stays offline through
// the approval/deadman window so it can't make additional edits that
// weren't part of what the approver reviewed. `bailSwapForRetry`
// clears commit_sha, which implicitly unfreezes and allows the next
// wake to spawn again.
const devSwap = getSwapForDevAgent(agentGroup.id);
if (devSwap && devSwap.commit_sha) {
log.info('Refusing to spawn dev agent — frozen during code-change approval', {
sessionId: session.id,
agentGroup: agentGroup.name,
requestId: devSwap.request_id,
status: devSwap.status,
});
return;
}
// Refresh the destination map and default reply routing so any admin
// changes take effect on wake.
writeDestinations(agentGroup.id, session.id);
@@ -221,24 +201,6 @@ function buildMounts(agentGroup: AgentGroup, session: Session): VolumeMount[] {
const groupRunnerDir = path.join(DATA_DIR, 'v2-sessions', agentGroup.id, 'agent-runner-src');
mounts.push({ hostPath: groupRunnerDir, containerPath: '/app/src', readonly: false });
// Builder-agent worktree at /worktree — only added when this agent group
// is the dev_agent of an in-flight swap. The dev agent edits the worktree
// (a git copy of the repo) through this mount. Its own runtime code at
// /app/src is unchanged — self-modification is structurally impossible.
const swap = getSwapForDevAgent(agentGroup.id);
if (swap) {
const worktreeDir = worktreePathFor(swap.request_id);
if (fs.existsSync(worktreeDir)) {
mounts.push({ hostPath: worktreeDir, containerPath: '/worktree', readonly: false });
} else {
log.warn('Dev agent has in-flight swap but worktree dir is missing', {
agentGroupId: agentGroup.id,
requestId: swap.request_id,
worktreeDir,
});
}
}
// Additional mounts from container config (groups/<folder>/container.json)
const containerConfig = readContainerConfig(agentGroup.folder);
if (containerConfig.additionalMounts && containerConfig.additionalMounts.length > 0) {