Skip to content

Hook restores the canonical clone to main when its branch has already merged #260

Closed

Description

@lukemaj

What: When the Project Direction check finds the canonical AgentsMD clone on a branch whose commits are all in origin/main and whose working tree is clean, it switches the clone back to main itself instead of only reporting source-checkout-off-release.
Why: An agent branched in the live clone for #258 and the branch stayed checked out after PR #259 merged, so every harness read an off-release revision and every session got an unhealthy report until a person noticed.
So what: A worker implements this in bin/agentsmd_instructions.py with tests; it merges after independent review and green CI.

Outcome

A merged, clean task branch left checked out in the canonical clone heals on the next hook run, with the report saying what was restored. Anything else (dirty tree, unmerged commits, detached HEAD on a non-release commit, unreadable Git) keeps today's unhealthy report and action text.

Problem Statement

On 2026-10-20 the clone /home/luke/dev/toolboxmd/agentsmd sat on fix/258-reminder-reasoning (switched 11:26 Warsaw per the reflog) after its PR #259 merged at 11:32. Finalization says whoever merges retires the branch in the same step, but nothing runs that step when the user merges on GitHub or an agent skips it. The hook detected it but only told agents to fix it, and agents correctly refuse to touch what may be someone's active work.

Solution

In guard_checkout, before returning source-checkout-off-release: if the current branch is not main, the working tree has no tracked or untracked changes, and every commit on the branch is reachable from the local origin/main ref (no network fetch in the hook), run git switch main and git merge --ff-only origin/main, then re-evaluate and report a status such as source-checkout-restored naming the branch it left. Never delete the branch (deletion stays with finalization), never fetch, and fall back to today's report on any Git error. Squash-merged branches whose commits are not ancestors keep the manual path.

