Repository navigation
Conversation
Three project-level Claude Code subagent definitions under .claude/agents/: - orchestrator: takes requirements, decomposes them into independent tasks, spawns task-worker subagents on the cheapest suitable model (haiku/sonnet/opus/fable), integrates their branches and hands conflicts to merge-conflict-resolver. Edit/Write are disallowed so every change goes through a worker. - task-worker: generic single-task implementer that works in its own worktree, verifies with build/test/format, commits on its branch and returns a structured report. Cannot spawn agents. - merge-conflict-resolver: resolves merge/rebase/cherry-pick conflicts preserving both sides' intent, verifies, stages or completes the operation and reports per-file resolutions. Cannot spawn agents. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The orchestrator overrides the model per task; the cheapest tier is the right baseline when no override is given. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The orchestrator now keeps shared memory across runs: - docs/orchestration/README.md defines the run-log format and naming (YYYY-MM-DD-HHMM-<slug>.md, UTC start time) with sections for the requirement, task table (agent/model/outcome), outcome, verification, decisions, open items and notes for the next orchestrator. - The orchestrator reads the latest logs before planning, opens its own log with status: in-progress as soon as it has restated the requirement, keeps it current, and closes it on the integration branch at the end. - Write/Edit are now allowed for the orchestrator but a PreToolUse hook (.claude/hooks/orchestrator-write-guard.sh) blocks any path other than docs/orchestration/*.md, so code changes still go through task-workers. - docs/README.md and CLAUDE.md classify the new folder. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds .claude/hooks/no-remote-writes.py, a PreToolUse hook on Bash wired into both worker agents. It parses each shell command (segments, global git options, wrappers like timeout/sh -c/xargs/eval) and exits 2 for: - git push, send-email, svn, request-pull - git remote add/set-url/rename/remove and git config of alias.*, remote.*, url.*, push.*, credential.* - any gh command other than read-only pr/issue/run/release/repo/search views and gh api without a write method or body commit, checkout, switch, fetch, pull, add, status, diff, log and read-only remote inspection remain allowed. `--self-test` runs 41 allow/block cases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
.claude/settings.json turns on the Claude Code Bash sandbox for this repo: no unsandboxed retry, fail if unavailable, network limited to api.anthropic.com / github.com / api.github.com / *.nuget.org, writes allowed to the dotnet/NuGet home dirs, private SSH keys read-denied. Findings from running build/test/format inside it, all encoded in the settings file and explained in CLAUDE.md: - MSBuild worker nodes use named pipes at the hard-coded path /tmp/MSBuild<pid>; the seccomp filter blocks Unix sockets and /tmp is read-only, so solution builds hung 5 minutes then "failed" with 0 errors. Fixed with allowAllUnixSockets + allowWrite /tmp, and the socket escape routes (D-Bus, SSH agent, X11, Docker/Podman) hidden via denyRead. Verified systemd-run/busctl/ssh-add fail in the sandbox. - SourceLink's LocateRepository fails on the /dev/null mount the sandbox puts over .gitmodules; env EnableSourceControlManagerQueries=false skips it for builds under Claude Code only. - SSH agent and keyring are unreachable in the sandbox, so git fetch/pull/push/ls-remote and read-only gh commands are excludedCommands (workers' hook still blocks pushes). no-remote-writes.py now also sets a per-worktree remote.*.pushurl to a dead path (extensions.worktreeConfig) when running in a linked worktree, so a push the parser misses still fails; the primary checkout is never touched. Verified in nested sandboxed sessions: dotnet build, dotnet test (998 tests), dotnet format --verify-no-changes, codeguard rules test, git ls-remote and gh pr view all succeed; home writes, direct network, private key reads and D-Bus access all fail. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Adds three project-level Claude Code subagent definitions under
.claude/agents/so multi-step work in this repo can be delegated and coordinated:orchestrator(opus, high effort): takes requirements from the user, decomposes them into independent tasks, spawnstask-workersubagents on the cheapest model that fits each task, integrates worker branches on a dedicated integration branch, hands conflicts tomerge-conflict-resolver, verifies with build/test/format and returns one report.Edit/Writeare hook-restricted to its run log indocs/orchestration/, so every repository change goes through a worker. Workers are spawned with worktree isolation so they never collide with each other or with other sessions.task-worker(haikudefault, overridable per spawn; the orchestrator picks the tier per task): generic single-task implementer. Reads the brief, stays inside the files it owns, adds tests, runs build/test/format, commits on its own branch and returns a fixed-format report (branch, changes, verification, assumptions, out-of-scope observations). Cannot spawn agents.merge-conflict-resolver(sonnetdefault; orchestrator usesopuswhen both sides changed the same logic): identifies the in-progress operation and sides, reads base/ours/theirs and originating commits, resolves to preserve both intents, regenerates rather than hand-merges generated files, verifies, stages or completes the operation, and reports per-file resolutions with confidence and a "needs human review" section. Wholesale ours/theirs, resets, force pushes and aborts are forbidden. Cannot spawn agents.Orchestration run logs
The orchestrator keeps shared memory across runs in
docs/orchestration/:YYYY-MM-DD-HHMM-<slug>.md(UTC start time), with the requirement, a task table (agent / model / outcome), outcome, verification, decisions, open items and "Notes for the next orchestrator". Format is indocs/orchestration/README.md.status: in-progressas soon as it has restated the requirement, keeps it current, and closes it on the integration branch so it reachesmainwith the work.Write/Editare enabled for the orchestrator, but aPreToolUsehook (.claude/hooks/orchestrator-write-guard.sh) blocks any path other thandocs/orchestration/*.md, so code changes still go throughtask-workers.docs/README.mdandCLAUDE.mdclassify the new folder (append-only, never moved todocs/done/).No remote writes from workers
task-workerandmerge-conflict-resolverget aPreToolUsehook onBash(.claude/hooks/no-remote-writes.py) that parses each command and rejects anything that writes to the remote:git pushin any form (including via-C,timeout,sh -c,xargs,eval),git remotemutations,git configof aliases/remotes/push/credential settings,git send-email/svn, and everyghcommand except read-only views andgh apiGETs. Commit, checkout, switch, fetch, pull, add, status, diff and log remain allowed. Pushing and PRs are the orchestrator's or the user's job.python3 -I .claude/hooks/no-remote-writes.py --self-testruns 41 allow/block cases.Bash sandbox (strict) and git-level push block
.claude/settings.jsonturns on the Claude Code Bash sandbox for this repo: no unsandboxed retry, fail if unavailable, network limited toapi.anthropic.com,github.com,api.github.com,*.nuget.org; writes allowed to the dotnet/NuGet home dirs; private SSH keys read-denied. On Linux it needsbubblewrapandsocat.Three things had to be worked around to make the .NET toolchain run inside it (details in CLAUDE.md):
/tmp/MSBuild<pid>; the seccomp filter blocks Unix sockets and/tmpis read-only, so solution builds hung for 5 minutes and reported FAILED with 0 errors. Fixed withallowAllUnixSockets+allowWrite: ["/tmp"], withdenyReadhiding the D-Bus buses, SSH agent, X11 and Docker/Podman sockets so the usual escape routes stay closed (verified:systemd-run --user,busctl,ssh-add -lall fail inside).LocateRepositoryfails on the/dev/nullmount the sandbox places over.gitmodules;env.EnableSourceControlManagerQueries=falseskips it for builds under Claude Code only (CI unaffected).git fetch/pull/push/ls-remoteand read-onlyghcommands run viaexcludedCommands. Workers still cannot push: their hook blocks the command first.no-remote-writes.pyadditionally sets a per-worktreeremote.*.pushurlto a dead path (viaextensions.worktreeConfig) whenever it runs in a linked worktree, so a push the parser misses fails at the git level. The primary checkout is never touched.Notes
model,effort,tools,disallowedTools,color).Test plan
name/model/tools/disallowedTools/hooksclaude -p --settings .claude/settings.jsonsessions):dotnet build,dotnet test(998 tests pass),dotnet format --verify-no-changes,codeguard rules test,git ls-remote,gh pr viewall succeed;touch ~/x, directcurl, reading a private key,systemd-run --user,busctl,ssh-add -lall failno-remote-writes.py --self-test: 41/41 cases pass; stdin protocol checked (git pushexit 2,git commitexit 0)docs/orchestration/<file>.md, blocks source paths and nested paths (exit 2)🤖 Generated with Claude Code