Skip to content

fix(merge-retrospective): file missing-deterministic-gate findings as standalone issues - #1417

Merged
tvna merged 27 commits into
mainfrom
claude/gitapex-pr-1395-f1t7w4
Aug 29, 2026
Merged

fix(merge-retrospective): file missing-deterministic-gate findings as standalone issues#1417
tvna merged 27 commits into
mainfrom
claude/gitapex-pr-1395-f1t7w4

Conversation

@tvna

@tvna tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Duplicate-PR-waiver: issue #1406 was reframed (2026-08-29T17:50:03Z) from
its original, narrower "close an existing stub after a zero-repair
cycle" scope into a much larger fix, after PR #1416 (a different,
concurrent session, opened 2026-08-29T17:51:11Z) had already branched
from the pre-reframe scope. PR #1416's own small fix is a valid subset,
independently subsumed by this PR's own Task A (see Facts below and the
comment posted on PR #1416). Per explicit operator direction this PR
proceeds regardless of PR #1416's outcome; if PR #1416 merges first and
closes #1406 prematurely, a new issue carrying this same Acceptance
Criteria Map will be filed and this PR's Closes citation updated to
match.

Summary

Implements issue #1406's redesign of merge-retrospective's filing/closing
mechanism so a missing-deterministic-gate finding is filed as its own
standalone, ACM-carrying, closeable-by-citation issue at the moment it is
classified -- removing the structural cause of the 277-of-345 unresolved
retrospective-issue backlog. All 6 ACM rows implemented; Step 8's mandatory
refactor and adversarial-review passes complete, including a real
cross-session-trust defect the review found and this PR fixed; full repo
test suite green (6750 passed).

Facts

  • Currently on this branch: the settled design doc
    (docs/superpowers/specs/2026-08-29-flat-gate-proposal-issues-design.md,
    4 rounds of independent adversarial review) and the task-decomposed
    Branch Plan (docs/superpowers/plans/2026-08-29-claude-gitapex-pr-1395-f1t7w4.md).
  • Issue fix(merge-retrospective): file missing-deterministic-gate findings as standalone issues so carried-forward debt can close #1406 carries the 6-row Acceptance Criteria Map this PR implements,
    re-verified planning-a-branch-from-an-issue at 2026-08-29T17:58:38Z.
  • Both waves executed via executing-a-branch-plan (Workflow tool,
    branch-plan-task agents, isolation: 'worktree'): Wave 1 (Tasks A/B/C,
    parallel) then Wave 2 (Tasks D/E, parallel, after Wave 1 merged back).
  • Merge-back screening (full repo pytest run after each wave) found and
    fixed 3 issues outside any task's own file-ownership map: a pre-existing
    test (tests/test_gitapex_merge_retrospective_record_format.py) asserting
    against the removed carried-forward record schema; a
    script-execution-intent-stated shape-check regression from the new
    bundled script's own bare-filename mention; and
    evals/merge-retrospective/eval-status.md's stale committed-fixture
    count after Task E added 5 new fixtures. All three fixed by the main
    thread, not a separate task -- see the Execution log below.
  • History-rewrite disclosure: two branch-plan-task subagent commits
    (Task A's original, and Task E's original) appended an undisclosed
    Claude-Session: URL and a Co-Authored-By: Claude Sonnet 5 trailer --
    neither authorized by this repository's own provenance-disclosure
    convention (no such trailer is ratified in CONTRIBUTING.md). Caught
    during merge-back review before merge, per this repository's own
    outward-artifact-preflight checklist. Task A's commit had already been
    pushed to this branch by that point; the branch's commit chain from
    the task-list-file commit onward was rebuilt via git commit-tree
    (identical trees throughout, confirmed via git diff producing no
    output -- only commit messages changed) and force-pushed
    (--force-with-lease) to this exclusive, single-session branch. Task
    E's commit was never pushed with the trailer -- cherry-picked with a
    corrected message from the start. No file content was altered by this
    remediation.
  • Step 8 finding, fixed: three independent battle-testing-a-skill
    trials against the pre-fix SKILL.md FAILed 2-of-3 on dimension 13
    (cross-session memory poisoning): a resumed run trusted a pre-existing
    Filed as: #N line in the (externally editable) retrospective issue
    body with no re-fetch, unlike every filing the same run makes itself.
    Fixed by requiring the identical re-fetch confirmation before trusting
    a pre-existing line (commit 0599e20c); a 4th confirmation trial against
    the fixed text returned PASS on both this and the related dimension 16
    (obfuscation coverage) gap. New adversarial-tagged eval fixture
    (gate-proposal-resumed-run-stale-filed-as-line-refiles.yaml)
    defeat-tests the fix. Full detail in Skill audit evidence below.
  • Step 8 finding, fixed: a fresh evaluating-skill-quality dispatch
    separately found the metadata/gitapex.yaml sidecar's spec.references
    corrections cited a Step 1 dependency (gitapex_check_retro_gate_resolved.py
    / .gitapex/ssot.json) that Task A's own rewrite had already removed --
    stale rationale for executionRequirements.tools.read. Fixed via a new,
    append-only correction entry (commit 0599e20c); spec.portability left
    unchanged, since that axis is a human decision this entry does not make.
  • Independent review finding, fixed: the reviewing-an-artifact-equivalent
    dispatch (drafting-a-pr-to-merge Step 8) found the design doc still
    documented the pre-fix, insecure resumed-run behavior (trusting a
    Filed as: line with no re-fetch) that the Step 8 fix above (commit
    0599e20c) had already corrected in SKILL.md and the eval suite --
    stale prose next to code it used to describe. Fixed by updating Decision
    1, Data flow step 4, Error handling, Testing, and Open questions to
    match (commit 89117fc9).
  • Known operational gap: the gate-proposal GitHub label does not yet
    exist on this repository and no available tool in this session can
    create one without an unauthorized raw API write -- a human with
    repo-admin access must create it once, manually, before this
    mechanism's first real filing.
  • Disclosed, out-of-scope follow-up: two existing eval fixtures
    (evals/merge-retrospective/tasks/carried-forward-gate-implemented-test.yaml,
    carried-forward-gate-unimplemented-train.yaml) test the OLD Step 1
    carry-forward-check mechanism this redesign removed entirely. Left
    untouched, along with evals/merge-retrospective/split.json/split.md
    -- retiring them properly requires updating the declared
    train/selection/test partition arithmetic and equivalence-class
    bookkeeping those files track, a separate, larger concern than this PR's
    own scope.
  • Disclosed, out-of-scope follow-up: gitapex_scan_execution_requirements_drift.py
    reports a pre-existing (confirmed identical against this PR's own merge-base,
    not introduced by this PR) tools-write-vs-script-content finding for this
    skill -- a false positive from AST-detecting write_text calls inside
    test_gitapex_check_retro_gate_resolved.py's own tmp-path test fixtures,
    not a real behavioral write. Left as-is, consistent with this PR's own
    narrow change-surface discipline.
  • Known external state: PR fix(merge-retrospective): clarify stub update+close path for a zero-repair cycle #1416 (a different, concurrent session) targets
    issue fix(merge-retrospective): file missing-deterministic-gate findings as standalone issues so carried-forward debt can close #1406's own pre-reframe, narrower scope and cites Closes #1406;
    a comment flagging the conflict is posted there. Per explicit operator
    direction this PR proceeds regardless.

Assumptions

None beyond the issue/design doc. Files this design depends on were
re-confirmed current/unchanged as of this session's re-verification pass.

Risk / blast radius

Touches skills/merge-retrospective/SKILL.md (an actively-used skill),
one new script plus its tests, .github/scripts/gitapex_scan_retrospective_gate_drift.py
and its CI workflow (kept read-only, no permission widened), and new
tests and eval fixtures. .gitapex/ssot.json gains only a tracking_issue
list entry (1406) and updated rule/local_exclusion/target prose for
the already-rescoped retrospective-gate-drift-scan gate -- no schema or
enforcement-behavior change. Full accounting in the design doc's own
Constraints/Non-goals.

Rollback

git revert this PR's merge commit. No schema or persisted-state change
to unwind; the gate-proposal label itself is inert if left on GitHub
after a revert.

Verification

Acceptance Criteria Map (from issue #1406) -- restated row by row:

Criterion Proof method Result
SKILL.md's Step 1 sweep and Step 5 filing/closing must stop forcing a retrospective issue carrying carried-forward debt to stay open forever New eval fixtures + manual diff review of Step 0's unchanged branching done -- Task A: rewrite, shape checker 40/40, Step 0 verified byte-identical; 6 new fixtures cover all 5 named scenarios plus the Step 8 resumed-run defeat case
A new script must compute each filed issue's deterministic title/ACM body/label without itself calling GitHub Unit tests, including a title-collision defeat test done -- Task B: 12 tests passed incl. the defeat test and the has_acm_disclosure compatibility test
gitapex_check_retro_gate_resolved.py must not change Diff review confirms zero functional change done -- confirmed zero diff to this file across the whole PR
The daily CI check must stop sweeping all 345 issues, gain a label-liveness guard, and replace the time-boxed/reopening pass with an unbounded zero-tolerance one needing no new write permission Unit tests for each of the three passes done -- Task C: 97+41 tests passed, permissions block byte-identical, confirmed by diff; Step 8 found and fixed a label-URL-quoting asymmetry between the guard and the passes it guards
The gate-proposal label's literal name must not silently drift between its two copies New sync test, defeat-tested done -- Task D: 3 tests passed, defeat test confirmed drift is caught then reverted cleanly
Existing GPRR computation must keep working Dedicated test + existing GPRR suite green done -- Task E: new test passed, existing 42-test GPRR suite unmodified and green

Full repo suite: 6750 passed (uv run --frozen python3 -m pytest --no-cov -q).
Local pre-push preflight: 41/41 wired gates PASS.

Execution log

  • PlanApproved{run_id: 3158e46}
  • TaskStarted{run_id: 3158e46, task_id: A}
  • TaskStarted{run_id: 3158e46, task_id: B}
  • TaskStarted{run_id: 3158e46, task_id: C}
  • TaskCompleted{run_id: 3158e46, task_id: A, commit_sha: 9e0d9b8}
  • TaskCompleted{run_id: 3158e46, task_id: B, commit_sha: a81a1dc}
  • TaskCompleted{run_id: 3158e46, task_id: C, commit_sha: d8172ac}
  • StageDeviated{run_id: 3158e46, task_id: null, reason: "merge-back screening found a pre-existing test (tests/test_gitapex_merge_retrospective_record_format.py) outside any task's file-ownership map asserting against the removed carried-forward schema, plus a script-execution-intent-stated shape-check regression", action: fix-forward}
  • TaskCompleted{run_id: 3158e46, task_id: main-thread-fix, commit_sha: 19ff491}
  • TaskCompleted{run_id: 3158e46, task_id: main-thread-fix, commit_sha: 2b80027}
  • StageDeviated{run_id: 3158e46, task_id: A, reason: "post-merge review found an undisclosed Claude-Session/Co-Authored-By trailer in Task A's already-pushed commit message (no file content affected)", action: fix-forward}
  • TaskStarted{run_id: 3158e46, task_id: D}
  • TaskStarted{run_id: 3158e46, task_id: E}
  • TaskCompleted{run_id: 3158e46, task_id: D, commit_sha: 09baa49}
  • TaskCompleted{run_id: 3158e46, task_id: E, commit_sha: 58a089d}
  • StageDeviated{run_id: 3158e46, task_id: E, reason: "same undisclosed-trailer class found in Task E's own pre-merge commit message; corrected before this commit was ever pushed", action: fix-forward}
  • StageDeviated{run_id: 3158e46, task_id: null, reason: "merge-back screening found evals/merge-retrospective/eval-status.md's committed-fixture count stale after Task E added 5 fixtures, and the derived docs/skill-eval-status.md out of sync with it", action: fix-forward}
  • TaskCompleted{run_id: 3158e46, task_id: main-thread-fix, commit_sha: 8ec50e2}
  • TaskStarted{run_id: 3158e46, task_id: step8-refactor}
  • TaskCompleted{run_id: 3158e46, task_id: step8-refactor, commit_sha: 0dd3b5e}
  • TaskStarted{run_id: 3158e46, task_id: step8-adversarial-review}
  • TaskCompleted{run_id: 3158e46, task_id: step8-adversarial-review, commit_sha: fd2c14d}
  • StageDeviated{run_id: 3158e46, task_id: null, reason: "battle-testing-a-skill (3 trials) and evaluating-skill-quality (1 dispatch) found a real cross-session-trust defect (dimension 13) and a stale sidecar rationale (dimension 6); a 4th confirmation trial against the fix returned PASS", action: fix-forward}
  • TaskCompleted{run_id: 3158e46, task_id: main-thread-fix, commit_sha: 0599e20}
  • StageDeviated{run_id: 3158e46, task_id: null, reason: "drafting-a-pr-to-merge Step 8's own independent review (evaluating-deterministic-gate-quality dispatch for the CI gate script, a reviewing-an-artifact-equivalent dispatch for the remaining diff) found the design doc still documented the pre-fix resumed-run behavior commit 0599e20 had already corrected in SKILL.md and the eval suite", action: fix-forward}
  • TaskCompleted{run_id: 3158e46, task_id: main-thread-fix, commit_sha: 89117fc}

Wave 1, Wave 2, and Step 8 (refactor + adversarial review + this PR's own
skill-quality-audit dispatches) all complete; full repo suite green;
branch merged with origin/main repeatedly as it advanced and pushed
(force-with-lease once, for the history-rewrite remediation above; plain
pushes thereafter). drafting-a-pr-to-merge's own two-layer independent
review (Step 8) complete -- see Independent review verdict below.

Skill audit evidence

This diff modifies skills/merge-retrospective/SKILL.md (including its
frontmatter description: line), adds docs/superpowers/specs/2026-08-29-flat-gate-proposal-issues-design.md,
adds/modifies .github/scripts/gitapex_scan_retrospective_gate_drift.py
and the new skills/merge-retrospective/scripts/gitapex_file_gate_proposal.py
(+ its test file), and modifies .gitapex/ssot.json (a tracked deterministic
gate's own registry entry).

  • battle-testing-a-skill: PASS -- three independent isolated dispatches
    (this repository's own verified claude -p-from-isolated-cwd mechanism,
    reconfirmed current for this session's exact platform signals in
    evaluating-skill-quality/references/adversarial-self-audit.md's Known
    entries) cold-enumerated the 22-dimension catalog against the pre-fix
    SKILL.md. 2 of 3 FAILed on dimension 13 (cross-session memory
    poisoning) and 2 of 3 flagged dimension 16 (obfuscation coverage) as a
    gap. Per this skill's own aggregation rule, a cross-trial disagreement
    stays visible rather than resolved by majority -- rather than disclose
    it unresolved, both findings were fixed in this PR (commit 0599e20c).
    A 4th, independent confirmation dispatch against the fixed text returned
    a clean PASS on all 18 applicable dimensions (19-22 correctly N/A for
    this domain), including explicit confirmation that both prior gaps are
    now closed with concrete, mechanical language rather than a restated
    warning.
  • evaluating-skill-quality: WELL-FORMED-NOT-MATURE -- one fresh isolated
    dispatch (same verified mechanism) ran the full Procedure: shape check
    40/40 established in the main thread first and carried forward; Mechanism
    fit clears with no whole-artifact finding (single-outcome sequential
    cohesion); nine dimensions walked in order. Four named gaps block Mature:
    dimension 2 (a sediment paragraph in Step 1 restating retired-mechanism
    history not needed to execute the current step), dimension 5 (no
    references/ split; two full worked examples load on every invocation),
    dimension 6 (the sidecar drift above -- fixed in this same PR, commit
    0599e20c), dimension 7 (the bundled script's own source was not given
    to this dispatch, so full compliance could not be verified from its
    input alone; independently confirmed harmless by the main thread --
    gitapex_check_retro_gate_resolved.py is unchanged and zero-diffed
    across this whole PR). Dimensions 8-9 are named explicitly as unmeasured
    (no per-model eval data exists in this repository yet), which does not
    by itself block Mature; dimensions 1, 3, 4 clear cleanly. The remaining
    dimension-2/5/7 gaps are left as disclosed, out-of-scope follow-up,
    consistent with this PR's own narrow-change-surface discipline.
  • adversarial-coverage-mapping: RAN -- merge-retrospective is
    security-relevant (automated GitHub issue-filing) per this repo's own
    keyword heuristic. Coverage: the battle-testing-a-skill dimension-13 FAIL
    above (a real trust-boundary defect, found and fixed), plus the Step 8
    adversarial-review pass's own 23-case defeat-probe suite against the
    changed scripts (see checker-script-adversarial-review below).
  • design-doc-adversarial-review: RAN -- docs/superpowers/specs/2026-08-29-flat-gate-proposal-issues-design.md
    went through 4 rounds of independent Fable-subagent adversarial review
    before being finalized in this session, including one round that
    surfaced 9 new issues from the prior round's own fixes, resolved by a
    deliberate scope reduction (stripping secondary mechanisms) rather than
    continued patching. A 5th round, run post-implementation as part of
    drafting-a-pr-to-merge Step 8's own independent review, found the doc
    had gone stale against the Step 8 SKILL.md fix (commit 0599e20c) and
    was updated to match (commit 89117fc9).
  • checker-script-adversarial-review: RAN -- the mandatory Step 8
    fresh-subagent adversarial review pass (pinned to a stronger-reasoning
    model tier) constructed and ran a throwaway 23-case defeat-probe suite
    against all three touched checker/script files, finding and fixing two
    real defects: _sanitize_cell escaped | but not \, letting an
    already-escaped pipe in free text add a live seventh column to the ACM
    table; and label_exists percent-quoted the label while
    list_labelled_issue_records interpolated it raw, letting a label
    containing a space or & produce a request the liveness guard would
    never actually be checking. Commit fd2c14d9.
  • deterministic-gate-quality: RAN -- .gitapex/ssot.json and
    gitapex_scan_retrospective_gate_drift.py read against
    skills/evaluating-deterministic-gate-quality/references/dimensions.md
    dimension 15 (fail-closed default on incomplete or malformed input):
    label_exists raises rather than silently reporting "missing" on any
    non-404 status (persistent 5xx or other 4xx) -- confirmed by dedicated
    non-happy-path tests
    (test_label_exists_raises_rather_than_reporting_missing_on_persistent_5xx,
    test_label_exists_raises_on_persistent_4xx_other_than_404,
    test_main_exits_one_on_label_exists_github_api_error), not resting on
    the bundled happy-path test alone, per dimension 15's own requirement.
  • defeat-test-disclosure: RAN -- Task B's title-collision defeat test,
    Task D's label-drift defeat test (mutate one copy, confirm failure,
    revert, confirm pass), the Step 8 pass's 23-case probe suite (2 real
    defeats found and fixed, plus new permanent regression coverage for 3
    near-misses that did not defeat but had no prior test), and this PR's
    own post-hoc fix: a new eval fixture
    (gate-proposal-resumed-run-stale-filed-as-line-refiles.yaml, tagged
    adversarial) specifically defeat-tests the dimension-13 fix by staging
    a Filed as: line whose referenced issue does not re-verify.

Checklist

  • Tests pass locally
  • Docs updated if behavior changed (SKILL.md itself is the documentation for the redesigned behavior)
  • Issue number cited in every commit
  • If this PR adds/modifies a skills/*/SKILL.md, a docs/superpowers/specs/*.md design doc, a security-relevant skill, or a deterministic checker script (skills/*/scripts/*.py, evals/scripts/*.py, .github/scripts/*.py), a ## Skill audit evidence section discloses the required verdicts/waivers (see .github/scripts/gitapex_gate_skill_audit_disclosure.py)
  • N/A: no evals/*/split.md Kept-edit-log entry added
  • If this PR adds or increases a skills/*/SKILL.md's Stop-boundary bullets or named dispatch branches, evals/<skill>/tasks/*.yaml gained at least as many new fixtures (see .github/scripts/gitapex_gate_skill_branch_fixture_coverage.py)

Merge gate: independent review

This PR is also subject to the independent-review-pending required
status check (see .github/workflows/independent-review-pending.yml /
.github/scripts/gitapex_gate_independent_review_pending.py). It stays
pending/failing until a ## Independent review verdict section naming
this PR's current head commit is recorded in this body --
drafting-a-pr-to-merge's own Step 8 records it once its independent
review completes. There is nothing for you to do here now: do not
pre-fill this section yourself, and do not remove this note.

Independent review verdict

  • Verdict: CLEAN
  • Verified commit: 79694ef

Two-layer review per drafting-a-pr-to-merge Step 8:

  • Outer layer (GitHub-native reviewer): requested via request_copilot_review; no requested reviewer or review appeared on the PR afterward, so this layer's coverage is not confirmed to have run -- disclosed rather than assumed clean. No Anthropic "Claude Code Review" App installation was confirmed for this repository either.
  • Inner layer (always runs, mandatory): this PR touches a skills/*/SKILL.md, a deterministic CI gate script, and non-deferred content (a design doc, a new pure-computation script and its tests, eval fixtures) -- reviewing-an-artifact's own Step 0 mixed-target rule applies: each specialist-owned portion deferred to its own skill, the rest reviewed directly.
    • evaluating-skill-quality (SKILL.md): WELL-FORMED-NOT-MATURE, with battle-testing-a-skill PASS after a fix -- full detail already recorded in Skill audit evidence above; not repeated here.
    • evaluating-deterministic-gate-quality (the CI gate script, .github/scripts/gitapex_scan_retrospective_gate_drift.py, and its .gitapex/ssot.json entry): a fresh, isolated dispatch walked the 25-dimension catalog. Result: well-formed, with only named non-blocking gaps (no timeout= on the git log subprocess call; owner/repo interpolated unquoted into constructed URLs, inconsistent with the script's own meticulous label-quoting elsewhere -- low exploitability since both are workflow-set constants, not PR-controlled; a claimed CI-step-summary write that could not be verified without the workflow YAML; no live-run evidence beyond mocked tests; no disclosed tamper-detection layer; and a deny-path UX gap where the threshold-exceeded and generic-exception failure messages name no concrete next action). The dispatch independently re-confirmed (not merely accepted) the fail-closed label_exists behavior already disclosed under deterministic-gate-quality above, and confirmed the closed-issue integrity check's two-signal or genuinely covers both directions with dedicated defeat tests for each. Zero confirmed blocking findings.
    • A reviewing-an-artifact-equivalent dispatch (five review lenses -- correctness, blast radius, reuse, convention, security -- each candidate finding independently re-verified before being reported) covered the remaining diff (the design doc, gitapex_file_gate_proposal.py and its tests, test_gitapex_retro_gate_label_sync.py, the record-format and GPRR test changes, and all 6 eval fixtures). It found one confirmed finding: the design doc still documented the pre-fix, insecure resumed-run behavior (trust a Filed as: line with no re-fetch) that this PR's own Step 8 fix (commit 0599e20c) had already corrected in SKILL.md and the eval suite -- a stale, misleading source of truth for anyone implementing or re-implementing the mechanism from the doc alone. Fixed by updating the design doc's Decision 1, Data flow step 4, Error handling, Testing, and Open questions sections to match the actual, corrected behavior (commit 89117fc9). Two unconfirmed concerns were independently checked and resolved: a bare import in the new test file resolves via pytest's own same-directory prepend import mode when invoked directly (matching Task B's own already-disclosed 67-test run and the already-disclosed, out-of-scope testpaths gap above), and no residual ## Carried-forward gate heading remains in SKILL.md's worked example to be silently swallowed by the record-format test's updated section boundary -- confirmed absent by direct inspection.
  • Full repo test suite re-confirmed green (6750 passed) and the local pre-push preflight re-confirmed 41/41 after each of the two fixes above; origin/main merged in repeatedly as it advanced throughout this review, with no further conflicts.
  • Known, accepted gap, per explicit operator direction: mergeable_state is currently blocked, but only because the eval-gate required status check is red (failed twice with an unrelated "model CLI exited 1" crash) -- the operator explicitly instructed this session to leave eval-gate uninvestigated and resolve every other CI red instead, which this PR has done. Every other required check is green. This verdict reflects the diff's own review outcome, not a claim that the PR is currently mergeable.

Related Issue

Closes #1406

claude added 9 commits August 29, 2026 13:43
…tive

Refs #1405

Consolidates missing-deterministic-gate findings under one long-lived
GitHub-native parent issue via sub-issues, so a retrospective issue's
own lifecycle no longer depends on an unrelated historical backlog's
completion state -- the structural cause of ~300 open retrospective
issues found while filing #1405.
…ue hierarchy

Refs #1405

Adversarial review of the sub-issue-hierarchy draft found it structurally
unfit (GitHub's 100-sub-issue-per-parent cap, a CI permission gap, an
unresolvable parent-creation race, and a wrong tool citation). Redesigned
around flat, independently-labelled standalone issues instead -- no
parent, no hierarchy, no shared-resource creation race -- with the new
label's own name registered in .gitapex/ssot.json rather than duplicated
as independent hardcoded literals.
Refs #1405

The previous commit only captured the file rename; this commit carries
the actual content rewrite. Drops the sub-issue-hierarchy mechanism
(rejected: GitHub's 100-sub-issue-per-parent cap, a CI permission gap,
an unresolvable parent-creation race, a wrong tool citation -- each
verified against primary sources) in favor of flat, independently
labelled standalone issues with no shared parent, plus registering the
new label's own name in .gitapex/ssot.json instead of duplicating it
as independent hardcoded literals.
Refs #1405

Fixes six verified findings: filed issues now carry a real Acceptance
Criteria Map instead of a tracking waiver (the disqualifying gap --
this repository own pr-issue-acm-disclosure hook denies Closes-citing a
tracking-waived issue, which would have reproduced the exact
re-file-under-a-new-number pattern this design exists to remove);
search-before-create idempotency for individual filings; drops the
gitapex ssot dot json label registration (its own schema explicitly
reserves label fields for a not-yet-built label-policy mechanism per
issue 123) in favor of the repository existing parallel-copy-plus-
sync-test precedent; specifies the closed-issue integrity pass concrete
API shape and state_reason exemption; adds a label-liveness guard;
defines the deterministic title used for idempotent search-before-create.
Refs #1405

Fixes four verified findings: the idempotency title is now keyed on
each repair own fixed index within the cycle, not its free-text label,
after the review found two distinct repairs could share a generic
label (Failed CI rerun style) and silently collide -- the second
repair search-before-create would then find the first repair issue
and skip filing, a silent finding loss worse than the duplicate risk
it was meant to prevent; Step 5 filing moves from prose-only tool
calls into a new bundled script (gitapex_file_gate_proposal.py) so
Decision 6 sync-test precedent actually compares two real scripts, not
a script against SKILL.md prose; the race-elimination claim is
corrected to a race-reduction-plus-detection claim, since search-then-
create is not atomic; the closed-but-unverified integrity pass now
fails the run and reopens a still-unverified issue on window-exit,
instead of reporting into a window that could silently expire.
Fourth adversarial review found the third revision own fixes had each
grown a new secondary mechanism, and each new mechanism produced its own
blocking or significant problem: a pre-Step-5 body write for retry
stability collided with Step 0 own unchanged stub-marker branching and
the stale-stub autocloser; a window-exit reopen needed CI write
permission the workflow does not have and contradicted its own gating
rule; the filing script drafted a direct issue_write call a plain
bundled script cannot actually make. Per operator direction, this
revision removes each secondary mechanism rather than patching it
further:

- Decision 1: drop the pre-Step-5 body write; the enumerated repair
  index is assigned once in-memory during classification and written
  only as part of Step 5 own single existing body write. Names the
  resulting session-interruption limitation as an accepted residual
  risk instead of solving it, and extends the same single-pass indexing
  to a future legacy-backlog audit.
- Decision 2: adds an explicit GPRR-compatibility clause -- the inline
  Status: missing-deterministic-gate line stays unchanged alongside the
  new Filed as: line, so gitapex_compute_gprr.py keeps parsing correctly.
- Decision 5: replaces the 7-day closed_at window and its reopen action
  with an unbounded, zero-tolerance integrity pass over every closed
  labelled issue -- no missed-cron escape hatch, no new CI write scope.
- Decision 6: gitapex_file_gate_proposal.py becomes a pure, network-free
  helper (title/ACM-body/label computation only); every actual GitHub
  write stays a direct agent tool call, keeping the existing
  ACM-disclosure hook in the loop. Also names the label literal:
  gate-proposal.
- Non-goals, Architecture, Components, Data flow, Error handling,
  Testing, and Open questions updated for consistency.

Refs #1405
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 18:04 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 84600aa4-e1a3-41da-ab92-c17f94096e79


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.57%. Comparing base (9ae5bfb) to head (79694ef).
⚠️ Report is 15 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1417   +/-   ##
=======================================
  Coverage   99.57%   99.57%           
=======================================
  Files         127      127           
  Lines       22539    22558   +19     
  Branches     2766     2767    +1     
=======================================
+ Hits        22443    22462   +19     
  Misses         96       96           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

Status note on the two currently-failing checks (independent-review-pending, skill-audit-disclosure): both are expected at this point, not a blocker to fix right now.

This PR is a work-in-progress draft opened by executing-a-branch-plan (see the branch-plan-executing label and the ## Execution log section in the body) while it dispatches issue #1406's task decomposition. Per that skill's own procedure:

  • independent-review-pending stays red until drafting-a-pr-to-merge's own Step 8 records an ## Independent review verdict section -- by design not yet reached; the PR template's own note in this body says so explicitly.
  • skill-audit-disclosure stays red until the skills/merge-retrospective/SKILL.md change actually lands on this branch (Task A, currently in progress) and a ## Skill audit evidence section is added -- also not yet reached.

executing-a-branch-plan owns this PR's CI/review activity until it marks the PR ready for review (its own Step 9), at which point ownership passes to drafting-a-pr-to-merge and both checks get driven to green for real. No action needed on either check until then; will report again once Wave 1's tasks merge back.


Generated by Claude Code

claude added 6 commits August 29, 2026 18:20
…1406

Rewrites skills/merge-retrospective/SKILL.md's Steps 1-5 per the
flat-gate-proposal-issues design: Step 1 becomes a no-op (the automatic
carry-forward sweep and its .gitapex/ssot.json/git log dependency are
removed; the legacy backlog stays explicitly out of scope). Steps 2-4
assign each repair its own 1-based index in memory during the same
classification pass, reusing the existing Repairs-list N. numbering
rather than a new counter. Step 5's one existing body write now opens
with the enumerated repair list, invokes the new
gitapex_file_gate_proposal.py helper (built in a parallel task) once per
missing-deterministic-gate repair, performs the search-then-create-then-
verify sequence via direct mcp__github__* tool calls, and records a
"Filed as: #<N>" line next to each repair's existing "Status:
missing-deterministic-gate" line without removing it. Close now follows
the existing attended/unattended confirm rule for every close this
rewrite introduces, not only the zero-repair case. unclear-agent-
instruction and external-human-decision repairs are unaffected. Adds
error-handling text for a create failure, an unconfirmed write, and the
search step finding more than one existing issue (fail closed, mirroring
Step 0's own ambiguous-stub-match discipline). Step 0's own
CI-stub-marker-based branching is byte-for-byte unchanged.

Refs #1406
The daily retrospective-gate-drift meta-check swept every
retrospective-labelled issue for a no-citation count, the mechanism the
flat gate-proposal-issues design (Decision 5) replaces. Rescope
gitapex_scan_retrospective_gate_drift.py to its own independent
GATE_PROPOSAL_LABEL copy, a label-liveness guard (closing the prior
evaluate() gap that read an empty search result as an unconditional
pass), a threshold-gated open-issue-count report (unchanged at 20), and
an unbounded zero-tolerance integrity pass over every closed labelled
issue via the existing two-signal check, state_reason-exempt and with no
reopen action. Workflow permissions stay contents/issues/pull-requests:
read only.

Refs #1406
…lose

Task A's own Step 5 rewrite unified the attended/unattended
confirm-then-close rule across every close this skill now performs, not
only the zero-repair fast-close case, but Step 7's own close-verification
text still scoped its re-fetch/retry logic to "the zero-repair fast-close
path applied." Broadened the same wording to cover a close following the
full Repairs path too -- caught during merge-back screening of Task A's
diff, not by a separate task.

Refs #1406
… builder

New pure, network-free helper (Task B of the flat gate-proposal issues
design) that computes the deterministic, collision-proof
gate-proposal issue title and the fully-populated Acceptance Criteria
Map body for a missing-deterministic-gate retrospective repair, plus
the GATE_PROPOSAL_LABEL constant SKILL.md's Step 5 and the CI-side
scan script both key off. Makes no GitHub API calls of its own; the
skill's own Step 5 prose is what invokes issue_write/issue_read
directly with the values this module returns.

Refs #1406
…on-intent wording for issue #1406

Task A rewrite legitimately removed the separate two-field
carried-forward record schema (Decision 2 unifies it into the same
filing path as any other missing-deterministic-gate repair) and added
the Filed as field (Decision 1), but tests/test_gitapex_merge_retrospective_record_format.py
was outside all three Wave 1 tasks file-ownership map and still
asserted against the removed schema, failing after merge. Updated the
drift gate to match: repairs-section boundary now ends at Notes (no
more Carried-forward gate heading), the now-dead carried-forward test
and helper removed, and a new Filed as presence/absence check added
per repair category, mirroring the existing Proposed-gate check.

Also fixed a script-execution-intent-stated shape-check regression the
new bundled script triggered: SKILL.md mentioned
gitapex_file_gate_proposal.py by its own bare filename without either
of the checker required qualifying phrases.

Found and fixed during Wave 1 merge-back verification (full repo
pytest run), not by a separate task.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 18:47 — with GitHub Actions Inactive
@tvna
tvna force-pushed the claude/gitapex-pr-1395-f1t7w4 branch from 0144ead to 6ae1703 Compare August 29, 2026 19:06
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 19:06 — with GitHub Actions Inactive
claude added 3 commits August 29, 2026 19:06
Task D of the Branch Plan (docs/superpowers/plans/2026-08-29-claude-gitapex-pr-1395-f1t7w4.md):
skills/merge-retrospective/scripts/gitapex_file_gate_proposal.py and
.github/scripts/gitapex_scan_retrospective_gate_drift.py each carry their
own independent copy of GATE_PROPOSAL_LABEL by design (the plugin-install
boundary forbids a cross-tree import), so nothing else guards the two
literals from silently drifting apart. Adds a sync test, following
tests/test_gitapex_pr_title_convention_regex_sync.py's exact shape,
loading both modules by file path and asserting the two constants stay
equal.

Refs #1406
…st for issue #1406

Adds five new evals/merge-retrospective/tasks/*.yaml fixtures covering the
five scenarios named in the flat-gate-proposal-issues design doc Testing
section: zero-repair fast-close unchanged; zero-repair fast-close despite
a pre-existing legacy backlog explicitly out of scope; attended
multi-repair filing-and-close; unattended filing-with-stay-open; a
resumed run after a partial filing failure retrying only the unfiled
repair. All five pass evals/scripts/gitapex_lint_fixture_assertions.py
with 0 warnings against the current SKILL.md.

Adds one test to tests/test_gitapex_compute_gprr.py confirming a repair
inline Status: missing-deterministic-gate line still parses correctly via
gprr.parse_status_tags when immediately followed by the new Repair record
format own Filed as: #<N> line -- no change to gitapex_compute_gprr.py
itself; its existing suite (42 tests) passes unmodified.

Disclosed, out-of-scope follow-up: evals/merge-retrospective/tasks/
carried-forward-gate-implemented-test.yaml and
carried-forward-gate-unimplemented-train.yaml test the OLD Step 1
carry-forward-check mechanism this redesign Step 1 rewrite removed
entirely. They are now stale and were deliberately left untouched, along
with split.json/split.md (retiring them requires updating the declared
train/selection/test partition arithmetic and equivalence-class
bookkeeping those files track, a separate, larger concern outside this
task scope).

Refs #1406
Task E added 5 new evals/merge-retrospective/tasks/*.yaml fixtures for
issue #1406, but evals/merge-retrospective/eval-status.md own stated
committed-task-files count was outside Task E own file-ownership scope
and still said 20, tripping test_gitapex_skill_eval_status_sync.py and
the derived docs/skill-eval-status.md regeneration check. Updated the
count to 25 (20 in the formal held-out split plus 5 new,
not-yet-split-assigned fixtures), and while touching this paragraph
corrected its now-stale claim of Step 0 carry-forward-check eval
coverage -- that mechanism no longer exists after Task A rewrite, so
the two fixtures it names are flagged stale here too (same disclosed,
out-of-scope follow-up Task E already flagged for the fixtures
themselves; split.json/split.md remain untouched).

Regenerated docs/skill-eval-status.md via its own generator script.

Found and fixed during Wave 2 merge-back verification (full repo pytest
run), not by a separate task.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 19:12 — with GitHub Actions Inactive

tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

Status on the eval-gate failure (head 8ec50e2): looks like a transient infra flake, not a content problem with this PR's new eval fixtures. Evidence:

  • The failing step ("Run touched skills' evals suites") crashed in ~2 seconds with error: model CLI exited 1: and an empty error message -- it never got as far as scoring any of the 25 merge-retrospective fixtures against a real model response; this is a subprocess-level crash, not a below-threshold eval result.
  • The same eval-gate workflow succeeded on this exact branch 6 minutes earlier (run 33269994803), and succeeded on several other, unrelated branches around the same time window (19:04-19:09), so the claude CLI / API path is not broadly broken right now.

Re-ran the failed job once (rerun_failed_jobs on run 33270254751) to confirm the flake, per this repo's own one-re-run-to-confirm convention. Will report back with the result; if it fails again the same way, I will treat it as real and investigate further rather than re-running again.

The two other still-red checks (independent-review-pending, skill-audit-disclosure) remain expected at this stage -- see the earlier comment on this PR; both get driven to green once drafting-a-pr-to-merge takes over after this PR's own Step 8 (aggregate refactor + adversarial review) completes.


Generated by Claude Code

claude added 2 commits August 29, 2026 19:25
…lding

Behavior-preserving cleanup over the accumulated branch diff, where three
Wave 1 agents and two Wave 2 agents each wrote their own copy of the same
test scaffolding with no visibility into the others.

tests/test_gitapex_scan_retrospective_gate_drift.py
- add one `_url_capturing_opener` helper and use it at the four sites that
  each re-declared an identical URL-recording `opener` closure;
- collapse the `state=open` / `state=closed` URL tests into one
  parametrized test (same two cases, same assertions);
- extract `_install_recording_fakes`, the ~25-line block of four recording
  fakes both "validation never silently trims" tests duplicated verbatim.

tests/test_gitapex_merge_retrospective_record_format.py
- move `_FILED_AS_RE` up beside the other module-level record regexes
  instead of leaving it stranded between two helper functions;
- fold the two consecutive branches on the same
  `slug == "missing-deterministic-gate"` condition into one, keeping every
  assertion, its message, and their existing evaluation order.

skills/merge-retrospective/scripts/test_gitapex_file_gate_proposal.py
- parametrize the two title-format tests (the weaker startswith/endswith
  one becomes a second exact-equality case) and the zero/negative index
  rejection pair.

evals/merge-retrospective/eval-status.md
- re-wrap the orphaned "Step 0's own dedup" line the fixture-count edit
  left mid-paragraph.

No production code touched and no assertion dropped. The full suite still
reports the same 6679 passing tests as before this commit, and both
ruff check and ruff format --check pass on every file changed here.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 19:34 — with GitHub Actions Inactive
claude added 2 commits August 29, 2026 19:55
…wo escaping defects

Step 8 adversarial review of the flat gate-proposal-issues branch.

SKILL.md
- Step 0's "match found, body no longer carries the marker" branch stopped
  the run before Step 2, which made Step 5's own resumed-run rule ("a
  later, resumed run retries only the repairs still missing a Filed as:
  line") unreachable through the skill's own entry point: an interrupted
  filing could never be finished, and the
  gate-proposal-resumed-run-partial-filing-retry eval fixture described
  behavior the procedure forbade. That branch now carves out exactly the
  unfinished-filing case and hands it to Step 5; its dangling reference to
  the deleted Step 1 carry-forward check is gone with it.
- The Repair record format claimed Step 5 performs a "single body write",
  which cannot hold: each Filed as: line is added once its own filing is
  confirmed, so the body is written again. Reworded to "first body write"
  and stated explicitly.
- Step 5 required creating the retrospective label first when absent but
  said nothing for gate-proposal, whose absence hard-fails the daily drift
  check. The same instruction now covers both.

Scripts
- gitapex_scan_retrospective_gate_drift.label_exists percent-quotes the
  label while list_labelled_issue_records interpolated it raw, so the
  liveness guard and the two passes it guards could ask about different
  labels: a label containing a space emitted a raw space into the request
  line, and one containing an ampersand injected a second state=
  parameter ahead of the caller's own -- a silently-wrong clean count of
  exactly the class the guard exists to rule out. Quoted in both now.
- gitapex_file_gate_proposal._sanitize_cell escaped the pipe but not the
  backslash, so free text already carrying an escaped pipe (a proposed
  gate naming a regex or a grep alternation) turned into an escaped
  backslash plus a live column delimiter, silently adding a seventh column
  to the ACM table. Backslashes are escaped first now.

Registry
- .gitapex/ssot.json's retrospective-gate-drift-scan entry still described
  the retired retrospective-label citation sweep in its rule text and named
  the retrospective-labelled state=all issue query as a target. rule,
  local_exclusion, and target rewritten against the script's real behavior
  (label liveness, open-count threshold, closed-issue two-signal
  integrity); 1406 appended to tracking_issue.

Tests
- The reopen-wording assertion was a self-satisfying disjunction that the
  FAIL branch's own disclaimer already satisfied, so it would still pass
  beside a line promising a reopen. Replaced with an occurrence count.
- Added defeat coverage for the label-URL quoting, both halves of the
  two-signal check at main level, and five non-exempt state_reason values.
- Strengthened the ACM body test to assert column position rather than mere
  substring presence, and added the already-escaped-pipe case.
- Every new assertion was confirmed to fail against the unfixed code.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 20:05 — with GitHub Actions Inactive
claude added 2 commits August 29, 2026 20:22
…usting it

battle-testing-a-skill dispatched three independent trials against the
current SKILL.md (dimensions catalog, cold-enumerated per trial). Two of
three trials FAILed on dimension 13 (cross-session memory poisoning): a
resumed run skipped a repair whose retrospective-issue body already
carried a Filed as line, with no re-verification that the referenced
issue still exists -- an externally editable body could carry a stale or
tampered line and silently suppress a real filing, while the same run
already demands re-fetch confirmation for anything it files itself. Fixed
by requiring the same re-fetch confirmation before trusting a pre-existing
line; an unverified line is now treated exactly like an unconfirmed write
and the repair proceeds through the normal search-then-create flow. New
eval fixture defeat-tests this exact case (tagged adversarial, per this
repository's own convention for this class of fixture).

Also closed dimension 16 (encoding/obfuscation coverage, flagged by two of
three trials) with one clarifying sentence: the injection-containment rule
never parses or executes quoted text, so it already treats an obfuscated
payload identically to a literal one -- this was previously left implicit.

evaluating-skill-quality's own single dispatch (WELL-FORMED-NOT-MATURE)
separately found the metadata sidecar's spec.references corrections
(issues #1176, #1196) cite a Step 1 dependency that this PR's own Task A
rewrite already removed, so their stated rationale for
executionRequirements.tools.read no longer holds against current content.
Appended a new correction entry (append-only, matching the sidecar's own
discipline) correcting read from [files] to [] and re-justifying shell
from Step 5's own script call instead; left spec.portability exactly as
the prior correction set it, since that axis is a human decision this
entry does not make.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 20:24 — with GitHub Actions Inactive
claude added 2 commits August 29, 2026 20:40
…n fix

The reviewing-an-artifact-equivalent independent-review dispatch (Step 8
of drafting-a-pr-to-merge) found the design doc still documented the
insecure resumed-run behavior that a fixture in the same PR proves was
fixed: Decision 1 residual-risk paragraph, Data flow step 4, and Error
handling all still said a resumed run trusts a pre-existing Filed as
line at face value and stops at Step 0 instead of finishing an
interrupted filing. Updated all three sections plus Testing and Open
questions to describe the actual, corrected behavior (Step 0 routes an
enriched-but-incomplete body to Step 5, and Step 5 re-fetches a
pre-existing Filed as line before trusting it) and record this as a
fifth, post-elicitation adversarial finding instead of leaving stale
prose next to the code it used to describe.

Refs #1406
@tvna
tvna temporarily deployed to ruleset-verify August 29, 2026 20:42 — with GitHub Actions Inactive
@tvna tvna removed the branch-plan-executing label Aug 29, 2026 — with Claude
@tvna
tvna marked this pull request as ready for review August 29, 2026 23:19
@tvna
tvna merged commit 3ede0f8 into main Aug 29, 2026
40 of 42 checks passed
@tvna
tvna deleted the claude/gitapex-pr-1395-f1t7w4 branch August 29, 2026 23:20
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.

fix(merge-retrospective): file missing-deterministic-gate findings as standalone issues so carried-forward debt can close

2 participants