Elon record

  • Requirements and who asked: the user asked (Chromeria thread, 2026-10-20) that a merged branch left in the canonical clone not keep every harness off main.
  • Deleted: a new prose rule (the orchestration ban on writes in main checkouts and finalization's same-step retirement already exist and were broken once); network fetches in the hook; automatic branch deletion; handling squash merges.
  • Bottleneck: the hook detects the state but only instructs, and agents rightly will not modify possibly active work.
  • Checked myself: guard_checkout in bin/agentsmd_instructions.py:124-175; clone reflog; PR fix: reply reminder asks for the Elon method in reasoning (#258) #259 merged with its commit an ancestor of origin/main; restored the clone by hand and confirmed inspect reports valid-stable-link.

Acceptance criteria

  • Clean branch fully contained in origin/main: the hook switches to main, fast-forwards, and reports healthy with a restored note.
  • Dirty tree, untracked files, unmerged commits, or a detached non-release HEAD: no Git mutation; today's status and action text.
  • Git errors during restore leave the clone as found and report today's unhealthy status.
  • Release-tag installs (detached at a tag) are unaffected.

User stories

  1. As the user, I want a merged task branch left in the live clone to heal itself, so that every harness reads main without me noticing and fixing it.
  2. As an agent, I want the hook to fix only provably safe cases, so that I never lose someone's active work.

Implementation decisions

  • Containment check against local origin/main only; no fetch.
  • Branch deletion stays with finalization.

Design review

  • Independent review: none before filing; the PR gets an independent review.
  • User decisions: approved the hook auto-restore in the Chromeria thread on 2026-10-20.

Testing decisions

  • Extend the existing guard_checkout / instruction-status tests with temporary Git repos covering each acceptance case.

Non-goals

  • Fetching, branch deletion, squash-merge detection, cleaning other worktrees.

Blockers

None.

Required proof

  • Focused tests for every acceptance case pass, the existing suite stays green, CI green, independent review on the final head.

Further notes

Contributes to the Objective: a fresh agent loads current direction and flags stale truth without manual routing; this removes a case that needed a human.

Activity

  1. lukemaj commented on Oct 20, 2026

    @lukemaj
    ContributorAuthor

    What: The requested guard change is implemented and pushed as PR #261 at 4615143db9180931c24e7c0f8d6ad41787f19410.
    Why: A clean branch contained in local origin/main can be restored safely, including rollback after a partial Git failure.
    So what: All required proof and independent review pass on this exact head; final merge remains with the user.

    Canonical handoff

    • PR: fix: restore merged canonical clone branches to main #261
    • Branch: fix/260-restore-merged-clone; workspace: /home/luke/.t3/worktrees/agentsmd/fix-260-restore-merged-clone.
    • Starting and intended base: 2fc48503329af63a9f8d5b31fe3dd6d0e71f7d59 (main); current head: 4615143db9180931c24e7c0f8d6ad41787f19410.
    • Version: 17.4.4 to 17.4.5 via versionctl, all mirrors and CHANGELOG committed atomically with fix: restore merged canonical clone branches to main.
    • Authority: implementation, proof, commit, push, PR and independent review for Hook restores the canonical clone to main when its branch has already merged #260. No merge authority exercised; no release, publication, or installation.
    • Acceptance implementation: healthy restored status names restored_from; dirty/untracked/unmerged/detached states retain the existing report; failures roll back tracked files and main's ref; release-tag installs retain their status.

    Proof

    • python3 -m unittest tests.test_live_checkout_guard tests.test_instruction_actions -v: PASS, 23 tests, including the new review regressions.
    • python3 -m unittest discover -s tests -p 'test_*.py': PASS, 512 tests in 254.936s on the replacement candidate.
    • python3 -m unittest discover -s tools/versionctl/tests -p 'test_*.py': PASS, 7 tests.
    • tools/versionctl/bin/versionctl release-check --sha HEAD: PASS on the clean candidate.
    • git diff --check: PASS.
    • CI: https://github.com/toolboxmd/agentsmd/actions/runs/39404676813/job/118567624741, validate PASS.
    • The positive restore cases first failed with the old guard. A real main-ref lock then exposed a partial-merge rollback gap, fixed by restoring the original clean files during the switch back. Regression tests cover this plus injected errors before and after Git effects.
    • Existing non-failing trigger-audit ResourceWarnings recorded with their owner: Procedure trigger audit: measure which operations procedures fire, then fix the worst #164 (comment).

    Review correction and learning

    Round 1 found two blockers, both accepted. Reading symbolic refs in full avoids Git producing a shortened name unusable by switch when a tag shares the branch name. Startup caching must track the bytes already loaded before the hook, rather than bytes the hook has just restored. The guard now preserves the original digest as restored_from_sha256, and the existing startup consumer records it. Three regression tests first failed (seven subcase failures), then passed, including first and following events on all five harnesses.

    These were missing proof cases at the existing owners, not missing general instruction rules. The corrections and deterministic regressions belong to the guard, its direct session-loader consumer, and the existing guard test file; no global rule or preference was added. The amendment preserves one SemVer transition and was pushed with an exact-old-head force lease.

    Review and remaining state

    Independent reviewer dispatched through T3 delegate_task, prismRole: reviewer, task request agentsmd-260-review-4615143-round-2. review/independent is success on this exact head, created by lukemaj, with published round-2 verdict. The reviewer independently reproduced both earlier blockers on the rejected head, reran their regressions successfully on this head, ran all 23 focused tests and four additional isolated rollback/hash checks, and removed its review artifacts. Reviewer owns only temporary review artifacts and GitHub verdict/status, not tracked source. The implementation agent remains owner of acceptance and completion.

    Canonical live install has not been switched, edited, or used as a test target. Tests use temporary repositories. Task worktree remains for PR review and merge; retire only after terminal disposition. Behavioral Live Verification remains pending after release through normal user work. All four acceptance criteria and required deterministic proof are satisfied. The worktree is clean; the PR is open, pushed, review-ready, and unmerged. No required proof remains pending. The task owner retains the worktree for this open PR; its merger must arrange same-step retirement after the user merges.

    Elon record

    • Requirements and who asked: The user and Hook restores the canonical clone to main when its branch has already merged #260 require local-only safe restoration in the existing guard, unchanged unsafe reports, proof, versioning, PR, and independent final-head review.
    • Deleted: Fetches, branch deletion, squash-merge handling, a new system, and live-install writes.
    • Bottleneck: The guard only reported a safely recoverable merged branch; restoration and both review corrections now pass complete proof and independent review.
    • Checked myself: Read the Issue, traced consumers, reproduced failures, inspected the full diff and version mirrors, ran all required local proof, verified the pushed PR head and green CI, and linked the PR to T3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions