Skip to content

Harden Phase 8's rebase fence and state the merge-authorization precedence rule - #119

Merged
dmccoystephenson merged 4 commits into
mainfrom
fix/phase-8-verification-and-merge-precedence
Aug 22, 2026
Merged

Harden Phase 8's rebase fence and state the merge-authorization precedence rule#119
dmccoystephenson merged 4 commits into
mainfrom
fix/phase-8-verification-and-merge-precedence

Conversation

@dmccoystephenson

@dmccoystephenson dmccoystephenson commented Aug 16, 2026

Copy link
Copy Markdown
Member

Summary

Three Phase 8 defects are corrected in create-dev-loop.md. All three were
reported from generated instances or prior self-audits, and all three live in
the same neighbourhood of the template — the merge phase and its "Branch is
behind main" Edge cases entry — so they are batched as one coherent change.

  • Post-rebase verification no longer runs a subset (Phase 8's rebase fence force-pushes on TEST_CMD alone, so a lint-gated required check survives it #115). The rebase fence
    verified with {{TEST_CMD}} alone and then force-pushed on the strength of
    that single result. Where a repository's required checks also run a formatter,
    linter or static analysis, a branch could be pushed still-red and the failure
    rediscovered from CI minutes later. The fence now runs the same verification
    set Phase 3 runs ({{COMPILE_CMD}}, {{TEST_CMD}}, {{#if LINT_CMD}}), and
    an accompanying paragraph states that where the repository's required checks
    exceed that set, those must be run too.
  • (stale info) is disambiguated (Phase 8's bare --force-with-lease has three failure causes that share one '(stale info)' message #117). A bare --force-with-lease needs a
    maintained remote-tracking ref, which a restricted clone does not have; the
    explicit --force-with-lease=<branch>:<sha> form fixes that but rejects an
    abbreviated SHA with the same message. Three unrelated causes — a restricted
    fetch refspec, an abbreviated SHA, and a genuine concurrent push — therefore
    read identically, and only the third justifies backing off. The fence now
    reads a full 40-character lease value from the remote at push time via
    git ls-remote, and the disambiguation rule (plus a prohibition on falling
    back to plain --force) is written down next to it.
  • Merge authority is separated from validation (Phase 8 doesn't state whether operator merge pre-authorization outranks a required-but-unrunnable anchor #118). Two consecutive
    dispatches each independently re-derived the answer to the same question:
    when a run carries standing merge pre-authorization but Phase 4 has marked the
    PR UNVERIFIED, which wins? A paragraph adjacent to the existing codeowner
    exception now states that pre-authorization conveys permission rather than
    evidence, and that the codeowner exception is retrospective by construction —
    so a flag passed before the PR existed does not satisfy it.

Three substitution-table rows are updated so the placeholder guidance stays
accurate now that COMPILE_CMD and LINT_CMD appear in two fences rather than
one, and the no-build-system paragraph's reference to the fence's "re-run tests"
step is reworded to match its new wording.

Retrofit note

Per CLAUDE.md's "Promoting a rule into the template" section: all three rules
are template-wide, so every generated skill that predates this change will
keep carrying the old wording until its next regeneration.
Retrofit passes are
likely needed on any existing <slug>-dev-loop skill, and are not opened here —
this dispatch is path-restricted to this repository's own checkout and cannot
reach the other skill repositories. Only the person running those skills can see
which ones exist. Two are already known to need it by name:

Research grounding

Per CLAUDE.md's "Grounding work in research":

Test plan

  • python3 scripts/check_docs.pyDoc consistency check passed.
  • python3 -m pytest tests/ → 13 passed
  • CI doc-consistency green on the PR head
  • Placeholder parity re-checked: {{COMPILE_CMD}} and {{LINT_CMD}} are
    newly used in the Phase 8 fence and both already carry Step 4 rows
  • Fence escaping unchanged — no fenced block was opened or closed by this
    diff, only edited within
  • No Step was added, removed or renumbered, so README's "What it does" list
    stays 1:1 without modification
  • Empirical revert performed rather than reasoned about: with
    create-dev-loop.md checked out from origin/main, the fence reads
    re-run tests / {{TEST_CMD}} / bare git push --force-with-lease and
    no precedence paragraph is present; with the fix restored, all three are.
    scripts/check_docs.py passes in both states, which is the point of
    [self-audit] The repo's own validation anchor is structurally unrunnable in a headless dispatch, so template changes can never merge autonomously #109 — CI cannot observe this class of defect.
  • UNVERIFIED — external anchor could not run. This repository's anchor is
    a manual /create-dev-loop run against a real target repository. That is
    structurally unrunnable in a headless dispatch (see [self-audit] The repo's own validation anchor is structurally unrunnable in a headless dispatch, so template changes can never merge autonomously #109), and this PR
    changes create-dev-loop.md, which is anchor-relevant. Per Phase 4's
    gate the PR is therefore handed to a human rather than auto-merged, and
    per the very precedence rule this PR adds, the standing merge
    authorization carried by this run does not override that.

Deferred this cycle

Recorded for auditability, per Phase 1's skip-reason rule:

Closes #115
Closes #117
Closes #118

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

dmccoystephenson and others added 2 commits August 16, 2026 02:12
…dence rule

The post-rebase verification ran the test command alone, so a required
check that also runs a linter or static analysis survived the force-push
and was rediscovered from CI minutes later. It now runs the same
verification set Phase 3 runs.

The bare --force-with-lease has three unrelated causes that share one
'(stale info)' rejection — a restricted fetch refspec, an abbreviated
SHA, and a genuine concurrent push. Only the third justifies backing off,
so the fence now reads a full 40-character lease value from the remote at
push time and the disambiguation rule is written down.

Phase 8 also gains an explicit precedence rule: a run-level merge
pre-authorization conveys permission, not validation, so it does not
satisfy Phase 4's anchor gate on an UNVERIFIED PR.

Closes #115
Closes #117
Closes #118

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

Copy link
Copy Markdown
Member Author

Self-review rubric

Scored adversarially against the diff and command output, not judgment. Two
items were failed on the first pass; one was fixed and re-scored, the other
stands and gates the merge.

Universal rubric

Repo-specific rubric

Findings

create-dev-loop.md:553-561 — the rebase fence is no longer copy-pasteable as a
single block: the --force-with-lease value must be taken from the preceding
git ls-remote output. That is a real ergonomic regression and is accepted
deliberately, because the alternative — a bare --force-with-lease that reads
as safe while silently having no lease in a restricted clone — is the defect
#117 reports. The prose beneath the fence names the substitution explicitly, so
a reader is not left to infer it.

create-dev-loop.md:558{{#if LINT_CMD}}{{LINT_CMD}}{{/if}} renders as a
blank line inside the fence when a repository has no linter. This matches what
the Phase 3 verify block at :282 already does, so it introduces no new
inconsistency, but neither location is ideal and a future cleanup could collapse
both.

PR body (fixed during this review, not left as a finding) — the retrofit note
that CLAUDE.md's "Promoting a rule into the template" section requires was
missing from the first version of the description. All three rules are
template-wide, so every skill generated before this change keeps the old
wording. A "Retrofit note" section has been added naming the two instances known
by name, and stating that the retrofit PRs cannot be opened from this dispatch
because it is path-restricted to this repository's checkout.

Merge status

Withheld. create-dev-loop.md matches this repository's do-not-auto-merge
list, and Phase 4's anchor gate is UNVERIFIED: the external anchor is a manual
/create-dev-loop run against a real target repository, which cannot execute in
a headless dispatch (#109). This run does carry standing operator merge
pre-authorization, and that is precisely the collision #118 exists to resolve —
so the rule this PR adds is applied to the PR that adds it. Pre-authorization
conveys permission, not evidence, and the codeowner exception is retrospective
by construction. The merge is therefore not taken.

Terminal state: open, CI green, self-review posted, awaiting a human able to run
/create-dev-loop against a real repository. Phase 8 already declares that a
valid outcome rather than a failed cycle.

This review comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

@dmccoystephenson

Copy link
Copy Markdown
Member Author

@copilot please fix the merge conflicts in this pull request.

@dmccoystephenson

Copy link
Copy Markdown
Member Author

@copilot please fix the merge conflicts in this pull request.

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

@copilot please fix the merge conflicts in this pull request.

Merge conflicts resolved in 26b149f. Both create-dev-loop.md and RESEARCH.md kept all paragraphs/entries from both sides — the standing-authorization paragraph (this PR) and the structurally-red-anchor paragraph (main), and similarly both PR #119 and PR #121 implementation entries in RESEARCH.md. scripts/check_docs.py passes and all 13 tests are green.

The entry was written on the day the PR was opened and dated 2026-08-16,
but the PR did not merge that day. Re-date it to the day the branch was
finalized so the finding does not carry a ship date that never happened.
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Follow-up review — merge-conflict resolution and anchor re-confirmation

The self-review posted earlier on this PR was scored against head 9d7af16. Two
commits have landed since, neither of which that review covers, so both are
reviewed here: the conflict resolution 26b149f (authored by the Copilot agent
in response to the merge-conflict request above) and 6bffb11 (added by this
session). The earlier review's findings and its withheld-merge conclusion are
otherwise unchanged and are not re-litigated — Phase 4's one-intrinsic-critique
cap is respected; this pass was re-opened only by external signals (new commits
on the branch, and a CI run that was never allowed to execute).

External-anchor status — resolved

CI on 26b149f was left in action_required rather than green: the workflow run
was gated on manual approval because the commit was pushed by the Copilot agent,
so run 32547957642 completed in 0s having executed nothing. That state is easy
to misread as a green history, since the last successful CI run on this branch
sits two commits back on 9d7af16 and the aggregate PR status reported "no
checks reported". Pushing 6bffb11 from an already-permitted account retriggered
the workflow without an approval gate; doc-consistency is now pass on head
6bffb11 (run 32558521520).

Locally re-confirmed on the same tree, with executed counts read rather than exit
statuses trusted:

  • python3 scripts/check_docs.pyDoc consistency check passed.
  • python3 -m unittest discover -s tests -vRan 13 tests ... OK (13 > 0)

Review of 26b149f (conflict resolution)

Verified by diffing the branch against current main rather than by reading the
merge commit, so that anything silently dropped from either side would surface.

  • Both sides survive: PASS. create-dev-loop.md retains this PR's standing
    merge-authorization paragraph and main's structurally-red-anchor paragraph
    at Phase 8, in that order; the Phase 4 structurally-red paragraph from main
    is intact at :353. RESEARCH.md §1 retains both the PR Harden Phase 8's rebase fence and state the merge-authorization precedence rule #119 and the PR Require unique scratch filenames and define the structurally-red-anchor path #121
    Implementations entries. The unique-scratch-filename rule shipped by Require unique scratch filenames and define the structurally-red-anchor path #121 is
    present in both of its locations (grep -c → 2).
  • Net diff is exactly this PR's change: PASS. git diff origin/main --stat
    reports two files, 15 insertions, 5 deletions — no third file was pulled in by
    the resolution and no unrelated hunk survived it.
  • Placeholder parity: PASS. {{COMPILE_CMD}}, {{TEST_CMD}} and
    {{#if LINT_CMD}} appear at :289-291 (Phase 3 verify block) and :574-576
    (Phase 8 rebase fence); all three carry Step 4 rows at :618-620, and the
    COMPILE_CMD / LINT_CMD rows were updated to say so. Confirmed mechanically
    by check_docs.py, not by inspection alone.
  • Fence escaping: PASS. The resolution opened and closed no fenced block;
    every added line sits inside an existing escaped fence or is prose.
  • Phase numbering: PASS. No phase was renumbered by the resolution.

Finding addressed in 6bffb11

RESEARCH.md:51 — the Implementations entry for this PR read
shipped 2026-08-16, which was the date the PR was opened. The PR did not
merge that day and has not merged since, so the finding was carrying a ship date
that never happened — a stale factual claim in one of the repository's own
documentation sources of truth. It has been re-dated to 2026-08-22, the day the
branch was finalized. This remains approximate: whoever merges should correct
it if the merge slips further. The underlying convention gap — that the format
prescribed in "How to use this document" asks for a date that is unknowable at
the time the entry is written — is filed separately as #128 rather than papered
over here.

Phase 7 — documentation accuracy check

Re-run against the post-merge tree, since the earlier pass predates it. No
inaccuracy was found beyond the date corrected above:

  • create-dev-loop.md — internally consistent; placeholder/table parity and
    phase cross-references verified by command.
  • README.md — unchanged and correct; no Step was added, removed, or renumbered,
    so the "What it does" list stays 1:1.
  • RESEARCH.md — §1's Implementations entry is present, accurately worded, and
    now correctly dated within the limits noted above.
  • SECURITY.md:35 — worth calling out, because this PR moves it from stale to
    accurate rather than merely leaving it alone. It already claimed that
    COMPILE_CMD, TEST_CMD and LINT_CMD are executed in "its Phase 3
    build-verification step, its Phase 4 external-signal anchor, and its Phase 8
    post-rebase re-check". Before this PR that was true only of TEST_CMD; the
    Phase 8 fence ran the test command alone. Adding COMPILE_CMD and LINT_CMD
    to that fence is what makes the sentence true. No edit is needed.
  • CONTRIBUTING.md, .github/PULL_REQUEST_TEMPLATE.md, .github/ISSUE_TEMPLATE/*.md
    — a grep across *.md confirms the rebase fence and the --force-with-lease
    guidance are restated in no other document, so no further source of truth drifts.
  • CLAUDE.md — unaffected by this diff. It carries a separate known inaccuracy
    (CLAUDE.md still links gardener under the old dmccoystephenson owner #106, the gardener owner link), which is untouched here because editing
    agent-loaded configuration requires separate authorization.

Merge status — unchanged, still withheld

The earlier review's conclusion stands and is reaffirmed on the new head. The
anchor for a change to create-dev-loop.md is a manual /create-dev-loop run
against a real target repository; that is structurally unrunnable in a headless
dispatch (#109), and create-dev-loop.md is anchor-relevant here, so the PR
remains UNVERIFIED under Phase 4's scope gate. create-dev-loop.md also
matches this repository's do-not-auto-merge list. This run additionally carries
no merge authorization of any kind.

Note what the green check above does and does not establish: doc-consistency
verifies mechanical doc consistency only. It passes identically with this diff
reverted — that was demonstrated empirically in the earlier review — so it is
evidence of no doc-drift regression and nothing more. It is not evidence that the
generated skill behaves correctly.

Terminal state: open, CI green on head 6bffb11, both post-review commits
reviewed, awaiting a human able to run /create-dev-loop against a real
repository and merge. Phase 8 declares that a valid outcome rather than a failed
cycle.

Deferred this cycle

This dispatch was scoped to finishing this PR, so the entire remaining backlog is
deferred for that single reason, recorded once here per Phase 1's
externally-directed exception rather than commented onto each issue: #106, #109,
#114, #116, #117 (open only because this PR has not merged), #120, #122, #123,
#124, #125, #126, #127. The PR body's existing "Deferred this cycle" section
gives per-issue reasoning for the four that predate it and remains accurate. #116
is still the natural first pick for the next cycle. #128 was filed during this
cycle and is likewise not implemented here.

This review comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit c77c997 into main Aug 22, 2026
1 check 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

2 participants