Skip to content

senior-dev: no wip commits, its own commit message, and hand-backs over self-fixes - #1716

Open
ZeroPoint95 wants to merge 15 commits into
devfrom
zeropoint95/senior-dev-no-wip-commits
Open

ZeroPoint95 wants to merge 15 commits into
devfrom
zeropoint95/senior-dev-no-wip-commits

Conversation

@ZeroPoint95

Copy link
Copy Markdown
Contributor

senior-dev's branches now carry clean history: no per-write wip commits and no senior-dev author. The run's work becomes codeaf's one commit, with a message senior-dev writes. On the turn a run ends, the chat now hands follow-up fixes back to senior-dev instead of patching its branch itself.

Prompted by #1693: about 50 wip(edit): <path> commits authored senior-dev <senior-dev@localhost>. With this repository's squash merge (body = every commit message), all of them would have landed in dev's history. #1696 replaced it.

1. No wip commits (8f696e069)

  • EagerCommit committed every file the model wrote or edited. It is deleted, along with its SENIOR_DEV_EAGER_COMMIT opt-out, the recorders' CommitsOnWrite, and on codeaf's side SENIOR_DEV_EXPECTED_BRANCH / DelegateSetup.Branch, which existed only to keep those commits on the run's branch.
  • Nothing else depended on those commits:
    • senior-dev snapshots through a temporary index and keeps its candidates as commit-tree objects outside the branch.
    • codeaf already commits whatever a run leaves, crash or not.
  • How senior-dev plans, implements and verifies is unchanged.
  • TestAWriteAndAnEditLeaveTheRunsBranchWhereItWas fails on dev with senior-dev wip(write): added.txt.

2. senior-dev is asked not to commit, and writes the commit message (62aa22777)

  • The line codeaf puts at the head of every brief now tells the program to leave its work uncommitted and not to push, switch branches or rewrite history, even where the brief asks it to.
  • It also asks for the commit message in .senior-dev/commit-message.
  • codeaf reads that file before the notes leave the copy, and uses it for its end-of-run commit, adding its credit lines once. With no message, the commit falls back to the task title over the run's ending.
  • This is steering, not enforcement: no git command is blocked, and a commit the program makes anyway stays on its branch.

3. Handing back counts as fixing it yourself (42c694411)

  • prompts/program-outcome.md used to tell the chat to finish "a small, clear gap" itself in a worktree. So after a senior-dev run, the chat did follow-ups itself.
  • That turn is the one moment a hand-off continues on the program's own branch. The page now says a hand-back to the same program counts as fixing it yourself, and the chat edits the branch itself only for trivial gaps or once retries are spent.
  • The page is read only on that turn, so the prompt-prefix budget is untouched.
  • Out of scope: follow-ups you ask for in a later message still start a fresh run from your checkout.

Manual:

  • senior-dev.md gains "Does senior-dev commit or push — no wip commits, who writes the commit message", and its sections on where the work goes and what codeaf does when senior-dev ends are updated.
  • delegates.md is updated to match.
  • New questions in the manual's retrieval tests (internal/manual/chat_test.go) check that "why does senior-dev make wip(edit) commits in my pull request" and "who writes the commit message for senior-dev's work" reach the senior-dev page.

Checks run locally

  • Passed: build and vet; full internal/seniordev/{util,tool,config,app} and internal/run; focused internal/session and cmd/codeaf; internal/manual and untagged internal/e2e; make test-laws.
  • TestStandingIsolationRecordsItsCopyBeforeWorkerInitialization fails, and fails the same way on clean dev (macOS /var vs /private/var). A separate fix is in progress.

🤖 Generated with Claude Code

ZeroPoint95 and others added 5 commits October 1, 2026 09:06
Every file senior-dev's model wrote or edited was committed on the run's
branch as it happened, `wip(write): <path>` / `wip(edit): <path>` under the
identity `senior-dev <senior-dev@localhost>`. It was a checkpoint from the
benchmark harness senior-dev was built in, and under codeaf it bought
nothing: the run works in a private worktree copy on a branch of its own,
its recorder snapshots through a temporary index and keeps its candidates
as commit-tree objects outside the branch, and codeaf commits whatever the
run leaves as one commit when it ends, crash or not. What it cost was
#1693 — fifty wip commits with senior-dev as an author, every one of which
the repository's squash merge would have written into dev's message.

The checkpoint is deleted rather than switched off: EagerCommit and its
opt-out SENIOR_DEV_EAGER_COMMIT, the recorders' CommitsOnWrite, and on
codeaf's side SENIOR_DEV_EXPECTED_BRANCH and DelegateSetup.Branch, which
existed only to fence those commits to the run's branch. The start-time
ignore and input lists stay, because the recorders read them.

A new test drives write and edit in a repository shaped the way codeaf
hands one over, task/ branch and old variable included, and fails on dev
with `senior-dev wip(write): added.txt`. The senior-dev and delegates
manual pages said the wip commits stay and nothing squashes them; they now
say there are none, and a probe asks why a pull request has them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sage for codeaf's commit

A senior-dev run whose brief asked it to commit and push did exactly that:
its model ran `git -c user.name=codeaf … commit` and `git push` from its own
shell, and codeaf's finishing commit found nothing left to take. The owner
wants codeaf, not the program, to own the commit, and chose steering over a
shell that refuses git's writing verbs — parsing every road to git is a
guard that guesses.

So the line codeaf puts at the head of the brief now tells the program to
leave its work uncommitted and not to push, switch branches or rewrite
history, even where the brief below asks it to, and — when the program has
a notes folder of its own, as senior-dev does — to write the commit's
message to `.senior-dev/commit-message`: a subject of at most 72 characters
in the repository's own style, a blank line, and a body saying what changed
and why. codeaf reads that file before the notes leave the copy and makes
it the finishing commit's message, signed once (signOnce, so a line the
program already wrote is not repeated). With no message, or a blank one,
the commit is what it was: the task's title over the run's ending.

Nothing is blocked: a commit the program makes anyway stays on its branch.
senior-dev's own code is untouched. The chat's guide for senior-dev was
not lengthened, because the prompt-prefix budget refuses the bytes and the
brief's head line already overrides a brief that asks for commits.

The senior-dev page gains its own section on whether senior-dev commits or
pushes and who writes the message; delegates.md says the same in brief.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g it yourself

The page the chat reads when a program's run ends told it to finish "a
small, clear gap" itself on the program's branch, in its own worktree,
and to fix or hand back a failure it saw in its own checks. A model reading
that did the follow-up work itself, in a worktree, where the program it had
just used was built for it — and that turn is the one moment a hand-off
carries on from the program's own branch, since the person's next message
starts any later run from their checkout again.

The page now says that wherever it tells the chat to fix or finish
something itself, handing the work back to the same program counts as doing
it, and is the road for anything beyond a line or two; the chat edits the
branch itself only for a trivial gap, or once the program can be sent back
no more. The failed and unverified bullets and the failed outcome's next
line say the same. The page is read on the wake turn only, so the fixed
prompt's byte budget is untouched. The two-hand-back cap is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ZeroPoint95
ZeroPoint95 marked this pull request as ready for review October 1, 2026 13:52
…art has its own test

From the review of #1716. The italic note under "Landing a tree delegate"
still said senior-dev's wip(edit) commits stay on its branch while the
decisions table above it said they ended on 2026-09-30; it now says so too.
And deleting the eager-commit tests took PathIgnoredAtStart's only direct
test with them; a table test makes its rule explicit again — the file
itself or anything under it as a folder, never a sibling sharing its prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AbirAbbas and others added 8 commits October 1, 2026 13:16
With eager commits gone a run's work is always uncommitted, so the
unsubmitted-work nudge and landing turn told every run's model to commit
before verifying, the opposite of its brief, and the patch summary diffed
the base against the working tree, which leaves out untracked files: a run
that wrote three files was shown as "measured its change 1 file · +28 -0",
and one that only added files as "its change is empty". The git-status
finding is gone (the candidate is frozen from the working tree through a
temporary index), and the summary measures the same snapshot tree the run
would hand in, keeping the working-tree diff only when that capture fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The message a program writes for codeaf's finishing commit was read with a
plain open, so a named pipe there hung the finish with the copy held, a
symlink was followed, and a NUL byte made git refuse the commit; a message
of only credit lines or an unchanged copy the repository already tracked
was taken as this run's. It is now read only as a regular file, without
following links or blocking, and those cases fall back to the title and
ending.

A message written early also replaced the run's ending, so a stopped,
failed, limited or broken run's commit read as finished work. The message
is used alone only when the run passed; otherwise the ending follows it
before the credits, and a run codeaf found gone says so.

The brief now also asks the program not to stash, reset, clean, or check
out or restore files over its work, which no longer sits in HEAD. Once a
program can be sent back no more, the wake page agrees with its note: tell
the person what still does not work. Manual and change entry follow.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-no-wip-commits

# Conflicts:
#	internal/run/delegateworker.go
#	internal/session/prompts/program-outcome.md
Brings in #1705 (a carried-on run counts only its own files; a published
branch is pushed, not merged) and #1713. The wake page keeps #1705's push
offer on `passed` and this branch's hand-back lines on `unverified` and
`failed`, and speaks to the model in the second person once retries are
spent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The check that a tracked commit message is not this run's own kept a
starting commit of its own (MessageBase), while #1705's ownBase already
answers where this run began, carried on or not. It reads ownBase, and the
extra persisted field is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…filled

With #1705's text beside this branch's, the senior-dev sections on what
codeaf does when a run ends and where its work goes outgrew a retrievable
section, and the "codeaf committed to dev" probe stopped reaching its page.
The hand-back rule, the checks-passed-but-not-submitted ending and the
finishing commit's credit get headings of their own, taking the work home
is split from why a branch was kept, and an automatic hand-off is the rest
of this work, as the wake page says, not a next piece.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in #1689 (senior-dev can be told something while it works). Its
child environment keeps the steering inbox through childEnv and no longer
passes SENIOR_DEV_EXPECTED_BRANCH, whose DelegateSetup.Branch this branch
removed with the wip commits it fenced.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Takes in the branch's own merge of dev (728ddb0) so the push is a
fast-forward; dev's content is already here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@AbirAbbas

Copy link
Copy Markdown
Collaborator

Taking over: checked by hand in the real binary with throwaway repos — a finished run, a run stopped part-way, a run whose codeaf was closed mid-run, a run started by a dev build and finished by this one, a steering note sent from the run's page, and a carried-on run. Each leaves one commit per run with senior-dev's own message, no wip( commits, and every file it wrote on the branch; the carried run's ending still reads 2 files past <commit>, where the last run left it.

Pushed:

  • ea9e02c43 — senior-dev's unsubmitted-run nudge told its model to commit before verifying (with nothing committed any more, that fired on every such nudge), and "measured its change" diffed the working tree, so new untracked files went uncounted (1 file · +28 -0 for a run that wrote three files; its change is empty for one that only adds files). The finding is gone and the summary measures the snapshot tree the run would hand in.
  • 402e7e5f1 — the commit message is read only as a regular file (a named pipe there hung the finish with the copy held; a symlink was followed); a NUL byte, credit lines only, or an unchanged copy the repo already tracked falls back to the title and ending. A message written early no longer hides that the run did not pass: stopped, failed, limit, crashed, unverified and gone runs carry the ending after the message. The brief also asks the program not to stash, reset, clean, or check out/restore over its work, which no longer sits in HEAD. Once retries are spent the wake page now says to tell the person, as its footer already did. Manual and change entry updated.
  • 86b398ee6 — the stale-message check uses senior-dev: a run that carries on a branch counts only its own files, and a published branch is pushed, not merged #1705's ownBase rather than a second persisted start commit.
  • d3f2a4244 — senior-dev and task-landing manual sections split after the merge, where one probe stopped reaching its page.
  • 85996df3a, 05429ff90, e198cbc0c — merges of dev (senior-dev: a run that carries on a branch counts only its own files, and a published branch is pushed, not merged #1705; senior-dev can be told something while it works, from its page or the chat #1689, whose child environment keeps the steering inbox without SENIOR_DEV_EXPECTED_BRANCH) and of this branch's own merge of dev.

Left for later:

  • A file the run writes and then ignores through its own .gitignore edit is not committed (an eager commit used to have tracked it). Force-adding newly ignored files would sweep shell-made build output onto the branch, so it is left as is.
  • With no per-write checkpoint, the model's own git stash, git checkout -- . or git reset --hard now hides or drops work that used to be in HEAD; the brief asks it not to, nothing enforces it.
  • RunSpec.ProgramBranch has no production reader now.

Brings in #1662.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants