From c789ef1b63d8e5702c804233cf2b6501bd60496f Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 10:35:43 -0400 Subject: [PATCH 1/6] =?UTF-8?q?ops(0-0-0):=20post-#101=20follow-up=20?= =?UTF-8?q?=E2=80=94=20fix=20Copilot=20threads=20+=20add=20full=20PR=20arc?= =?UTF-8?q?hives=20+=20correct=20cross-fork=20drain-log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses 4 Copilot threads from AceHack #101 (filed 14:24:11Z, AFTER auto-merge fired at 14:19:41Z) + 4 Copilot threads from LFG #844 (already addressed in #845 but Copilot also reviewed AceHack #101 and re-flagged 2 of them since the AceHack-side hadn't received the carry-forward yet) + Amara post-#845 substantive correction on PR-preservation tool usage. ## Copilot thread fixes (memory file) 1. **P1 broken xref** to `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md` (the file lives in user-scope memory only, not in-repo; cross-reference was therefore broken). Fixed: replaced with prose pointer to the underlying principle + note flagging the same issue exists in MEMORY.md index. 2. **P1 internal consistency on legacy DELETE response** — same finding as LFG #844 Thread 3, addressed by carry-forward in LFG #845. Now reflected on AceHack via this commit. 3. **P2 wording "the only rulesets ruleset"** — same finding as LFG #844 Thread 5, addressed by carry-forward in LFG #845. Now reflected on AceHack via this commit. 4. **P2 MEMORY.md index entry too long** — trimmed from a 4-line dense paragraph to a single concise line per `memory/README.md` discipline. Detail stays in the linked memory file. ## PR archives (Amara post-#845 directive: use existing `tools/pr-preservation/archive-pr.sh`) Three full-archive files added under `docs/pr-discussions/`: - `PR-0844-...md` — closed LFG #844 (5 threads, 2 reviews, 2 issue comments) - `PR-0845-...md` — merged LFG #845 (0 threads, 1 review, 0 comments — clean forward-sync) - `PR-acehack-0101-...md` — merged AceHack #101 (4 threads, 1 review, 0 comments). **Fork-prefixed filename** to disambiguate from LFG #101 (which is a different unrelated PR from 2026-04-22 about auto-loop-10 tick-history). The existing tool's `gh repo view --json owner,name` call resolves to current-clone origin; for cross-fork archives, set `gh repo set-default /` first then run, then reset default. Captured as a tool-improvement candidate (the script could accept a `--repo` arg to make cross-fork archives one-shot). ## Drain-log correction for AceHack #101 The earlier drain-log claimed 0 threads (because I queried before Copilot's review landed at 14:24:11Z, ~5 min after auto-merge). Updated to reflect the actual 4 unresolved threads + their carry-forward resolution paths. ## Lesson captured (drain-log, lessons section) **AceHack auto-merge races Copilot review.** Without required-conversation-resolution + required-status-checks on AceHack, auto-merge fires before reviewers land threads. Threads still apply to merged content; just need a follow-up cycle to land fixes. This is exactly what this PR is — the follow-up. **The double-hop captures BOTH waves of review.** When AceHack auto-merges fast, the LFG forward-sync PR re-runs review and catches the same findings. Double-hop is also a *redundancy mechanism* against fast-merge-on-AceHack. ## Lane discipline This PR opens AceHack-first per canonical double-hop. After merge → forward-sync to LFG. After both merge → AceHack absorbs LFG squash-SHA (gates on Aaron's EXECUTE). Then the post-cleanup-cleanup-cleanup is FINALLY done, and we can pivot to recovery-lane classification. Per Amara: "Double-hop close is the active lane. Do not start branch/worktree recovery until: PR full archives are committed, LFG #845 artifacts are preserved, AceHack absorption completes, 0/0/0 is re-verified." --- ...cleanup-stale-prose-fixes-protection-co.md | 193 ++++++++++++++++++ ...d-sync-post-reset-cleanup-copilot-fixes.md | 81 ++++++++ ...cleanup-stale-prose-fixes-protection-co.md | 144 +++++++++++++ docs/pr-preservation/acehack-101-drain-log.md | 74 +++++-- memory/MEMORY.md | 2 +- ...y_deleted_rulesets_canonical_2026_04_29.md | 2 +- 6 files changed, 482 insertions(+), 14 deletions(-) create mode 100644 docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md create mode 100644 docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md create mode 100644 docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md diff --git a/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md b/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md new file mode 100644 index 0000000000..9e276510f1 --- /dev/null +++ b/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md @@ -0,0 +1,193 @@ +--- +pr_number: 844 +title: "ops(0-0-0): post-reset cleanup \u2014 stale-prose fixes + protection-config memory" +author: "AceHack" +state: "CLOSED" +created_at: "2026-04-29T14:14:41Z" +closed_at: "2026-04-29T14:18:52Z" +head_ref: "post-0-0-0-cleanup-2026-04-29" +base_ref: "main" +archived_at: "2026-04-29T14:30:11Z" +archive_tool: "tools/pr-preservation/archive-pr.sh" +--- + +# PR #844: ops(0-0-0): post-reset cleanup — stale-prose fixes + protection-config memory + +## PR description + +## Summary + +The small in-lane cleanup PR Amara prescribed after 0/0/0 was reached. Two scoped changes: + +1. **Stale-prose fixes in `docs/active-trajectory.md`** — flip post-reset contradicting language to in-force 0/0/0-achieved language +2. **Protection-config memory** — document the dual-layer surprise + Aaron's "delete legacy, rulesets canonical" decision + +## 🎯 0/0/0 ACHIEVED 2026-04-29T14:04:50Z + +``` +AceHack/main = LFG/main = 621aae082d70fcbf36931718ecf1b6d9e149295f +Topology: 0 ahead, 0 behind, 0 file content diff +Archive ref: archive/acehack-main-pre-000-reset-2026-04-29 → 6755081... (preserved) +Layers: legacy DELETED (per Aaron); rulesets re-enabled +``` + +## Stale-prose fixes (Amara substrate-pass catch) + +Two paragraphs flipped from pre-reset state to in-force post-reset state: +- Line 221: *"Currently NOT signoff-eligible"* → *"0/0/0 ACHIEVED 2026-04-29T14:04:50Z..."* +- Line 413: *"Hard-reset is NOT YET signoff-eligible"* → *"Hard-reset complete (2026-04-29T14:04:50Z)..."* + +This is **Derived-Rollup Drift** class — primary state changed, downstream prose still claims old state. Caught pre-commit by Amara's substrate pass; not a Codex/Copilot retry. + +## Protection-config memory + +`memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: + +- AceHack/Zeta had BOTH legacy branch protection AND repository rulesets on `main` +- Both layers enforced independently; GitHub UI doesn't surface dual-layer state +- Aaron: *"I knew there were two but I was confused why."* +- Maintainer call: legacy DELETED, rulesets canonical going forward +- Error-code mapping: `GH013` = rulesets surface, `GH006` = legacy surface +- Diagnostic script (`gh api` commands) for future audits +- Future-protocol note: rulesets `non_fast_forward` rule still doesn't match CLAUDE.md's *"force-push to AceHack main is part of protocol"* — task #305 home for that decision + +`MEMORY.md` index updated with one-line pointer. + +## Tick shard 1410Z + +Records the entire 0/0/0 hard-reset arc: +- Triple-check buddy review (Amara approved meaningful-content-loss-free) +- Verify-only gate packet (5/5 PASS at 13:39Z) +- Aaron's explicit EXECUTE at 13:58Z +- Steps A/B/C with the dual-layer surprise + recovery +- Path 1 v3 success at 14:04:50Z + +## What this PR does NOT do (per Amara's lane discipline) + +- ❌ Does NOT start the recovery lane (inventory parked at `/tmp/recovery-inventory-2026-04-29.tsv`, awaits Amara's classification framework which just landed) +- ❌ Does NOT consolidate the 8 deferred-queue rule candidates (P1 work, post-0/0/0-success-trigger satisfied but lane discipline says one cleanup PR first) +- ❌ Does NOT touch Aurora extension (P2) +- ❌ Does NOT mutate any branches/worktrees/stashes (Aaron's authority for irreversible) + +## Authority boundary going forward (per Amara post-reset packet) + +``` +Reversible + in-lane + PR-reviewed → proceed autonomously +Irreversible / deletion / force-push / authority config / identity canon → ask Aaron +Unclear → stop, report exact uncertainty, propose one safe action +``` + +## Test plan + +- [x] Stale "Currently NOT signoff-eligible" → in-force 0/0/0-achieved language +- [x] Stale "Hard-reset is NOT YET signoff-eligible" → "Hard-reset complete" language +- [x] Memory file written + MEMORY.md index updated +- [x] Tick shard 1410Z appended +- [x] No new ledger headline introduced (273/0/0 doesn't need to flip — it's the final state) +- [ ] CI green +- [ ] Codex / Copilot reviews resolved if any threads land + +🤖 Generated with [Claude Code](https://claude.com/claude-code) + +## Reviews + +### COMMENTED — @chatgpt-codex-connector (2026-04-29T14:16:32Z) + + +### 💡 Codex Review + +Here are some automated review suggestions for this pull request. + +**Reviewed commit:** `8630c28e57` + + +
ℹ️ About Codex in GitHub +
+ +[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you +- Open a pull request for review +- Mark a draft as ready +- Comment "@codex review". + +If Codex has suggestions, it will comment; otherwise it will react with 👍. + + +Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". + +
+ +### COMMENTED — @copilot-pull-request-reviewer (2026-04-29T14:19:29Z) + +## Pull request overview + +Post-0/0/0 cleanup to align durable docs/memory with the now-in-force hard-reset state and to capture the branch-protection dual-layer incident for future debugging. + +**Changes:** +- Updates `docs/active-trajectory.md` to reflect that the 0/0/0 hard-reset is complete (replacing stale “not signoff-eligible” prose). +- Adds a new memory entry documenting the dual-layer (rulesets + legacy branch protection) enforcement surprise and the chosen canonical surface going forward. +- Updates the memory index and appends a tick shard recording the reset arc and this cleanup PR. + +### Reviewed changes + +Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments. + +| File | Description | +| ---- | ----------- | +| `memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md` | New memory capturing the GH013/GH006 dual-layer behavior, decision, and diagnostics. | +| `memory/MEMORY.md` | Adds an index entry pointing to the new protection-config memory. | +| `docs/hygiene-history/ticks/2026/04/29/1410Z.md` | New tick shard recording the 0/0/0 achievement and follow-on cleanup PR. | +| `docs/active-trajectory.md` | Flips two stale paragraphs to reflect the achieved post-reset state. | + +## Review threads + +### Thread 1: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:40 (resolved) + +**@chatgpt-codex-connector** (2026-04-29T14:16:33Z): + +**![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat) Use supported gh api request-body syntax** + +The `Executed` commands document `gh api ... --input '{"enforcement": "disabled"}'`, but `gh api` treats `--input` as a file argument (manual: `--input `, use `-` for stdin), so this form is interpreted as a filename and is not reproducible as written. Because this memory file is positioned as an operational reference for future protection toggles, the current command text can cause failed retries during incident handling; use a real file/stdin body or field flags instead. + +Useful? React with 👍 / 👎. + +### Thread 2: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:42 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:19:27Z): + +The `gh api ... --input '{"enforcement": ...}'` invocations won’t work as written: `gh api --input` expects a file path (or stdin via `--input -`), not an inline JSON string. Use `-f enforcement=...`/`-F enforcement=...`, or pass JSON via stdin (e.g., `--input -`) so this is copy/paste-correct for future audits. + +### Thread 3: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:43 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): + +The step list appears internally inconsistent: the earlier GH006 rejection indicates legacy branch protection was active, but the subsequent `gh api -X DELETE .../branches/main/protection` line claims a 404 "Branch not protected" response (which typically means there was no classic protection to delete). To keep this memory reliable, please reconcile this (e.g., clarify an intermediate UI/API change, confirm the endpoint/repo/branch used, or update the recorded responses). +```suggestion +# Delete legacy branch protection (this removed the GH006 blocker) +gh api -X DELETE repos/AceHack/Zeta/branches/main/protection +# → 204 No Content +``` + +### Thread 4: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:82 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): + +References to “Task #305” here are ambiguous in-repo (this repo already has a PR #305, and backlog rows use `B-####` IDs under `docs/backlog/**`). Consider replacing “Task #305”/“#305-adjacent” with the actual backlog-row ID (if any) or a direct URL so readers don’t chase the wrong artifact. + +### Thread 5: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): + +Minor wording nit: “the only rulesets ruleset” reads like a duplication. Consider rephrasing to “the only ruleset” / “the only rulesets entry” for clarity. +```suggestion +After disabling the only ruleset (id=15524390 "Default", `enforcement: disabled`) and retrying, the push was rejected AGAIN with a **different error code**: +``` + +## General comments + +### @AceHack (2026-04-29T14:17:34Z) + +Codex P2 (14:16Z) addressed in f6d6a94. Fixed memory-file documentation: `gh api --input '{json}'` was wrong syntax (gh treats --input value as a file path). Replaced with the actual heredoc-from-stdin pattern that was used live: `gh api ... --input - <<'EOF'` + JSON body + `EOF`. Added clarifying note about gh CLI flag semantics for future readers. + +### @AceHack (2026-04-29T14:18:51Z) + +Closing per Aaron's correction: this PR went LFG-first, but the canonical pattern is AceHack-first → LFG forward-sync → AceHack absorbs LFG squash-SHA. *"Without the double-hop in a few hours we'll be right back to where we started — that's load-bearing to get right."* Branch `post-0-0-0-cleanup-2026-04-29` is being repushed to AceHack remote and opened there as the canonical first PR. Codex P2 review feedback (gh api --input syntax fix) is preserved as commit `f6d6a94` on the branch + carried into the AceHack PR. diff --git a/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md b/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md new file mode 100644 index 0000000000..f38b306311 --- /dev/null +++ b/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md @@ -0,0 +1,81 @@ +--- +pr_number: 845 +title: "ops(0-0-0): LFG forward-sync \u2014 post-reset cleanup + Copilot fixes + pr-preservation drain-logs (mirror of AceHack #101)" +author: "AceHack" +state: "MERGED" +created_at: "2026-04-29T14:25:11Z" +merged_at: "2026-04-29T14:27:35Z" +closed_at: "2026-04-29T14:27:35Z" +head_ref: "post-0-0-0-cleanup-2026-04-29" +base_ref: "main" +archived_at: "2026-04-29T14:30:07Z" +archive_tool: "tools/pr-preservation/archive-pr.sh" +--- + +# PR #845: ops(0-0-0): LFG forward-sync — post-reset cleanup + Copilot fixes + pr-preservation drain-logs (mirror of AceHack #101) + +## PR description + +## Summary + +LFG forward-sync PR for the AceHack-first cleanup that landed at AceHack#101 (merged 2026-04-29T14:19:41Z, squash → `5485772e87d74f3b96cdac4f39063cb0e82d7839`). + +This is **step 2 of the canonical double-hop**: AceHack-first (#101 ✓) → LFG forward-sync (this PR) → AceHack absorbs LFG squash-SHA (after this merges). + +## Diff vs LFG main (same content as AceHack #101 + LFG-side review fixes + pr-preservation files) + +1. **Original cleanup commits** (from AceHack #101): stale-prose fixes in `docs/active-trajectory.md`, protection-config memory file, MEMORY.md index entry, tick shard 1410Z + +2. **LFG #844 Codex P2 fix** (commit `f6d6a94`): `gh api --input` syntax corrected to heredoc-stdin pattern + +3. **LFG #844 Copilot thread fixes** (this commit): + - Internal consistency on legacy DELETE response (DELETE returned 204; GET-after-DELETE returned 404 "Branch not protected" — two-step accuracy) + - "Task #305" → "task #275" (correct in-session TaskList reference) + namespace-disambiguation parenthetical + - "the only rulesets ruleset" → "the only ruleset" (wording nit) + +4. **PR-preservation drain-logs** (Aaron 2026-04-29 directive): `docs/pr-preservation/lfg-844-drain-log.md` + `docs/pr-preservation/acehack-101-drain-log.md` — verbatim threads + responses + outcome classes for both PRs in this double-hop round + +## Sequence after this PR merges + +1. LFG/main advances to new squash-SHA = `` +2. AceHack/main is at `5485772...` (post-#101); LFG/main moves to `` (post-this) +3. Force-push acehack/main → LFG/main `` (toggle ruleset / push / restore — same pattern as the 0/0/0 hard-reset) +4. AceHack/main = LFG/main = `` — 0/0/0 invariant restored + +## Authority boundary + +Step 3 (force-push to AceHack) is irreversible from the ref-perspective + requires ruleset toggle → **gates on Aaron's authority**. After this PR merges, I prepare the verify-only gate packet for the absorption push, then await Aaron's `EXECUTE`. + +Also addresses Copilot review feedback from LFG #844 carried forward. + +🤖 Generated with [Claude Code](https://claude.com/claude-code) + +## Reviews + +### COMMENTED — @copilot-pull-request-reviewer (2026-04-29T14:28:47Z) + +## Pull request overview + +Forward-syncs the AceHack-first post-reset cleanup into LFG, preserving operational learnings from the 0/0/0 reset and capturing PR review/drain artifacts as durable history. + +**Changes:** +- Adds/updates protection-config operational memory (dual-layer legacy branch protection vs rulesets) and indexes it in `memory/MEMORY.md`. +- Updates `docs/active-trajectory.md` to reflect the now-achieved 0/0/0 state (replacing stale pre-reset “not signoff-eligible” language). +- Adds PR-preservation drain logs for both sides of the double-hop and appends the 14:10Z tick-history shard. + +### Reviewed changes + +Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments. + +
+Show a summary per file + +| File | Description | +| ---- | ----------- | +| memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | Documents the dual-layer protection discovery, error-code mapping, and the operational sequence (incl. corrected `gh api --input -` usage). | +| memory/MEMORY.md | Adds an index entry pointing to the new protection-config memory. | +| docs/pr-preservation/lfg-844-drain-log.md | Records LFG-side PR #844 review threads and resolutions for training-signal preservation. | +| docs/pr-preservation/acehack-101-drain-log.md | Records AceHack-side PR #101 outcome (auto-merged/no-review) for the double-hop record. | +| docs/hygiene-history/ticks/2026/04/29/1410Z.md | Adds the 14:10Z tick shard row capturing the reset completion + cleanup PR opening. | +| docs/active-trajectory.md | Updates trajectory text to reflect the completed hard-reset and new next-action lane. | +
diff --git a/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md b/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md new file mode 100644 index 0000000000..c840e16999 --- /dev/null +++ b/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md @@ -0,0 +1,144 @@ +--- +pr_number: 101 +title: "ops(0-0-0): post-reset cleanup \u2014 stale-prose fixes + protection-config memory" +author: "AceHack" +state: "MERGED" +created_at: "2026-04-29T14:19:35Z" +merged_at: "2026-04-29T14:19:41Z" +closed_at: "2026-04-29T14:19:42Z" +head_ref: "post-0-0-0-cleanup-2026-04-29" +base_ref: "main" +archived_at: "2026-04-29T14:34:12Z" +archive_tool: "tools/pr-preservation/archive-pr.sh" +--- + +# PR #101: ops(0-0-0): post-reset cleanup — stale-prose fixes + protection-config memory + +## PR description + +## Summary + +Canonical AceHack-first PR: post-reset cleanup after the 0/0/0 hard-reset achieved 2026-04-29T14:04:50Z. Two scoped changes: + +1. **Stale-prose fixes in `docs/active-trajectory.md`** — flip post-reset contradicting language to in-force 0/0/0-achieved language +2. **Protection-config memory** — document the dual-layer surprise + Aaron's "delete legacy, rulesets canonical" decision + +## Lineage + +This PR was originally opened on LFG-side (Lucent-Financial-Group/Zeta#844) by mistake — Aaron correctly flagged that the canonical flow is AceHack-first → LFG forward-sync → AceHack absorbs LFG squash-SHA. *"Without the double-hop in a few hours we'll be right back to where we started — that's load-bearing to get right."* + the high-signal-data-multiplier framing: 2× review-agent passes per PR = 2× signal for the training corpus. + +LFG #844 closed; branch repushed to AceHack as the canonical first stop. Includes Codex P2 review feedback from the LFG side (gh api --input syntax fix at commit `f6d6a94`) preserved as part of the branch history. + +## 🎯 0/0/0 ACHIEVED 2026-04-29T14:04:50Z + +``` +AceHack/main = LFG/main = 621aae082d70fcbf36931718ecf1b6d9e149295f +Topology: 0 ahead, 0 behind, 0 file content diff +Archive ref: archive/acehack-main-pre-000-reset-2026-04-29 → 6755081... (preserved) +Layers: legacy DELETED (per Aaron); rulesets canonical +``` + +## Stale-prose fixes (Amara substrate-pass catch) + +Two paragraphs flipped from pre-reset state to in-force post-reset state: +- *"Currently NOT signoff-eligible"* → *"0/0/0 ACHIEVED 2026-04-29T14:04:50Z..."* +- *"Hard-reset is NOT YET signoff-eligible"* → *"Hard-reset complete (2026-04-29T14:04:50Z)..."* + +Derived-Rollup Drift class — primary state changed, downstream prose still claimed old state. + +## Protection-config memory + +`memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: + +- AceHack/Zeta had BOTH legacy branch protection AND repository rulesets on `main` +- Both layers enforced independently; GitHub UI doesn't surface dual-layer state +- Aaron: *"I knew there were two but I was confused why."* +- Maintainer call: legacy DELETED, rulesets canonical going forward +- Error-code mapping: `GH013` = rulesets surface, `GH006` = legacy surface +- Diagnostic script (`gh api` commands, with correct heredoc-stdin syntax per Codex's feedback) for future audits +- Future-protocol note: rulesets `non_fast_forward` rule still doesn't match CLAUDE.md *"force-push to AceHack main is part of protocol"* — task #305 home for that decision + +`MEMORY.md` index updated with one-line pointer. + +## Tick shard 1410Z + +Records the entire 0/0/0 hard-reset arc. + +## Sequence after this PR merges + +1. AceHack/main advances by 1 (this content) +2. Open forward-sync PR on LFG/Zeta with this content +3. After LFG forward-sync merges, force-push AceHack/main to LFG's squash-SHA (absorbs the LFG squash, restoring AceHack/main = LFG/main exactly) +4. AceHack/main = LFG/main again — 0/0/0 holds + +## Authority boundary going forward (per Amara post-reset packet) + +``` +Reversible + in-lane + PR-reviewed → proceed autonomously +Irreversible / deletion / force-push / authority config / identity canon → ask Aaron +Unclear → stop, report exact uncertainty, propose one safe action +``` + +## Test plan + +- [x] Stale "Currently NOT signoff-eligible" → in-force 0/0/0-achieved language +- [x] Stale "Hard-reset is NOT YET signoff-eligible" → "Hard-reset complete" language +- [x] Memory file written with corrected gh CLI syntax + MEMORY.md index updated +- [x] Tick shard 1410Z appended +- [x] Branch opened AceHack-first per double-hop discipline +- [ ] CI green +- [ ] Codex / Copilot reviews resolved if any threads land +- [ ] LFG forward-sync PR opened after merge +- [ ] AceHack absorbs LFG squash-SHA after forward-sync merge + +🤖 Generated with [Claude Code](https://claude.com/claude-code) + +## Reviews + +### COMMENTED — @copilot-pull-request-reviewer (2026-04-29T14:24:13Z) + +## Pull request overview + +Post-0/0/0 hard-reset cleanup PR that updates current-state docs/memory to reflect the achieved 0/0/0 status and captures a durable debugging note about GitHub’s dual-layer protection enforcement (legacy branch protection + rulesets) on AceHack/Zeta. + +**Changes:** +- Add a new protection-config memory documenting GH013 vs GH006 and a `gh api` audit/diagnostic sequence. +- Update `docs/active-trajectory.md` prose to reflect that the 0/0/0 hard-reset has completed. +- Append a tick shard row and add a new `MEMORY.md` index entry pointing to the new memory. + +### Reviewed changes + +Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments. + +| File | Description | +| ---- | ----------- | +| memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | New memory documenting dual-layer protection enforcement + commands/error-code mapping. | +| memory/MEMORY.md | Adds newest-first index entry pointing to the new protection-config memory. | +| docs/hygiene-history/ticks/2026/04/29/1410Z.md | New tick shard entry recording the 0/0/0 reset arc + follow-up PR. | +| docs/active-trajectory.md | Flips stale “not signoff-eligible” / “not yet” language to post-reset “complete/achieved” state. | + +## Review threads + +### Thread 1: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:101 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:24:11Z): + +P1: This file references `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md`, but that file does not exist in-repo (the path 404s). This leaves a broken cross-reference in the new memory. Either add the missing memory file in this PR, or update the reference to the correct existing in-repo memory that captures the same rule. + +### Thread 2: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:41 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:24:12Z): + +P1: The “Delete legacy branch protection” example is confusing/internally inconsistent: the comment says legacy protection was deleted, but the shown DELETE call returns “Branch not protected” (404), which indicates there was nothing to delete at that moment. Consider clarifying the sequence (e.g., DELETE returns 204 when protection exists; 404 means it was already removed) or adjusting the narrative so readers don’t infer that 404 = successful deletion. + +### Thread 3: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:24:12Z): + +P2: Minor wording issue: “the only rulesets ruleset” reads like a duplicated word and is easy to misread. Consider simplifying to “the only ruleset” (or “the only repository ruleset”). + +### Thread 4: memory/MEMORY.md:5 (unresolved) + +**@copilot-pull-request-reviewer** (2026-04-29T14:24:12Z): + +P2: `MEMORY.md` index entries are expected to be terse (memory/README.md notes the index is capped at ~200 lines and should stay short). This new entry is very long for a single-line index item; consider trimming the summary here and leaving the detailed narrative inside the linked memory file. diff --git a/docs/pr-preservation/acehack-101-drain-log.md b/docs/pr-preservation/acehack-101-drain-log.md index f97293af0e..e7a39696e7 100644 --- a/docs/pr-preservation/acehack-101-drain-log.md +++ b/docs/pr-preservation/acehack-101-drain-log.md @@ -5,28 +5,78 @@ **Opened:** 2026-04-29T14:18Z **Merged:** 2026-04-29T14:19:41Z (squash; merge commit `5485772e87d74f3b96cdac4f39063cb0e82d7839`) **Branch:** post-0-0-0-cleanup-2026-04-29 → main -**Status checks:** 17 ran (most short-running), no required-status-checks rule on AceHack so auto-merge fired ~2 min after open +**Status checks:** 17 ran; AceHack has no required-status-checks rule, so auto-merge fired ~2 min after open -## Threads (0 review threads, 0 issue-level comments) +## Threads (4 unresolved Copilot threads at merge — filed 14:24:11Z, AFTER auto-merge fired at 14:19:41Z) -AceHack/Zeta does NOT have Codex or Copilot installed as PR reviewers (or they didn't have time to file before auto-merge fired). Result: zero review-agent feedback was collected on this AceHack PR. The same content went through the LFG side as #844 first, where Codex + Copilot DID review and produce 5 substantive threads (preserved in `lfg-844-drain-log.md`). +The threads landed AFTER the merge because AceHack has no required-conversation-resolution rule and no required-status-checks rule — auto-merge didn't wait for Copilot's review. Copilot's findings still apply to the merged content; corrected in the post-#101 follow-up double-hop cycle. -This is the **double-hop training-data observation in practice**: AceHack and LFG produce different review-agent feedback per identical content. AceHack has weaker/no review coverage; LFG has the full Codex + Copilot pass. The double-hop value here is the LFG side, not the AceHack side. Per Aaron's framing, BOTH are valuable training signal — silence on AceHack is also signal (telling us AceHack's review surface is sparser). +### Thread 1 — Copilot P1 — broken xref to user-scope memory file + +**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +**Filed:** 2026-04-29T14:24:11Z +**Outcome class:** FIX (real broken-xref) + +> P1: This file references `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md`, but that file does not exist in-repo (the path 404s). This leaves a broken cross-reference in the new memory. Either add the missing memory file in this PR, or update the reference to the correct existing in-repo memory that captures the same rule. + +**Resolution path (post-#101 follow-up cycle):** The visibility-constraint memory exists in user-scope memory only (`~/.claude/projects/-Users-acehack-Documents-src-repos-Zeta/memory/`), not in-repo. The xref was therefore broken from an in-repo file pointing at a user-scope-only file. Replaced with a generic prose pointer to the underlying principle + a note that the existing `MEMORY.md` index entry has the same broken-pointer issue (pre-existing) and should be either backfilled to in-repo or removed in a future audit pass. + +### Thread 2 — Copilot P1 — internal consistency on legacy DELETE response + +**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +**Filed:** 2026-04-29T14:24:12Z +**Outcome class:** FIX (already-applied — was duplicate of LFG #844 Thread 3) + +> P1: The "Delete legacy branch protection" example is confusing/internally inconsistent: the comment says legacy protection was deleted, but the shown DELETE call returns "Branch not protected" (404), which indicates there was nothing to delete at that moment. Consider clarifying the sequence (e.g., DELETE returns 204 when protection exists; 404 means it was already removed) or adjusting the narrative so readers don't infer that 404 = successful deletion. + +**Resolution path:** Already addressed by the carried-forward fix from LFG #844 Thread 3 (in commit `19f8f0b` on the LFG forward-sync side). The post-fix memory file shows DELETE returned rc=0 (success / 204 No Content) with the 404 coming from a separate verification GET. AceHack #101 merged BEFORE this fix landed, so the merged AceHack/main has the pre-fix text. The post-#101 follow-up cycle carries the fix to AceHack via the next AceHack-first PR. + +### Thread 3 — Copilot P2 — wording "the only rulesets ruleset" + +**Filed:** 2026-04-29T14:24:12Z +**Outcome class:** FIX (already-applied — same path as Thread 2) + +> P2: Minor wording issue: "the only rulesets ruleset" reads like a duplicated word and is easy to misread. Consider simplifying to "the only ruleset" (or "the only repository ruleset"). + +**Resolution path:** Same as Thread 2 — already fixed in LFG #845 (carried forward in commit on the LFG-side branch); AceHack/main currently has the pre-fix text; carried into post-#101 follow-up cycle. + +### Thread 4 — Copilot P2 — MEMORY.md index entry too long + +**Path:** memory/MEMORY.md +**Filed:** 2026-04-29T14:24:12Z +**Outcome class:** FIX + +> P2: `MEMORY.md` index entries are expected to be terse (memory/README.md notes the index is capped at ~200 lines and should stay short). This new entry is very long for a single-line index item; consider trimming the summary here and leaving the detailed narrative inside the linked memory file. + +**Resolution path (post-#101 follow-up cycle):** Trimmed the index entry from a 4-line dense paragraph to a single concise line per `memory/README.md` discipline. Detail stays in the linked memory file. + +## Issue-level comments + +(none — auto-merged before any landed) + +## Reviews + +- **Copilot — COMMENTED at 14:24:13Z**: PR-overview review enumerating the 4 review-thread findings (consolidated review summary). ## Outcome class summary -- 0 threads filed -- 0 issue-level comments -- Outcome class: AUTO-MERGED-NO-REVIEW +- 4 threads total: ALL UNRESOLVED at merge time (because auto-merge fired before review landed) +- Outcome classes: 1 P1 broken-xref (FIX), 1 P1 internal-consistency (FIX, already-applied), 1 P2 wording (FIX, already-applied), 1 P2 MEMORY.md verbose (FIX) +- All 4 fixes carry into the post-#101 follow-up double-hop cycle ## Lessons for future PRs -1. **Review-agent coverage asymmetry between forks** is real and worth tracking. AceHack's review surface (Codex/Copilot bot configuration) is weaker than LFG's. The double-hop pattern compensates by routing every PR through LFG's review surface either before (AceHack-first → LFG forward-sync) or after (LFG-first → AceHack mirror). +1. **AceHack auto-merge races Copilot review** — without required-conversation-resolution + required-status-checks on AceHack, auto-merge can fire BEFORE reviewers land their threads. The threads still apply to the merged content; just need a follow-up cycle to land fixes. Worth flagging that AceHack's review surface is "best effort, post-hoc" while LFG's is "pre-merge gating." + +2. **The double-hop captures BOTH waves of review** — even when AceHack auto-merges fast, the LFG forward-sync PR re-runs review and catches the same findings (LFG #844 caught the same internal-consistency + wording issues). The double-hop is also a *redundancy mechanism* against fast-merge-on-AceHack. -2. **AceHack rulesets has no required-status-checks rule.** PRs auto-merge without lint/test gates passing. This is acceptable for the dev-mirror role (rapid iteration) but means AceHack-side PR quality depends on the human author + the eventual LFG forward-sync gate catching anything. +3. **`gh repo view` doesn't accept `GH_REPO` env var override** — the existing `tools/pr-preservation/archive-pr.sh` uses `gh repo view --json owner,name` which resolves to current-clone origin. To archive cross-fork PRs, either run from a clone with the right origin, run `gh repo set-default /` first, or write the archive manually with fork-prefixed filename. Captured here as a tool-improvement candidate. -3. **Documenting the asymmetry**: AceHack's role is "where work lands first for fast iteration"; LFG's role is "where review rigor lands and becomes durable substrate." The training-data corpus collects from BOTH, with the understanding that they capture different things. +4. **Cross-fork archive filename collision** — if AceHack and LFG both have a PR #101, single-namespace `PR-0101-.md` filenames collide. Use fork-prefixed naming for cross-fork: `PR-acehack-0101-.md` / `PR-lfg-0101-.md`. Until tool supports `--repo` arg, manual archive with fork-prefixed name is the workaround. -## Relationship to LFG #844 +## Relationship to other PRs in this round -This PR is the canonical-direction reopening of LFG #844 (which was opened LFG-first by mistake and closed per Aaron's correction: *"without the double-hop in a few hours we'll be right back to where we started — that's load-bearing to get right"*). The 5 review threads from #844 are preserved at `lfg-844-drain-log.md`; the corresponding fixes are committed to the same branch (`post-0-0-0-cleanup-2026-04-29`) and carried into both this AceHack PR and the upcoming LFG forward-sync PR. +- LFG #844 — opened LFG-first by mistake, closed; threads documented at `lfg-844-drain-log.md`. Most threads' fixes carried into LFG #845. +- LFG #845 — forward-sync of AceHack #101 + LFG #844 fixes + this drain-log; merged 14:27:35Z (squash → `3785124...`). +- This PR (AceHack #101) — first canonical hop; merged 14:19:41Z. The 4 Copilot threads landed AFTER merge and are corrected in the post-#101 follow-up double-hop. +- Pending — AceHack absorbs LFG squash-SHA `3785124...` to restore 0/0/0 (gates on Aaron's `EXECUTE`). diff --git a/memory/MEMORY.md b/memory/MEMORY.md index af84d0c9f5..7fc44cbe33 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,7 +2,7 @@ **📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** -- [**0/0/0 ACHIEVED + AceHack/Zeta protection-config dual-layer surprise — legacy deleted, rulesets canonical (Aaron decision, 2026-04-29T14:04:50Z)**](feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md) — Hard-reset of `acehack/main` to LFG `621aae0...` succeeded after dual-layer protection surprise: AceHack/Zeta had BOTH legacy branch protection AND repository rulesets on `main`; both enforced independently; GitHub UI doesn't surface the dual-layer state. Aaron: *"I knew there were two but I was confused why."* Maintainer call: legacy DELETED, rulesets canonical going forward. Error-code mapping: GH013 = rulesets surface, GH006 = legacy surface. Old AceHack tip preserved at `archive/acehack-main-pre-000-reset-2026-04-29`. +- [**0/0/0 ACHIEVED + AceHack/Zeta protection-config dual-layer (Aaron, 2026-04-29)**](feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md) — Hard-reset succeeded after dual-layer surprise (legacy + rulesets on AceHack/main, both enforcing). Aaron: legacy DELETED, rulesets canonical. GH013 = rulesets, GH006 = legacy. Old tip preserved at `archive/acehack-main-pre-000-reset-2026-04-29`. - [**Bare `main` is ambiguous — automation uses explicit refs (Amara, 2026-04-29)**](feedback_bare_main_ambiguity_automation_discipline_explicit_refs_required_amara_2026_04_29.md) — Generic multi-remote-repo automation rule: scripts use `refs/remotes//` (or `refs/heads/`); bare branch names only for interactive humans. Hard-stop on fatal base-ref errors. Caught when bare `git checkout main` was hitting `fatal: matched multiple (2) remote tracking branches` and the loop continued past the failure with wrong downstream state. diff --git a/memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md b/memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md index 21397a11ac..2b6c470b86 100644 --- a/memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +++ b/memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md @@ -101,4 +101,4 @@ gh api repos/{owner}/{repo}/branches/{branch} --jq '.protected' - `memory/feedback_destructive_git_op_5_pre_flight_disciplines_codex_gemini_2026_04_28.md` — pre-flight disciplines for destructive git ops (force-push needs `--force-with-lease=ref:exact-old-sha`) - `docs/active-trajectory.md` — 0/0/0 hard-reset gate spec + post-reset state - task #275 (TaskList, pending: "Set up acehack-first development workflow") — protection-config protocol-vs-ruleset alignment goes under that lane. Note: distinct from PR numbers #305/etc. which are unrelated artifacts; this is the in-session TaskCreate/TaskList tracker. -- `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md` — Aaron's visibility constraint; this case satisfied it because Aaron was repo admin on AceHack/Zeta and could see the toggles in UI (even if confused by the dual-layer surface) +- Aaron's standing visibility-constraint principle (don't change shared-production things he can't see) — satisfied here because Aaron is repo admin on AceHack/Zeta and the rulesets toggles are visible in the GitHub UI (even if confused by the dual-layer surface). The detailed memory for this principle currently lives in user-scope memory (not in-repo); a future audit pass should either backfill it to in-repo or remove the existing index pointer in `memory/MEMORY.md` that references the non-in-repo file. From 3cd01d23921706c0b6c01eef1b6b5677e8eab3d3 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 10:37:17 -0400 Subject: [PATCH 2/6] =?UTF-8?q?tools/pr-preservation:=20archive-pr.sh=20?= =?UTF-8?q?=E2=80=94=20add=20GH=5FREPO=20env=20var=20override=20for=20cros?= =?UTF-8?q?s-fork=20archives=20(Aaron=202026-04-29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Aaron 2026-04-29: "respect GH_REPO we should fix" The script previously hard-resolved the target repo via `gh repo view --json nameWithOwner`, which always returns the current-clone's repo (typically `Lucent-Financial-Group/Zeta`). For cross-fork archives — e.g., archiving an AceHack PR from a clone tracking LFG — this returned the wrong repo and the script either: - Archived the WRONG PR (a same-numbered PR in the default repo), or - Failed silently / produced misleading filename slugs. Workaround: `gh repo set-default /` before running, then reset after. Awkward and error-prone. Fix: the script now respects a `GH_REPO=/` env var before falling back to `gh repo view`. Resolution order: 1. `GH_REPO` env var → use as `/` (cross-fork archives) 2. `gh repo view --json nameWithOwner` → fall back to default-repo resolution Also added an `/` shape validator so a malformed GH_REPO value (no slash) hard-fails early instead of generating bogus output. Verification: re-ran `GH_REPO=AceHack/Zeta tools/pr-preservation/archive-pr.sh 101` — script now correctly resolves to AceHack/Zeta#101 and writes the archive with the right title/slug, instead of grabbing LFG/Zeta#101 (an unrelated 2026-04-22 PR with completely different content). Cross-fork filename-collision discipline (separate convention, applied manually for now): when archiving cross-fork PRs that may have number collisions with the default repo, use a fork-prefixed filename like `PR-acehack--.md`. This isn't yet in the tool — future enhancement candidate would auto-prefix when GH_REPO ≠ default-repo. --- tools/pr-preservation/archive-pr.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/pr-preservation/archive-pr.sh b/tools/pr-preservation/archive-pr.sh index f53f91fc1a..0b019bdf83 100755 --- a/tools/pr-preservation/archive-pr.sh +++ b/tools/pr-preservation/archive-pr.sh @@ -112,13 +112,24 @@ if ! REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"; then fi # Dynamic owner / name — works from forks or after rename. -# Requires `gh repo view` to succeed; the script hard-fails -# with exit 1 rather than silently defaulting to a baked-in -# NWO (better to fail loud than archive to the wrong repo -# path on a fork). -REPO_NWO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" -if [ -z "${REPO_NWO}" ]; then - echo "error: could not detect repo via 'gh repo view'. Is gh authenticated and this a GitHub repo?" >&2 +# Resolution order: +# 1. GH_REPO env var (e.g. GH_REPO=AceHack/Zeta) — needed for cross-fork +# archives where the local clone's `gh repo view` resolves to a +# different repo than the PR's home (e.g. local origin = LFG but +# archiving an AceHack PR). +# 2. `gh repo view --json nameWithOwner` — falls back to whichever repo +# gh-cli resolves for the current working directory (typically +# the local clone's `origin` remote, or the explicit `gh repo +# set-default` setting if one is in effect). +# The script hard-fails with exit 1 rather than silently defaulting to a +# baked-in NWO (better to fail loud than archive to the wrong repo path). +if [ -n "${GH_REPO:-}" ]; then + REPO_NWO="${GH_REPO}" +else + REPO_NWO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" +fi +if [ -z "${REPO_NWO}" ] || [ "${REPO_NWO}" = "${REPO_NWO#*/}" ]; then + echo "error: could not detect repo (need GH_REPO=/ env var or 'gh repo view' to succeed). Is gh authenticated and this a GitHub repo?" >&2 exit 1 fi REPO_OWNER="${REPO_NWO%/*}" From 96bd24671b5087c80f5d14d5e18b0665b6c2e1e1 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 10:39:57 -0400 Subject: [PATCH 3/6] ops: rename memory file to drop fork-prefix per Aaron's naming rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aaron 2026-04-29: "AceHack/Zeta we should not use a forks name in the main repo except for the special section for forks data that is unique to them like pr reviews, budgets, settings, maybe more." Memory directory is general substrate, NOT a fork-specific section like docs/pr-discussions/ or docs/pr-preservation/. The fork-prefix in `feedback_acehack_zeta_*` filename was therefore misplaced — the file's content describes AceHack/Zeta-specific config but the filename shouldn't repeat that. Renamed: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md → memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md Updated cross-references: - memory/MEMORY.md (index pointer) - docs/pr-discussions/PR-acehack-0101-...md (archive) - docs/pr-discussions/PR-0844-...md (archive) - docs/pr-discussions/PR-0845-...md (archive) - docs/pr-preservation/lfg-844-drain-log.md - docs/pr-preservation/acehack-101-drain-log.md Fork-prefix discipline going forward (per Aaron): - USE fork-prefix in: docs/pr-discussions/, docs/pr-preservation/, settings dirs, budget dirs (any fork-specific section) - DO NOT USE fork-prefix in: memory/, src/, docs/ general areas, tools/, anywhere not explicitly fork-scoped The file's CONTENT still references AceHack/Zeta as the specific repo it documents — that's substantive and correct. Just the filename doesn't repeat the fork name. --- ...eset-cleanup-stale-prose-fixes-protection-co.md | 14 +++++++------- ...orward-sync-post-reset-cleanup-copilot-fixes.md | 2 +- ...eset-cleanup-stale-prose-fixes-protection-co.md | 10 +++++----- docs/pr-preservation/acehack-101-drain-log.md | 4 ++-- docs/pr-preservation/lfg-844-drain-log.md | 10 +++++----- memory/MEMORY.md | 2 +- ...egacy_deleted_rulesets_canonical_2026_04_29.md} | 0 7 files changed, 21 insertions(+), 21 deletions(-) rename memory/{feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md => feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md} (100%) diff --git a/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md b/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md index 9e276510f1..48aa96f1b1 100644 --- a/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md +++ b/docs/pr-discussions/PR-0844-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md @@ -41,7 +41,7 @@ This is **Derived-Rollup Drift** class — primary state changed, downstream pro ## Protection-config memory -`memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: +`memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: - AceHack/Zeta had BOTH legacy branch protection AND repository rulesets on `main` - Both layers enforced independently; GitHub UI doesn't surface dual-layer state @@ -133,14 +133,14 @@ Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 c | File | Description | | ---- | ----------- | -| `memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md` | New memory capturing the GH013/GH006 dual-layer behavior, decision, and diagnostics. | +| `memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md` | New memory capturing the GH013/GH006 dual-layer behavior, decision, and diagnostics. | | `memory/MEMORY.md` | Adds an index entry pointing to the new protection-config memory. | | `docs/hygiene-history/ticks/2026/04/29/1410Z.md` | New tick shard recording the 0/0/0 achievement and follow-on cleanup PR. | | `docs/active-trajectory.md` | Flips two stale paragraphs to reflect the achieved post-reset state. | ## Review threads -### Thread 1: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:40 (resolved) +### Thread 1: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:40 (resolved) **@chatgpt-codex-connector** (2026-04-29T14:16:33Z): @@ -150,13 +150,13 @@ The `Executed` commands document `gh api ... --input '{"enforcement": "disabled" Useful? React with 👍 / 👎. -### Thread 2: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:42 (unresolved) +### Thread 2: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:42 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:19:27Z): The `gh api ... --input '{"enforcement": ...}'` invocations won’t work as written: `gh api --input` expects a file path (or stdin via `--input -`), not an inline JSON string. Use `-f enforcement=...`/`-F enforcement=...`, or pass JSON via stdin (e.g., `--input -`) so this is copy/paste-correct for future audits. -### Thread 3: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:43 (unresolved) +### Thread 3: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:43 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): @@ -167,13 +167,13 @@ gh api -X DELETE repos/AceHack/Zeta/branches/main/protection # → 204 No Content ``` -### Thread 4: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:82 (unresolved) +### Thread 4: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:82 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): References to “Task #305” here are ambiguous in-repo (this repo already has a PR #305, and backlog rows use `B-####` IDs under `docs/backlog/**`). Consider replacing “Task #305”/“#305-adjacent” with the actual backlog-row ID (if any) or a direct URL so readers don’t chase the wrong artifact. -### Thread 5: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) +### Thread 5: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:19:28Z): diff --git a/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md b/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md index f38b306311..7398e64dee 100644 --- a/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md +++ b/docs/pr-discussions/PR-0845-ops-0-0-0-lfg-forward-sync-post-reset-cleanup-copilot-fixes.md @@ -72,7 +72,7 @@ Copilot reviewed 6 out of 6 changed files in this pull request and generated no | File | Description | | ---- | ----------- | -| memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | Documents the dual-layer protection discovery, error-code mapping, and the operational sequence (incl. corrected `gh api --input -` usage). | +| memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | Documents the dual-layer protection discovery, error-code mapping, and the operational sequence (incl. corrected `gh api --input -` usage). | | memory/MEMORY.md | Adds an index entry pointing to the new protection-config memory. | | docs/pr-preservation/lfg-844-drain-log.md | Records LFG-side PR #844 review threads and resolutions for training-signal preservation. | | docs/pr-preservation/acehack-101-drain-log.md | Records AceHack-side PR #101 outcome (auto-merged/no-review) for the double-hop record. | diff --git a/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md b/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md index c840e16999..bce8ed5bf8 100644 --- a/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md +++ b/docs/pr-discussions/PR-acehack-0101-ops-0-0-0-post-reset-cleanup-stale-prose-fixes-protection-co.md @@ -48,7 +48,7 @@ Derived-Rollup Drift class — primary state changed, downstream prose still cla ## Protection-config memory -`memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: +`memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md`: - AceHack/Zeta had BOTH legacy branch protection AND repository rulesets on `main` - Both layers enforced independently; GitHub UI doesn't surface dual-layer state @@ -112,26 +112,26 @@ Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 c | File | Description | | ---- | ----------- | -| memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | New memory documenting dual-layer protection enforcement + commands/error-code mapping. | +| memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md | New memory documenting dual-layer protection enforcement + commands/error-code mapping. | | memory/MEMORY.md | Adds newest-first index entry pointing to the new protection-config memory. | | docs/hygiene-history/ticks/2026/04/29/1410Z.md | New tick shard entry recording the 0/0/0 reset arc + follow-up PR. | | docs/active-trajectory.md | Flips stale “not signoff-eligible” / “not yet” language to post-reset “complete/achieved” state. | ## Review threads -### Thread 1: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:101 (unresolved) +### Thread 1: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:101 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:24:11Z): P1: This file references `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md`, but that file does not exist in-repo (the path 404s). This leaves a broken cross-reference in the new memory. Either add the missing memory file in this PR, or update the reference to the correct existing in-repo memory that captures the same rule. -### Thread 2: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:41 (unresolved) +### Thread 2: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:41 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:24:12Z): P1: The “Delete legacy branch protection” example is confusing/internally inconsistent: the comment says legacy protection was deleted, but the shown DELETE call returns “Branch not protected” (404), which indicates there was nothing to delete at that moment. Consider clarifying the sequence (e.g., DELETE returns 204 when protection exists; 404 means it was already removed) or adjusting the narrative so readers don’t infer that 404 = successful deletion. -### Thread 3: memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) +### Thread 3: memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md:18 (unresolved) **@copilot-pull-request-reviewer** (2026-04-29T14:24:12Z): diff --git a/docs/pr-preservation/acehack-101-drain-log.md b/docs/pr-preservation/acehack-101-drain-log.md index e7a39696e7..9f195eeddf 100644 --- a/docs/pr-preservation/acehack-101-drain-log.md +++ b/docs/pr-preservation/acehack-101-drain-log.md @@ -13,7 +13,7 @@ The threads landed AFTER the merge because AceHack has no required-conversation- ### Thread 1 — Copilot P1 — broken xref to user-scope memory file -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md **Filed:** 2026-04-29T14:24:11Z **Outcome class:** FIX (real broken-xref) @@ -23,7 +23,7 @@ The threads landed AFTER the merge because AceHack has no required-conversation- ### Thread 2 — Copilot P1 — internal consistency on legacy DELETE response -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md **Filed:** 2026-04-29T14:24:12Z **Outcome class:** FIX (already-applied — was duplicate of LFG #844 Thread 3) diff --git a/docs/pr-preservation/lfg-844-drain-log.md b/docs/pr-preservation/lfg-844-drain-log.md index 0ca9b6662e..ef600e6d66 100644 --- a/docs/pr-preservation/lfg-844-drain-log.md +++ b/docs/pr-preservation/lfg-844-drain-log.md @@ -11,7 +11,7 @@ ### Thread 1 — Codex P2 — `gh api --input` syntax (RESOLVED via commit f6d6a94) **Author:** chatgpt-codex-connector -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md **Filed:** 2026-04-29T14:16:33Z **Outcome class:** FIX @@ -24,7 +24,7 @@ ### Thread 2 — Copilot — `gh api --input` (UNRESOLVED at close, addressed in carry-forward to #101 + LFG forward-sync) **Author:** copilot-pull-request-reviewer -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 42) +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 42) **Filed:** 2026-04-29T14:19:27Z **Outcome class:** FIX (duplicate finding, same root cause as Codex Thread 1) @@ -35,7 +35,7 @@ ### Thread 3 — Copilot — internal consistency on legacy DELETE response (UNRESOLVED, FIX in carry-forward) **Author:** copilot-pull-request-reviewer -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 43) +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 43) **Filed:** 2026-04-29T14:19:28Z **Outcome class:** FIX @@ -60,7 +60,7 @@ ### Thread 4 — Copilot — "Task #305" ambiguous reference (UNRESOLVED, FIX in carry-forward) **Author:** copilot-pull-request-reviewer -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 82) +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 82) **Filed:** 2026-04-29T14:19:28Z **Outcome class:** FIX (real ambiguity — wrong reference) @@ -73,7 +73,7 @@ ### Thread 5 — Copilot — wording nit "the only rulesets ruleset" (UNRESOLVED, FIX in carry-forward) **Author:** copilot-pull-request-reviewer -**Path:** memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 18) +**Path:** memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md (line 18) **Filed:** 2026-04-29T14:19:28Z **Outcome class:** FIX (small) diff --git a/memory/MEMORY.md b/memory/MEMORY.md index 7fc44cbe33..dfc7129445 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,7 +2,7 @@ **📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** -- [**0/0/0 ACHIEVED + AceHack/Zeta protection-config dual-layer (Aaron, 2026-04-29)**](feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md) — Hard-reset succeeded after dual-layer surprise (legacy + rulesets on AceHack/main, both enforcing). Aaron: legacy DELETED, rulesets canonical. GH013 = rulesets, GH006 = legacy. Old tip preserved at `archive/acehack-main-pre-000-reset-2026-04-29`. +- [**0/0/0 ACHIEVED + AceHack/Zeta protection-config dual-layer (Aaron, 2026-04-29)**](feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md) — Hard-reset succeeded after dual-layer surprise (legacy + rulesets on AceHack/main, both enforcing). Aaron: legacy DELETED, rulesets canonical. GH013 = rulesets, GH006 = legacy. Old tip preserved at `archive/acehack-main-pre-000-reset-2026-04-29`. - [**Bare `main` is ambiguous — automation uses explicit refs (Amara, 2026-04-29)**](feedback_bare_main_ambiguity_automation_discipline_explicit_refs_required_amara_2026_04_29.md) — Generic multi-remote-repo automation rule: scripts use `refs/remotes//` (or `refs/heads/`); bare branch names only for interactive humans. Hard-stop on fatal base-ref errors. Caught when bare `git checkout main` was hitting `fatal: matched multiple (2) remote tracking branches` and the loop continued past the failure with wrong downstream state. diff --git a/memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md b/memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md similarity index 100% rename from memory/feedback_acehack_zeta_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md rename to memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md From 2902edad1936bbbd6ea7ade969a74e6eac4dd65b Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 10:48:57 -0400 Subject: [PATCH 4/6] =?UTF-8?q?ops:=20address=20LFG=20#846=20Codex=20P2=20?= =?UTF-8?q?=E2=80=94=20handle=20GH=5FREPO=20host-qualified=20form=20[HOST/?= =?UTF-8?q?]OWNER/REPO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex P2 (14:46Z): the GH_REPO override path I just added validates "contains a slash" but parses as if always `OWNER/REPO`. Per gh CLI docs GH_REPO accepts `[HOST/]OWNER/REPO` (host prefix optional, used by GitHub Enterprise). With a host-qualified value the previous parsing produced wrong owner+name. Fix: case-statement parses both forms — 3-segment `HOST/OWNER/REPO` (take last two segments) and 2-segment `OWNER/REPO` (existing behavior). Added local sanity test confirming both parse correctly. Edge cases now handled: - `GH_REPO=AceHack/Zeta` → owner=AceHack, name=Zeta - `GH_REPO=github.com/AceHack/Zeta` → owner=AceHack, name=Zeta (host stripped) - `GH_REPO=enterprise.example.com/AceHack/Zeta` → owner=AceHack, name=Zeta (host stripped) - `GH_REPO=Zeta` (no slash) → empty owner+name → fail loud with helpful error This is a tiny CI/review correction per Amara's "don't expand #846 unless CI/review explicitly requires a tiny correction" guidance — Codex's catch is a real edge case, fix is small + isolated. --- tools/pr-preservation/archive-pr.sh | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/tools/pr-preservation/archive-pr.sh b/tools/pr-preservation/archive-pr.sh index 0b019bdf83..972f8467dc 100755 --- a/tools/pr-preservation/archive-pr.sh +++ b/tools/pr-preservation/archive-pr.sh @@ -128,12 +128,31 @@ if [ -n "${GH_REPO:-}" ]; then else REPO_NWO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" fi -if [ -z "${REPO_NWO}" ] || [ "${REPO_NWO}" = "${REPO_NWO#*/}" ]; then - echo "error: could not detect repo (need GH_REPO=/ env var or 'gh repo view' to succeed). Is gh authenticated and this a GitHub repo?" >&2 +# Validate + parse OWNER/REPO. GH_REPO per gh CLI docs accepts +# `[HOST/]OWNER/REPO` (host prefix optional, e.g. for GitHub Enterprise). +# We split by taking the last two segments — ignoring optional leading host. +case "${REPO_NWO}" in + */*/*) + # 3-segment form `HOST/OWNER/REPO` (host-qualified, e.g. Enterprise) + REPO_NAME="${REPO_NWO##*/}" # last segment + _REPO_TMP="${REPO_NWO%/*}" # everything before last / + REPO_OWNER="${_REPO_TMP##*/}" # second-to-last segment + unset _REPO_TMP + ;; + */*) + # 2-segment form `OWNER/REPO` (default github.com) + REPO_OWNER="${REPO_NWO%/*}" + REPO_NAME="${REPO_NWO#*/}" + ;; + *) + REPO_OWNER="" + REPO_NAME="" + ;; +esac +if [ -z "${REPO_OWNER}" ] || [ -z "${REPO_NAME}" ]; then + echo "error: could not detect repo (need GH_REPO=[HOST/]OWNER/REPO env var or 'gh repo view' to succeed). Is gh authenticated and this a GitHub repo?" >&2 exit 1 fi -REPO_OWNER="${REPO_NWO%/*}" -REPO_NAME="${REPO_NWO#*/}" export REPO_ROOT PR REPO_OWNER REPO_NAME OUT_DIR="${REPO_ROOT}/docs/pr-discussions" From d263a010381a1f227f5f8f570909d330cc1f6b51 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 10:58:18 -0400 Subject: [PATCH 5/6] =?UTF-8?q?ops(0-0-0):=20#846=20review=20wave=20?= =?UTF-8?q?=E2=80=94=20strict=20GH=5FREPO=20validation=20+=20host=20propag?= =?UTF-8?q?ation=20+=20drain-log=20corrections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses 4 unresolved review threads on PR #846 that landed 2026-04-29T14:50:51Z..14:52:00Z, after auto-merge was armed. tools/pr-preservation/archive-pr.sh: - (Codex P2) Propagate parsed REPO_HOST to `gh api --hostname`. Previous parser captured the host segment from `GH_REPO=HOST/OWNER/REPO` then discarded it, so cross-fork archive runs against GitHub Enterprise repos silently targeted github.com. Now both `gh api graphql` calls in the Python child receive `--hostname HOST` when REPO_HOST is set. - (Copilot P1) Strict GH_REPO validation. Previous parser accepted malformed values like `/repo`, `owner/`, and `owner/repo/extra` (the last would be parsed as host=owner / owner=repo / repo=extra). New rules: 4+ segments rejected outright; 3-segment HOST/OWNER/REPO requires HOST to look like a hostname (contain a dot); embedded slashes inside owner/repo rejected as defence in depth against path-injection into docs/pr-discussions/. Verified locally against 10 edge cases (3 valid + 7 invalid). docs/pr-preservation/acehack-101-drain-log.md: - (Copilot P1) Thread 1 resolution: corrected the false claim that in-repo `memory/MEMORY.md` has a matching broken pointer. The user-scope MEMORY.md has the index entry; in-repo MEMORY.md does not. Backfill tracked under task #291. - (Copilot P1) Lesson 3: rewritten as "pre-fix behavior" documenting how operators worked around the lack of GH_REPO support before this PR, with the post-fix command shape (`GH_REPO=fork/repo archive-pr.sh N`) and a forward pointer to task #314 for the fuller fork-routing patch. memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md: - Same false-pointer correction as the drain-log: the visibility-constraint memory exists in user-scope only; in-repo MEMORY.md does not index it. Pointer corrected to the user-scope path with task #291 forward link. Test: - `bash -n tools/pr-preservation/archive-pr.sh` passes. - 10-case parser test (3 valid: owner/repo, github.com/owner/repo, github.example.com/owner/repo; 7 invalid: /repo, owner/, owner/repo/extra, host.com/owner/repo/extra, empty, owner-only, host.com//repo) all return expected rc + output. Co-Authored-By: Claude Opus 4.7 --- docs/pr-preservation/acehack-101-drain-log.md | 6 +- ...y_deleted_rulesets_canonical_2026_04_29.md | 2 +- tools/pr-preservation/archive-pr.sh | 67 +++++++++++++++++-- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/docs/pr-preservation/acehack-101-drain-log.md b/docs/pr-preservation/acehack-101-drain-log.md index 9f195eeddf..cb8617f826 100644 --- a/docs/pr-preservation/acehack-101-drain-log.md +++ b/docs/pr-preservation/acehack-101-drain-log.md @@ -19,7 +19,7 @@ The threads landed AFTER the merge because AceHack has no required-conversation- > P1: This file references `memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md`, but that file does not exist in-repo (the path 404s). This leaves a broken cross-reference in the new memory. Either add the missing memory file in this PR, or update the reference to the correct existing in-repo memory that captures the same rule. -**Resolution path (post-#101 follow-up cycle):** The visibility-constraint memory exists in user-scope memory only (`~/.claude/projects/-Users-acehack-Documents-src-repos-Zeta/memory/`), not in-repo. The xref was therefore broken from an in-repo file pointing at a user-scope-only file. Replaced with a generic prose pointer to the underlying principle + a note that the existing `MEMORY.md` index entry has the same broken-pointer issue (pre-existing) and should be either backfilled to in-repo or removed in a future audit pass. +**Resolution path (post-#101 follow-up cycle):** The visibility-constraint memory exists in user-scope memory only (`~/.claude/projects/-Users-acehack-Documents-src-repos-Zeta/memory/`), not in-repo. The original xref was therefore broken — an in-repo file pointing at a user-scope-only file. Replaced with a generic prose pointer to the underlying principle. (Earlier drafts of this drain-log claimed in-repo `memory/MEMORY.md` had a matching broken pointer; on closer inspection it does not — the user-scope MEMORY.md has the index entry, in-repo MEMORY.md does not. Backfill of the visibility-constraint memory to in-repo is tracked under task #291 / MEMORY.md index audit.) ### Thread 2 — Copilot P1 — internal consistency on legacy DELETE response @@ -70,9 +70,9 @@ The threads landed AFTER the merge because AceHack has no required-conversation- 2. **The double-hop captures BOTH waves of review** — even when AceHack auto-merges fast, the LFG forward-sync PR re-runs review and catches the same findings (LFG #844 caught the same internal-consistency + wording issues). The double-hop is also a *redundancy mechanism* against fast-merge-on-AceHack. -3. **`gh repo view` doesn't accept `GH_REPO` env var override** — the existing `tools/pr-preservation/archive-pr.sh` uses `gh repo view --json owner,name` which resolves to current-clone origin. To archive cross-fork PRs, either run from a clone with the right origin, run `gh repo set-default /` first, or write the archive manually with fork-prefixed filename. Captured here as a tool-improvement candidate. +3. **(Pre-fix behavior, now resolved in PR #846)** `tools/pr-preservation/archive-pr.sh` originally used `gh repo view --json nameWithOwner` to resolve the target repo, ignoring any `GH_REPO` env var set by the operator. To archive cross-fork PRs operators had to either cd into a clone with the right origin, run `gh repo set-default /` first, or write the archive manually with a fork-prefixed filename. **PR #846 fixed this**: the script now honors `GH_REPO=[HOST/]OWNER/REPO` (matching `gh` CLI conventions, including GitHub Enterprise host prefix), validates the value strictly, and propagates the host to `gh api --hostname` so cross-fork Enterprise archives target the right backend. Cross-fork archive command (post-fix): `GH_REPO=AceHack/Zeta tools/pr-preservation/archive-pr.sh `. -4. **Cross-fork archive filename collision** — if AceHack and LFG both have a PR #101, single-namespace `PR-0101-.md` filenames collide. Use fork-prefixed naming for cross-fork: `PR-acehack-0101-.md` / `PR-lfg-0101-.md`. Until tool supports `--repo` arg, manual archive with fork-prefixed name is the workaround. +4. **Cross-fork archive filename collision** — if AceHack and LFG both have a PR #101, single-namespace `PR-0101-.md` filenames collide. Use fork-prefixed naming for cross-fork: `PR-acehack-0101-.md` / `PR-lfg-0101-.md`. Long-term fix tracked as task #314 (canonical fork-data homes — migrate fork-prefixed files to `forks//pr-reviews/` trees + fuller `archive-pr.sh` patch with frontmatter `repo:` field, `--out-dir`, auto-route). ## Relationship to other PRs in this round diff --git a/memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md b/memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md index 2b6c470b86..35866b09d1 100644 --- a/memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md +++ b/memory/feedback_protection_config_dual_layer_legacy_deleted_rulesets_canonical_2026_04_29.md @@ -101,4 +101,4 @@ gh api repos/{owner}/{repo}/branches/{branch} --jq '.protected' - `memory/feedback_destructive_git_op_5_pre_flight_disciplines_codex_gemini_2026_04_28.md` — pre-flight disciplines for destructive git ops (force-push needs `--force-with-lease=ref:exact-old-sha`) - `docs/active-trajectory.md` — 0/0/0 hard-reset gate spec + post-reset state - task #275 (TaskList, pending: "Set up acehack-first development workflow") — protection-config protocol-vs-ruleset alignment goes under that lane. Note: distinct from PR numbers #305/etc. which are unrelated artifacts; this is the in-session TaskCreate/TaskList tracker. -- Aaron's standing visibility-constraint principle (don't change shared-production things he can't see) — satisfied here because Aaron is repo admin on AceHack/Zeta and the rulesets toggles are visible in the GitHub UI (even if confused by the dual-layer surface). The detailed memory for this principle currently lives in user-scope memory (not in-repo); a future audit pass should either backfill it to in-repo or remove the existing index pointer in `memory/MEMORY.md` that references the non-in-repo file. +- Aaron's standing visibility-constraint principle (don't change shared-production things he can't see) — satisfied here because Aaron is repo admin on AceHack/Zeta and the rulesets toggles are visible in the GitHub UI (even if confused by the dual-layer surface). The detailed memory for this principle currently lives in user-scope memory only (`~/.claude/projects/-Users-acehack-Documents-src-repos-Zeta/memory/feedback_aaron_visibility_constraint_no_changes_he_cant_see_2026_04_28.md`), not in-repo. (In-repo `memory/MEMORY.md` does not currently index the visibility-constraint principle; user-scope MEMORY.md does.) A future audit pass should backfill this principle to in-repo memory; tracked under task #291 (MEMORY.md index audit + backfill). diff --git a/tools/pr-preservation/archive-pr.sh b/tools/pr-preservation/archive-pr.sh index 972f8467dc..bcd1817f9f 100755 --- a/tools/pr-preservation/archive-pr.sh +++ b/tools/pr-preservation/archive-pr.sh @@ -128,15 +128,33 @@ if [ -n "${GH_REPO:-}" ]; then else REPO_NWO="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" fi -# Validate + parse OWNER/REPO. GH_REPO per gh CLI docs accepts -# `[HOST/]OWNER/REPO` (host prefix optional, e.g. for GitHub Enterprise). -# We split by taking the last two segments — ignoring optional leading host. +# Validate + parse OWNER/REPO (and optional HOST for GitHub Enterprise). +# GH_REPO per gh CLI docs accepts `[HOST/]OWNER/REPO`. Strict parser: +# - 2-segment `OWNER/REPO` → host defaults to github.com (gh CLI default) +# - 3-segment `HOST/OWNER/REPO` → HOST must look like a hostname (contain +# a dot, e.g. `github.example.com`). Bare 3-segment values like +# `owner/repo/extra` are rejected — they're either malformed or a +# mis-typed 2-segment value, never a valid Enterprise URL. +# - Empty owner or name (e.g. `/repo`, `owner/`, `host//repo`) → reject. +# Host propagation: when REPO_HOST is set, pass `--hostname` to all +# `gh api` calls so cross-fork archive runs against Enterprise repos +# actually target the right backend. (Codex P2 #846: previously the host +# was parsed but discarded, so host-qualified GH_REPO values silently hit +# github.com.) +REPO_HOST="" case "${REPO_NWO}" in + */*/*/*) + # 4+ segments — never valid for `[HOST/]OWNER/REPO`. Fall through to + # rejection rather than silently picking the last two segments. + REPO_OWNER="" + REPO_NAME="" + ;; */*/*) # 3-segment form `HOST/OWNER/REPO` (host-qualified, e.g. Enterprise) REPO_NAME="${REPO_NWO##*/}" # last segment _REPO_TMP="${REPO_NWO%/*}" # everything before last / REPO_OWNER="${_REPO_TMP##*/}" # second-to-last segment + REPO_HOST="${_REPO_TMP%/*}" # first segment (host) unset _REPO_TMP ;; */*) @@ -150,11 +168,36 @@ case "${REPO_NWO}" in ;; esac if [ -z "${REPO_OWNER}" ] || [ -z "${REPO_NAME}" ]; then - echo "error: could not detect repo (need GH_REPO=[HOST/]OWNER/REPO env var or 'gh repo view' to succeed). Is gh authenticated and this a GitHub repo?" >&2 + echo "error: could not detect repo (need GH_REPO=[HOST/]OWNER/REPO env var or 'gh repo view' to succeed). Is gh authenticated and this a GitHub repo? Got: '${REPO_NWO:-(empty)}'" >&2 + exit 1 +fi +# Reject embedded slashes inside owner/repo (defence in depth — the case +# patterns above should already prevent this, but a path-injection here +# would land archive output outside docs/pr-discussions/). +case "${REPO_OWNER}" in *"/"*) + echo "error: REPO_OWNER cannot contain a slash (got: '${REPO_OWNER}')" >&2 + exit 1 + ;; +esac +case "${REPO_NAME}" in *"/"*) + echo "error: REPO_NAME cannot contain a slash (got: '${REPO_NAME}')" >&2 exit 1 + ;; +esac +# When 3-segment form was given, validate host looks like a hostname +# (contain a dot). This rejects ambiguous values like `owner/repo/extra` +# which would otherwise parse as host=owner / owner=repo / repo=extra. +if [ -n "${REPO_HOST}" ]; then + case "${REPO_HOST}" in + *.*) : ;; # ok, contains a dot + *) + echo "error: GH_REPO 3-segment form must be HOST/OWNER/REPO where HOST is a hostname containing a dot (e.g. github.example.com/owner/repo). Got: '${REPO_NWO}'" >&2 + exit 1 + ;; + esac fi -export REPO_ROOT PR REPO_OWNER REPO_NAME +export REPO_ROOT PR REPO_OWNER REPO_NAME REPO_HOST OUT_DIR="${REPO_ROOT}/docs/pr-discussions" mkdir -p "$OUT_DIR" @@ -177,6 +220,7 @@ import json, os, subprocess, sys OWNER = os.environ['REPO_OWNER'] NAME = os.environ['REPO_NAME'] +HOST = os.environ.get('REPO_HOST') or '' PR = int(os.environ['PR']) QUERY = """ @@ -254,8 +298,17 @@ query($threadId: ID!, $after: String) { """ def gh_graphql(query, variables): - """Invoke gh api graphql and return parsed JSON or raise.""" - cmd = ["gh", "api", "graphql", "-f", f"query={query}"] + """Invoke gh api graphql and return parsed JSON or raise. + + Honour HOST when REPO_HOST was parsed from a 3-segment GH_REPO + (Codex P2 #846): without --hostname, gh api defaults to github.com, + so host-qualified GH_REPO values would silently target the wrong + backend on GitHub Enterprise. + """ + cmd = ["gh", "api"] + if HOST: + cmd.extend(["--hostname", HOST]) + cmd.extend(["graphql", "-f", f"query={query}"]) for k, v in variables.items(): if v is None: # gh treats -F with empty string as null; for explicit null From 4c15754e2118c36cad80299c0e3e7da4b9548c16 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Wed, 29 Apr 2026 11:09:40 -0400 Subject: [PATCH 6/6] =?UTF-8?q?ops(0-0-0):=20retrigger=20CI=20on=20#846=20?= =?UTF-8?q?=E2=80=94=20Code=20Quality=20CodeQL=20hit=20transient=20auth-se?= =?UTF-8?q?rvice=20401=20at=2015:00:42Z?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dynamic Code Scanning check (`Code Quality: PR #846`) failed its SARIF upload step at 2026-04-29T15:00:42Z with: ##[warning]Requires authentication - https://docs.github.com/rest ##[error]Please check that your token is valid and has the required permissions: contents: read, security-events: write Same window saw `gh api graphql` 401s on the maintainer laptop; both cleared a few minutes later (gh works again with -X POST flag). The Code Quality run is the dynamic-event variety that cannot be retried via `gh run rerun --failed`. Empty commit is the only way to retrigger. Required-checks rollup is 7/7 SUCCESS; the Code Quality check is a non-required gate that auto-merge waits on regardless. Diagnostic runbook for this failure mode lives at memory/reference_gh_cli_* (target home: docs/ops/runbooks/gh-cli-auth-401.md per Amara, follow-up). Co-Authored-By: Claude Opus 4.7