Skip to content

fix: prompt_sync helpers push the current branch, not a hardcoded main - #178

Merged
Jammy2211 merged 9 commits into
mainfrom
claude/automind-task-planning-wxq004
Aug 10, 2026
Merged

fix: prompt_sync helpers push the current branch, not a hardcoded main#178
Jammy2211 merged 9 commits into
mainfrom
claude/automind-task-planning-wxq004

Conversation

@Jammy2211

@Jammy2211 Jammy2211 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

The PyAutoMind half of PyAutoBrain#225, plus the Mind bookkeeping for PyAutoBrain#223/#224 that this session produced. Both are on this branch because the session was scoped to it; see "Scope note" below.

The defect — corrected after measurement

scripts/prompt_sync.sh — both helpers ended in git push origin main regardless of what was checked out:

prompt_sync_push() {
  ...
  git commit -m "$subject" && \
  git push origin main )
}

create_issue step 6 and start_dev step 7 both instruct an agent to call it.

An earlier revision of this PR described this as "pushes Mind straight to main". That was half right, and not the half that fires most often. git push origin main pushes the local main ref — never the commit just made on a feature branch. Measured against real bare remotes, the old behaviour splits by the state of local main:

local main vs remote what the old script did
equal — the normal case, a session that branched from it push is a no-op, exits 0, and the committed work never leaves the machine. The caller is told the sync succeeded.
ahead — unpushed commits on main publishes those to remote main, unreviewed, and still leaves the branch work local.

The first row is the common one and the quieter danger: in an ephemeral cloud container, "committed, reported synced, never pushed" is silent loss. The second is the review bypass. Same root cause; both fixed by pushing HEAD.

The single-branch laptop flow is byte-identical — there the current branch is main. Verified across four scenarios (nothing staged, tracked change, untracked-only, deletion): old and new produce the same commit count, same refs, same remote state. A detached HEAD is now refused rather than guessed at.

One regression caught while fixing it

prompt_sync_push is restructured to drop its subshell. With the naive ( ... ) && _push shape, the documented "no-op if nothing is staged" early return falls through to the push, so a caller with no changes would push anyway. The early return now precedes the push, and test_push_is_still_a_no_op_when_nothing_is_staged pins it.

Test Plan

  • pytest tests/134 passed (127 existing + 7 new)
  • python3 scripts/lifecycle.py check — OK
  • 5 of the 7 new tests fail against origin/main's script, verified by swapping it in. A test that cannot fail is decoration.
  • Old vs new behaviour on main compared directly across 4 scenarios — identical

The tests drive the real script against throwaway git repos with real bare remotes, because that is the only way to observe which ref actually moved; grepping the source for the string would pass on a script that still pushed the wrong branch by another route.

The two halves of the bug get their own tests, since they are separate failures: test_committed_work_actually_reaches_the_remote and test_a_branch_push_never_advances_main.

The most striking pre-fix failure: from a detached HEAD, the old script pushed main -> main.

Scope note — why this branch carries two things

The session was scoped to claude/automind-task-planning-wxq004, so all Mind changes landed here. Alongside the fix, the branch carries the registry bookkeeping for the tasks that produced it — filing PyAutoBrain#223/#225, the draft/active/ lifecycle moves, and the active.md entries.

That bookkeeping is ordinary Mind state and should land regardless. If you would rather review the fix in isolation, say so and I will split the scripts/ + tests/ changes onto their own branch.

Related

  • PyAutoBrain#225 — umbrella for all three defects; stays open until this and PyAutoBrain#226 both land
  • PyAutoBrain#226 — the other two defects (conflict guard fails closed; installer tests unpinned). CI green on both legs.
  • PyAutoBrain#224 — the task during which all three were hit

claude added 9 commits August 10, 2026 18:23
draft_staleness_detection_signals.md is DELIVERED for legs 1 and 2 (the
lifecycle.py gate keys and the intake reconcile re-rank). Leg 3 — an
upstream-repo read — is the only route to the two findings that leave no
Mind-local evidence, and its own delivery note says so. One prompt is one
task is one PR, so it is split out rather than re-opening a delivered
prompt; the parent now points at it.

Filed by hand after the Intake Agent mis-classified the raw text as
bug/PyAutoFit — it latched onto the counter-example prose rather than the
work. Corrected to feature/pyautobrain; the Feature Agent parses the
result as feature/pyautobrain, medium, high, direct, library workflow.

Baselines verified at split time and recorded in the prompt: reconcile
flags 29 of 136 scanned (7 high); no --repo flag exists in _intake.py's
argparse; and nothing under PyAutoBrain/agents/ performs any network
access, which is why leg 3's opt-in flag needs an explicit policy line.

Also verified the trap the acceptance criterion turns on: all five
identifiers named by test_mode_bypass_ordered_assertion_ties.md are
present on PyAutoFit main, yet that prompt is confirmed NOT shipped — so
the mode must report needs-review with evidence, never a shipped verdict.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
Routes leg 3 of the staleness work into the dev workflow. PyAutoBrain#223
carries the two-level plan; the prompt advances draft/ -> active/ and is
registered in active.md as library-dev.

Conflict check clean at registration (worktree_check_conflict exit 0, no
other task claims PyAutoBrain or PyAutoMind). The repos: list is left
empty per the schema — no branch exists yet, and any 2-space `- Repo`
bullet would read as a live worktree claim.

Committed by hand rather than via prompt_sync_push: that helper hardcodes
`git push origin main`, which is wrong for a branch-scoped session. Mind
changes for this task go to claude/automind-task-planning-wxq004.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
Records the PyAutoBrain claim per start_library step 4's web-github variant
(repos bullet, no worktree: field) now that feature/reconcile-upstream-repo-mode
is pushed at 875330f.

Corrects the conflict-check line: the run recorded at start_dev time was
VACUOUS. worktree_check_conflict resolves active.md under $PYAUTO_MAIN, which
defaults to $HOME/Code/PyAutoLabs and does not exist in a cloud session, so it
read no file and returned 0 = "no conflict". Re-run with PYAUTO_MAIN=/workspace
it confirms the same conclusion for real: the only other live claim is
profile-validation-resample-recovery on PyAutoGalaxy, no overlap.

The guard failing OPEN is logged as a follow-up. A cloud or CI session running
the documented command gets a green light that means nothing.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
…n#224)

Records the open PR and the ship-gate outcome. The documented fallback gate
returned RED (Heart is unreachable from a cloud session, so pytest -x is the
gate) on two tests/test_skill_install.py failures. A human acknowledged the
reason and authorized the PR.

CI then vindicated that call: both pytest legs (3.12, 3.13) are SUCCESS on
875330f, so those failures were purely local to this container — install.sh
takes its web-github branch when $HOME/Code/PyAutoLabs is absent and never
performs the work the test asserts on. They were also proven pre-existing at
merge-base a50efc3 with the diff absent.

The prompt stays in active/ until merge, when the ship skills advance it to
complete/2026/08/.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
The PyAutoMind half of PyAutoBrain#225. Both helpers ended in
`git push origin main` regardless of what was checked out. create_issue step 6
and start_dev step 7 both instruct an agent to call them, so a branch-scoped
session — a cloud session with a designated branch, or any PR-based flow —
that followed the documented steps verbatim pushed Mind straight to main,
bypassing review. In this session it was caught only because the helper was
inspected before use; the documented path would have violated the branch
requirement.

Pushing HEAD leaves the single-branch laptop flow byte-identical (there the
current branch IS main) while making a branch-scoped checkout do the right
thing. A detached HEAD is refused rather than guessed at.

prompt_sync_push is restructured to drop its subshell: with the old
`( ... ) && push` shape the "no-op if nothing is staged" early return would
have fallen through to the push, so a caller with no changes would have pushed
anyway. The early return now precedes the push.

Tests drive the real script against throwaway repos with real bare remotes,
because only that shows WHICH ref actually moved; grepping the source would
pass on a script that still pushed the wrong branch by another route. Verified
they fail against the pre-fix script — 3 of 5 do, including the detached-HEAD
case, where the old script pushed `main -> main`.

Also files the prompt for the whole three-defect task.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
Both PRs open. Records the three defects, the fixes, and a correction to the
initial diagnosis of the installer-test failure: it was not the installer's
web-github branch, it was PYAUTO_ROOT defaulting to the repo's grandparent, so
a clone at lowercase pyautobrain never resolves PyAutoBrain/skills. The issue
body was corrected before implementation.

PyAutoBrain pytest is now 331 passed with nothing ignored — green in a cloud
session for the first time, which retires the false-RED ship gate that cost a
human acknowledgement on #224.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
lifecycle.py check flagged DRIFT: the prompt sat in draft/ while active.md
listed it as an issued task. This is create_issue step 5, which was skipped
when going prompt -> issue -> implementation directly.

Caught late because the check ran in an `&& tail -2` pipeline, so the shell
saw tail's exit status rather than the check's.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
…lly hits

Found auditing this branch against origin/main. The write-up said the old
helper "pushes Mind straight to main". Measuring it against real bare remotes
shows that is only the half that needs local main to be AHEAD.

`git push origin main` pushes the local main REF, never the commit just made on
a feature branch. So when local main equals the remote — the normal case for a
session that branched from it — the push is a no-op, exits 0, and the committed
work never leaves the machine while the caller is told the sync succeeded. In an
ephemeral cloud container that is silent loss, and it is the case that fires
most often. Publishing unreviewed main commits is the other half.

Two tests added for the two halves, since they are separate failures:
test_committed_work_actually_reaches_the_remote (the work is ON the remote) and
test_a_branch_push_never_advances_main (an unpushed local main commit is not
published as a side effect). Both fail against origin/main's script; 5 of the 7
now do. 134 passed.

The fix itself is unchanged and already correct — pushing HEAD addresses both
halves. This corrects the description and the coverage, not the code.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
Conflict in active.md: main appended workspace repo bullets to the
profile-validation-resample-recovery entry while this branch added two new task
entries immediately after it. Both sides kept — their bullets complete that
entry's repos: list, then the new entries follow. Verified the claim parser
still reads every row (worktree_list_claimed returns all 7).

Also corrects a stale count in this branch's own entry: the Mind tests that fail
against the pre-fix script are 5 of 7, not 3 of 5, after the audit added a test
per half of the prompt_sync defect.

lifecycle check OK, 134 passed.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PY39MRi1oPbxhhr6tDToQU
@Jammy2211
Jammy2211 merged commit 8bb91f9 into main Aug 10, 2026
2 checks passed
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