Repository navigation
agents: architecture guides per area + pstack factory glue - #1292
Draft
alexanderludwig wants to merge 24 commits into
Draft
alexanderludwig wants to merge 24 commits into
alexanderludwig wants to merge 24 commits into
Conversation
alexanderludwig
force-pushed
the
tooling/claude-factory
branch
from
October 20, 2026 20:17
66ce8bd to
e76499d
Compare
alexanderludwig
force-pushed
the
tooling/claude-factory
branch
4 times, most recently
from
October 21, 2026 03:20
bff0c1f to
5a2cd42
Compare
…e import Every judgment step is a fresh Claude Code session pinned to GesundAI through the audit proxy, in its own Herdr pane; every gate is a script. Stages: intake (sharpen into a test plan), red, fix, verify (verify-antseed table as data, doctor first, sandbox before/after in a scratch worktree), blast radius, three-model review (opus-5.5, fable-5.1, gpt-6-astra) plus judge, no-comments, publish (dry run only), reflect. Inputs: proposed CLAUDE.md invariants and the security-critical paths list. Co-Authored-By: Claude <noreply@anthropic.com>
…ce deps The first dry run's green gate failed at both commits with `Failed to load url @antseed/protocol/billing`: a fresh worktree had only `pnpm install`, and workspace packages resolve each other through their gitignored dist/. red-green.sh now runs `pnpm --filter '<pkg>^...' run build` after install (what CI has before a package's tests). gate-red.sh also runs the red in a fresh worktree, so this shows up before any fix is written. red() and fix() resume idempotently: existing commits are gated first and the session is skipped when the gate passes. Co-Authored-By: Claude <noreply@anthropic.com>
The second dry run stopped at the read-only gate: the verify session's `ln -sfn $(readlink -f $d) ...` over an unmatched glob created a symlink named `*` in the fix worktree (its persisting cwd). Read-only stages (intake, verify, blast radius, reviewers, judge) now start in runs/<slug>/scratch/<stage> with the worktree added by path; native-step cds the pane into --cwd so the transcript path matches; the preamble keeps scratch and evidence under the run dir and asks for a clean `git status` before answering; verify cites the gates' fresh red/green instead of rebuilding them by hand; stop() logs a decision row. Proposals from the run's reflect (read-only bind mount, Stop hook, quarantine) stay open. Co-Authored-By: Claude <noreply@anthropic.com>
…eviewer Run 3 stopped with `could not split pane wB:pN`: the judge pane was split from reviewer A's pane, which native-step closes after a successful, audited session. The judge now gets a pane from the run tab's root pane. Resuming the review stage redoes a round with no judgment and reuses the reviews already answered in it, instead of skipping to the next round. Co-Authored-By: Claude <noreply@anthropic.com>
In run 3, reviewer C (gpt-6-astra) never saw the diff: `git -C <wt> diff` does not match the `Bash(git diff:*)` allow prefix, so plan mode asked the model's safety classifier, and gpt-6-astra answers that with HTTP 400. The driver now writes review-input/ (diff.patch, log.txt, changed files at HEAD) and the review and judge prompts point there for Read. A review whose session got non-200 responses carries an audit note for the judge. Readers no longer get the preamble's decision-log rule. Co-Authored-By: Claude <noreply@anthropic.com>
`git -C <dir> push` matched no deny prefix; only the dead pushurl stopped it. Session settings now come from lib/session-env.mjs with five independent layers: deny rules for every push form, remote/url/hooks/credential config, inline `git -c` and `--no-verify`; `url.<dead>.pushInsteadOf` for https, http, ssh and git@ (catches inline `-c remote.origin.pushurl=<real>`); a dead origin pushurl; core.hooksPath with a pre-push that refuses unless FACTORY_ALLOW_PUBLISH=1; and no credentials (helpers reset, unusable GH_TOKEN, prompts and ssh off). scripts/check-push-gap.sh proves seven routes refused (dry-run pushes to a throwaway ref) plus the hook and publish gates; a pinned session proved the deny rules refuse `git -C <wt> push`, `cd <wt> && git push`, `git -c ...` and `git remote set-url`. Co-Authored-By: Claude <noreply@anthropic.com>
…eer 1, item 2) - Review reuse on resume needs the review's recorded HEAD to equal the current HEAD and the review to be undegraded (no non-200 responses, e.g. gpt-6-astra's refused classifier calls); a sidecar review-r<n>-<model>.json records head, tag, degraded and refused codes. - Every terminal outcome writes a decisions row: driver errors (labelled FAILED (driver error)) and PASS/STOPPED, not only gate stops. - auditStep reports `degraded` for any non-200 message response. - gate-green fails when the fix commit touches a test file. - verify.sh copies each sandbox report directory into verify/<label>/reports. - Preamble states the Bash tool's 600 s cap; blast radius no longer offers a /tmp git worktree. (The judge-pane anchor fix landed earlier in cfd131362.) Co-Authored-By: Claude <noreply@anthropic.com>
…g (steer 1, item 3, D3) scripts/run-bounded.sh runs a command with a deadline and, on timeout, kills every process it started (they carry a unique FACTORY_RUN_ID in their environment, which survives setsid and reparenting; TERM, then KILL), and also reaps background leftovers of a command that exits on its own. verify.sh uses it instead of `timeout`; scripts/run-scenario.sh is now the only way a verify session may run an extra scenario (deadline, `pnpm sandbox down`, recorded). native-step counts the session's background-task output as activity and, when a tool call has been silent for --tool-ceiling-min (20), presses Escape and tells the session to finish without it (a second hang fails the step). Proofs: check-run-bounded.sh (hung tree with a setsid'd grandchild and xvfb-run: exit 124, nothing left) and a pinned smoke session whose silent 7-minute command was interrupted after 1 minute and which then answered. Co-Authored-By: Claude <noreply@anthropic.com>
D1: run-with-evidence does not exit after a failed desktop launch; reproduced through run-scenario.sh (scenario FAILED at waitForLoadState, tree killed by the 240 s deadline, `Failed to shutdown` in desktop-main.log). D2: the desktop window never loads under Xvfb on this VPS; `--disable-gpu` was tested and removes the GPU errors but does not fix the load, so the cause is unverified. Co-Authored-By: Claude <noreply@anthropic.com>
…(steer 1, item 5) tooling/claude-factory is rebased onto origin/codex/sandbox-stack (a441f1d), so .claude/skills/verify-antseed and sandbox-test are files next to the factory. Prompts point at them, verify-plan --audit reads the local table, and preflight requires the sandbox stack to be an ancestor of the factory branch. Co-Authored-By: Claude <noreply@anthropic.com>
… 1, item 6, D4) The sandbox-test / verify-antseed / CLAUDE.md / e2e README part of item 6 landed on codex/sandbox-stack as d21c468; after the rebase only this factory README line remains here. Co-Authored-By: Claude <noreply@anthropic.com>
Claude Code asks before any write under the project's .claude/ even in acceptEdits mode; a factory session can wait on that prompt forever, and the stall nudge (Enter) would pick its default "Yes". In 2.1.302 no allow rule satisfies the check (tested: Edit/Write(//<root>/.claude/**) and the grant's own Edit(/.claude/**), in the settings file and in --allowedTools). So: - prompts are detected from the transcript (a Write/Edit with no tool_result, or Herdr `blocked`), not the screen, which a narrow pane garbles; - a file under the session's own write root's .claude/ gets Claude Code's session grant (option 2), selected by native-step; the driver passes the write root only for stages that write product files (not readers, read-only stages or reflect); - every other prompt is refused with Escape and fails the step at once (exit 5, a clear driver outcome); - the stall nudge never presses Enter while a tool call is pending. Proof (pinned opus-5.5 smoke sessions): A wrote <root>/.claude/skills/smoke/ SKILL.md with no human (grant at +5 s, done in 27 s); B, a .claude/ write outside its scope, was refused and failed 5 s after the prompt, nothing written. Co-Authored-By: Claude <noreply@anthropic.com>
…vers It scanned every Xvfb and sleep on the machine, so any other Xvfb (another session's desktop run) failed it. run-bounded.sh now prints its run id; the check reads it and lists only processes whose /proc/<pid>/environ carries that FACTORY_RUN_ID. Proven with a decoy `xvfb-run -a sleep 120` running alongside: RUN_BOUNDED OK (exit 124 after 7 s, 7 marked processes, none left). Co-Authored-By: Claude <noreply@anthropic.com>
The dry-run body was 199 lines. Its red section kept only the last 60 lines of output and so omitted the headline -1500000n -> "-1.-5" case. Its security-critical reason quoted the glob's general description, and it leaked machine paths (/root, /tmp, ~/.antseed-sandbox) and factory-internal file references. scripts/pr-body.mjs now writes, in order: - the security marker naming only the matched glob and files - the issue link, or "no GitHub issue: task-file run" - the fix in the fix commit's own words - test level and file - the key red assertion with the red signature, the red summary and the green summary - verify rows pass/fail from each row's own commands, with sandbox scenarios and pre-existing failures named - one line per reviewer and the judge verdict - everything else in one collapsed <details> block, with paths cut out publish.sh refuses the body if it contains a path or factory-internal reference, lacks the red signature, has a main part over 60 lines, or has more than one <details>. The old body fails all three content checks: 8 leak lines, 0 signatures, 199 main lines. Co-Authored-By: Claude <noreply@anthropic.com>
… shows both doctor runs Under `## Fix`, the body now adds one sentence naming the files deliberately left unchanged and why. It is generated from the run's scope note (runs/<slug>/scope.json: decided_by, decision, left_unchanged[] with path, what and source, and reason), and the body fails if a listed path does not exist at HEAD. The evidence table now includes the baseline rows, labelled "sandbox, without this change" and "sandbox, with this change", so both doctor runs (before and after the fix) and both teardowns show. The security-glob narrowing stays on the backlog. Co-Authored-By: Claude <noreply@anthropic.com>
…branch names intake.sh --note-file (factory.mjs --note-file) appends the human's notes to task.md under "Operator notes (from the human, not part of the issue)": hints to verify, and decisions reserved for the human. A slug that already starts with the issue number gives fix/<slug> instead of fix/<n>-<n>-.... Co-Authored-By: Claude <noreply@anthropic.com>
--workspace <label> (default bug-<issue>, or <slug> for a task file) makes the driver create that workspace (lib/workspace.mjs), record its id in the run state, and put the run tab, every stage pane, the reviewers and the judge in it instead of HERDR_WORKSPACE_ID. On resume it reuses its own recorded workspace; a label held by any other workspace is refused, never reused. Runs whose state predates this keep their recorded tab's workspace. A slug equal to the issue number gives branch fix/<n>. Proof, scripts/check-workspace.mjs: fresh workspace wC, pinned session in wC:p2 answered (audit ok), the 6 other workspaces were unchanged, and wC was closed: WORKSPACE OK. Co-Authored-By: Claude <noreply@anthropic.com>
Replace the scripted state machine (factory.mjs, stage prompts, gate scripts) with one Claude Code session running pstack 0.15.25's poteto-mode as an autonomous run. The factory now only says where things are, maps pstack's Cursor names to Claude Code, and adds what pstack cannot know about AntSeed. - RUN.md: the first message. Task, exit condition, AntSeed files from the tooling checkout, and the Claude Code mapping (Agent tool, todo file, gate wake watcher, deslop fallback, orch ledger and gates). - pstack-models.md: pstack's per-role model table. Opus writes code, astra verifies, panels mix opus, fable, astra and sol. - agents/astra.md, agents/sol.md: general agents pinned to gpt-6-astra and gpt-6.1-sol. - start.sh: worktree, task, orch store, session settings (GesundAI pin, no push, Claude Code Bash sandbox, deny rules), model preflight, resumable start. - check-push-gap.sh: pushes to a local fixture with positive controls. - verify-antseed: features/ map in pstack's create-verification-skill shape, proof on the matching surface, user-visible review evidence, security-critical paths, and prove.sh for mechanical red and green. - Area CLAUDE.md guides for buyer-core, contracts, node, protocol, cli, gateway and desktop. Tooling branch only, never pushed.
… MB overflowed argv)
… FACTORY_RESUME reopens a session Claude Code makes a --plugin-dir read-only to the session's Bash sandbox, and the plugin was .factory itself, so runs/<slug> (orch ledger, gates) could not be written.
…ude Code mapping - Verification order follows pstack: self-verify, interrogate, deslop and no-comments, then one independent verifier at the code-ready head (Autopilot-full step 4, Orchestrate's Verification). - Cursor's /loop is Claude Code's /loop for Autonomous run step 2. Reasoning level maps to the Agent effort parameter, with a budget line. - Read-only reviewer agents (reviewer, astra-reviewer, sol-reviewer) stand in for readonly: true. - Reflect rows aimed at pstack files are upstream proposals, never local edits. - start.sh prepares the fix and scratch worktrees (forge-std, install, build with the .nvmrc Node), retries network steps, matches model aliases, and gives prove.sh and agent-browser writable dirs in the run.
…their brief names
…y's own dispatcher over pstack playbooks
alexanderludwig
force-pushed
the
tooling/claude-factory
branch
from
October 21, 2026 14:52
5a2cd42 to
2fed5a1
Compare
alexanderludwig
force-pushed
the
codex/sandbox-stack
branch
from
October 27, 2026 04:22
475bed0 to
8672ac9
Compare
alexanderludwig
force-pushed
the
tooling/claude-factory
branch
from
October 27, 2026 04:22
2fed5a1 to
77799e7
Compare
This branch has not been deployed
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.
What this is
A local "factory" that takes one GitHub issue (or task file) to a branch ready for a PR. It's pstack 0.15.25 run as is, plus a thin layer of AntSeed glue. Everything sits under
.factory/.The base is
codex/sandbox-stack(#1145), so this diff shows only the factory. #1145 keeps only the sandbox and theverify-antseedskill (withprove.sh).This PR is the main "make the repo agent-ready" change. It has the architecture knowledge, which any agent reads (factory or not), and the factory glue.
Architecture knowledge
CLAUDE.md→## Design principlesCLAUDE.md→## Invariantspackages/{node,buyer-core,protocol,api-adapter,router-core,web-sdk,contracts},plugins,apps/{cli,desktop},apps/cli/src/gatewayFactory glue (
.factory/)start.shclaudewith pstack and the plugin.FACTORY_RESUME=<id>reopens a session.RUN.mdorchestrator.mdorch/preferences.md(seeded bystart.sh), short reports, a lead that keeps only summaries and checkpoints with Pause safely.CLAUDE.mdrewritepnpm sandbox.add-migrationskillverification.pstack-models.mdsandbox-run.sh--chain localsandbox scenario outside Claude Code's Bash sandbox (sandbox.excludedCommands), because forge panics inside it. Refuses--live,--real-fundsand mainnet.plugin/agents/*astraandsol(model pins) plus read-only reviewer versions.git-hooks/pre-push,check-push-gap.shProcess
The playbook steps are pstack's, referenced and never copied. The dispatcher (
orchestrator.md) is ours. See.factory/README.md→ "The process: pstack's steps, our dispatcher".Tried on
Not a user-facing change
This is dev tooling and agent docs only, so there's no CHANGELOG entry.
Known limits
See
.factory/README.md→ Known limits. localhost stays reachable, the no-push env is a speed bump, and the model pin is set once per session.