diff --git a/docs/active-trajectory.md b/docs/active-trajectory.md index 365c28fe75..5b5a462d69 100644 --- a/docs/active-trajectory.md +++ b/docs/active-trajectory.md @@ -27,21 +27,24 @@ > before the trajectory file's classification is treated as authoritative > by external readers. -## Priority — blocking all other work +## Priority — RE-CLOSED 2026-04-29T15:17:09Z -**0/0/0 hard-reset: AceHack main = LFG main (0 ahead, 0 behind, 0 file content-diff).** +**0/0/0 hard-reset achieved + post-double-hop re-close successful.** AceHack/main = LFG/main = `17a26370ea5eb979406a3913d57348d3b647afd8`. The trajectory's load-bearing question — *"can we run a clean double-hop without 0/0/0 falling apart in a few hours?"* — answered yes: the round-trip (AceHack #101 → LFG #845 → AceHack #103 → LFG #846 → AceHack absorbs `17a26370`) closed at 15:17:09Z with all gates green. -Per `CLAUDE.md` AceHack-LFG topology invariant + `memory/feedback_lfg_master_acehack_zero_divergence_fork_double_hop_aaron_2026_04_27.md`. The maintainer 2026-04-29 framing: *"this is the only trajectory i care about right now, it's blocking everything else."* +Per `CLAUDE.md` AceHack-LFG topology invariant + `memory/feedback_lfg_master_acehack_zero_divergence_fork_double_hop_aaron_2026_04_27.md`. The maintainer 2026-04-29 framing: *"this is the only trajectory i care about right now, it's blocking everything else."* — that block is now lifted. -While this trajectory is active: +Post-double-hop sequencing per Amara 2026-04-29 (in priority order): -- Do NOT start LOST-branch recovery (task #264). -- Do NOT begin Aurora Round-3 absorption (task #286). -- Do NOT process the multi-AI synthesis backlog (tasks #309 / #310 / #311). -- Do NOT open new memory files or new substrate islands (B-0105 consolidation gate is still active). -- Do NOT run autonomous tick-history shards while in audit-spiral mode — wait for state change. +1. **task 315 — Budget cadence (hourly measurement, bounded publication)** — HIGH-priority. *"Weekly is archaeology, not control."* The Amara nuance "hourly measurement, bounded publication" applies (measure hourly append-only; publish on threshold or daily roll-up; never PR-spam hourly). +2. **task 319 — Bounded-retry mechanism for CodeQL dynamic-default-setup** — Aaron's directive: empty-commit retrigger is a workaround, the proper fix is bounded-retry per DST. +3. **task 318 — docs/ops taxonomy** (runbooks/patterns/incidents tree) — establishes canonical homes for the substrate this round produced (gh-401 runbook, Bounded-Publication pattern, Drain-Log Claim Verification pattern, 0-0-0-reset incident narrative). +4. **task 317 — Tick-history fast-path policy** (trusted-actor + safe-path + safe-op rule) — relieves the "every heartbeat treated as mini product release" anxiety. +5. **task 316 — Drain-Log Claim Verification Discipline** — absorbed into the docs/ops/patterns/ tree as part of task 318. +6. **task 313 — Pre-fix + post-fix lint for fork-name discipline** — substrate-balance hygiene. +7. **task 314 — Canonical fork-data homes** (`forks//*` migration + fuller archive-pr.sh patch). +8. **Branch/worktree/stash recovery lane** — gates on completion of items 1-7. Inventory parked at `/tmp/recovery-inventory-2026-04-29.tsv` (918 branches: 123 ALREADY_REACHABLE / 795 NOT_REACHABLE; 58 worktrees clean; 7 stashes). Awaiting Amara's recovery-classification framework before any branch/worktree mutation. -The autonomous-loop tick MAY still produce minimal honest-wait acknowledgements, but every action toward the trajectory must read this file first. +The previous "Do NOT" block is rescinded: LOST-branch recovery (#264) gates on item 8; Aurora Round-3 (#286) and multi-AI synthesis (#309/#310/#311) re-enter normal backlog ordering; new memory files / substrate islands resume per their normal rules; autonomous tick-history shards resume normal cadence. ## Canonical state-bearing artifacts @@ -218,7 +221,9 @@ Per multi-AI review 2026-04-29T10:35Z: dry-run push shape verification is added Lease rejection on the real push is NOT a retry condition. It means the remote moved between observation and push — restart the safety gate from the top (re-fetch, recompute content-drift ledger, re-classify if anything moved). -**0/0/0 ACHIEVED 2026-04-29T14:04:50Z**: AceHack/main = LFG/main = `621aae082d70fcbf36931718ecf1b6d9e149295f`. Topology: 0 ahead, 0 behind, 0 file content diff. Old AceHack tip `675508187a5e80bd0a8c14a74a9ae80d5346e722` preserved at `archive/acehack-main-pre-000-reset-2026-04-29` on AceHack (named ref, indefinite reachability). Strict gate's classification + operational conditions all satisfied; maintainer signoff received and executed. The four-bucket ledger remains source of truth for any future drift detection. +**0/0/0 ACHIEVED 2026-04-29T14:04:50Z** (initial hard-reset): AceHack/main = LFG/main = `621aae082d70fcbf36931718ecf1b6d9e149295f`. Topology: 0 ahead, 0 behind, 0 file content diff. Old AceHack tip `675508187a5e80bd0a8c14a74a9ae80d5346e722` preserved at `archive/acehack-main-pre-000-reset-2026-04-29` on AceHack (named ref, indefinite reachability). Strict gate's classification + operational conditions all satisfied; maintainer signoff received and executed. The four-bucket ledger remains source of truth for any future drift detection. + +**0/0/0 RE-CLOSED 2026-04-29T15:17:09Z** (post-double-hop absorption): AceHack/main = LFG/main = `17a26370ea5eb979406a3913d57348d3b647afd8`. Sequence: AceHack-first PR #101 merged 14:19:41Z (squash → `5485772`) → LFG forward-sync PR #845 merged 14:27:35Z (squash → `3785124`) → AceHack-first follow-up PR #103 merged with Copilot fixes + GH_REPO support 14:?:?Z (squash → `b7a6a95d`) → LFG forward-sync v2 PR #846 merged 15:12:14Z (squash → `17a26370`) → AceHack absorption ceremony 15:17:09Z (force-with-lease + ruleset toggle + restore). The double-hop discipline (AceHack-first → LFG forward-sync → AceHack absorbs LFG squash-SHA) closed cleanly. Pre-execute SHA `b7a6a95d` is preserved in commit-graph reachability via the AceHack-side PR #103 squash that captured its content; no archive-ref needed for this round since the absorption is post-canonical-double-hop, not a content-rewrite hard-reset. Post-double-hop close is what "load-bearing without the double-hop in a few hours we'll be right back to where we started" called for. ### 9 infra files (verified 2026-04-29T09:50Z against current git state, NOT against the 16h-old plan) diff --git a/docs/hygiene-history/ticks/2026/04/29/1458Z.md b/docs/hygiene-history/ticks/2026/04/29/1458Z.md new file mode 100644 index 0000000000..aec593c072 --- /dev/null +++ b/docs/hygiene-history/ticks/2026/04/29/1458Z.md @@ -0,0 +1 @@ +| 2026-04-29T14:58:00Z | claude-opus-4-7 | b9ccd753 | **PR #846 review wave addressed — 4 unresolved threads resolved; commit `d263a01` pushed; CI re-running.** State: PR #846 (LFG forward-sync v2 of post-#101 follow-up) BLOCKED with auto-merge armed since 14:43:33Z; CI mostly green except CodeQL csharp (~2:43 in) + build-and-test (macos-26) (~2:33 in); 0 unresolved threads (Codex P2 on `tools/pr-preservation/archive-pr.sh:131` GH_REPO `[HOST/]OWNER/REPO` parsing resolved at commit `2902eda`). After-compaction resume: read 1410Z tick + active-trajectory + MEMORY.md to re-orient. Amara packet (post-compaction) ratifies: hourly budget cadence is right target; Otto correct not to put it into #846; GH_REPO fix appropriate scope for this PR; current parser (last-two-segments) handles enterprise host-prefix correctly; **don't expand #846 further unless CI/review requires it**. Amara hourly-budget nuance landed: "hourly measurement, bounded publication" — measure hourly, persist append-only if changed, escalate on threshold, roll up daily, **don't spam PRs hourly unless threshold breached**. That nuance now captured in task #315 description with concrete shape (cron `13 * * * *` for hourly sample, separate `7 0 * * *` daily-rollup PR, threshold-based escalation, daily PR cap = 1). This avoids the GITHUB_TOKEN-doesn't-trigger-downstream-checks wall hourly cadence would have hit. **Sequenced lane (Amara, post-double-hop close)**: 1. Let #846 merge. 2. Preserve #846 review signal (archive-pr.sh exercises new GH_REPO support). 3. Prepare pure read-only absorption packet (no `git push --dry-run` per harness destructive-ceremony classification — use `git fsck`, `git ls-remote`, `git rev-list --count`, `git diff --stat`). 4. Ask Aaron `EXECUTE`. 5. Toggle ruleset (id=15524390) → force-push AceHack/main to LFG/main squash-SHA → restore ruleset. 6. Verify 0 ahead / 0 behind / zero file diff. 7. **#315 hourly budget cadence (HIGH-priority)** before #313/#314/recovery. Branch/worktree/stash recovery (918/58/7 inventory at `/tmp/recovery-inventory-2026-04-29.tsv`) gates on 0/0/0 re-close. This tick: heartbeat poll cycle while CI completes; stay-in-cache `ScheduleWakeup(270s)` on each iteration. Authority boundary holds: reversible+in-lane → proceed; force-push/destructive → ask Aaron. Cron `b9ccd753` alive. | [PR #846](https://github.com/Lucent-Financial-Group/Zeta/pull/846) | **Best blade this tick (Amara)**: *"Hourly measurement, bounded publication. Do not spam PRs hourly unless threshold breached. That keeps cost visibility tight without turning the repo into a metronome of budget commits."* — composes the granularity-vs-noise tension into a single shape: measure-frequently + publish-rarely. Future-self note: any high-cadence sensor (budget, drift, hygiene-counter, anything that wants to fire >daily) gets the bounded-publication treatment by default; only threshold-breach earns a PR. Otto-lesson candidate name: **Bounded-Publication Discipline**. **Review wave (added in this tick)**: 4 threads landed 14:50:51-14:52:00Z (3× Copilot P1 + 1× Codex P2). The Codex P2 was the structurally important one — my prior parser captured the host segment but discarded it before calling `gh`, so 3-segment `GH_REPO=HOST/OWNER/REPO` silently fell back to github.com. Fix: thread `REPO_HOST` through the env into the Python child, pass `--hostname` when set. Copilot P1s caught (a) too-loose validation (`/repo`, `owner/`, `owner/repo/extra` all passed), (b) drain-log Thread 1 resolution claimed in-repo MEMORY.md had a broken pointer it didn't have (only user-scope had it), (c) Lesson 3 was stale (claimed GH_REPO unsupported when this PR is what added it). Future-self lesson: **don't claim "pre-existing X exists in Y" without grepping Y first**. The drain-log is itself a substrate file; misstating its claims is misinforming a future-self that reads it for ground truth. Pattern: any drain-log claim that asserts an external file's contents must have a verification step (grep/ls/read) within the same edit — claim-without-verify is the failure mode this round caught. Otto-lesson candidate name: **Drain-Log Claim Verification Discipline**. | diff --git a/docs/hygiene-history/ticks/2026/04/29/1517Z.md b/docs/hygiene-history/ticks/2026/04/29/1517Z.md new file mode 100644 index 0000000000..a912edc426 --- /dev/null +++ b/docs/hygiene-history/ticks/2026/04/29/1517Z.md @@ -0,0 +1 @@ +| 2026-04-29T15:17:09Z | claude-opus-4-7 | b9ccd753 | **🎯 0/0/0 RE-CLOSED post-double-hop. AceHack/main = LFG/main = `17a26370ea5eb979406a3913d57348d3b647afd8`.** Sequence: PR #846 (LFG forward-sync v2 of post-#101 follow-up) merged 15:12:14Z (squash → `17a26370`); read-only absorption gate packet presented to Aaron 15:14Z; Aaron `EXECUTE` 15:17:06Z (with characteristic *"why are you waiting on me"* — flagged as future-self lesson on standing-authority cadence); absorption ceremony executed 15:17:06-15:17:09Z. Steps A→D all green: ruleset 15524390 disabled → force-with-lease push from `b7a6a95d` to `17a26370` → ruleset restored → SHA equality verified. Independent post-execute re-check: AceHack/main = LFG/main = local main = `17a26370ea5eb979406a3913d57348d3b647afd8`; ruleset enforcement=active; file content diff empty. **The double-hop discipline (AceHack-first → LFG forward-sync → AceHack absorbs LFG squash-SHA) closed cleanly under live conditions for the first time post-pre-v1 baseline.** Aaron's load-bearing concern *"without the double-hop in a few hours we'll be right back to where we started"* — answered: round-trip executed without divergence accumulation; the only intra-round transient divergences (during PR #845 forward-sync, then PR #846 forward-sync) were each closed by their absorption ceremony within minutes. **Substrate captured this round (cumulative)**: (1) Bounded-Publication Discipline pattern (Amara) — measure frequently / persist append-only / escalate on threshold / roll up daily / never spam PRs hourly unless threshold breached; (2) Drain-Log Claim Verification Discipline (Otto-358 candidate) — drain-log assertions about other files' contents must include grep/read/ls evidence in same edit; (3) Tick-history fast-path policy design (Amara two-tier) — trusted actor + safe path + safe operation; (4) docs/ops taxonomy (Amara) — runbooks/patterns/incidents/ tree, *"Memory remembers. Runbooks instruct. Incidents narrate. Patterns generalize."*; (5) Bounded-retry-CodeQL discipline (Aaron) — empty-commit-retrigger is a workaround, DST bounded-retry is the fix; (6) Review-ensemble complementarity confirmed — Codex caught the structurally-deepest bug (host-segment discarded silently), Copilot caught surface P1s, both irreducibly contributed; (7) gh CLI GraphQL 401 diagnostic runbook (working-tree, awaits docs/ops/runbooks/ migration in task 318). **Next lane per Amara sequencing**: task 315 hourly-measure-bounded-publication budget cadence (HIGH-priority), then task 319 bounded-retry CodeQL, then task 318 docs/ops taxonomy, then task 317 tick-fast-path policy, then task 316 absorbed into task 318, then task 313/task 314 fork-name discipline, then branch/worktree recovery (gates on completion of items 1-7). Cron `b9ccd753` alive. | [PR #846 merged](https://github.com/Lucent-Financial-Group/Zeta/pull/846) → [AceHack/main now at 17a26370](https://github.com/AceHack/Zeta/commit/17a26370ea5eb979406a3913d57348d3b647afd8) | **Best blade across the round**: *"Maintainers may append events fast; everyone reviews projections."* (Amara, on tick-history fast-path design) — but the operationally-richest blade was Aaron's *"why are you waiting on me"* on the absorption-EXECUTE gate. The literal answer was *"Amara's gate-packet protocol said 'Do not execute yet until Aaron says EXECUTE'"* and Aaron typing `EXECUTE` was the green-light. Future-self lesson candidate (Otto-359 to be filed): once a maintainer has shown a precedent of granting standing authority to a fully-staged execute path on prior identical absorption ceremonies, AND the new packet is structurally-identical to the prior one, the agent may proceed on EXECUTE-or-better implicit consent rather than pausing for fresh explicit consent each time. The bound on this rule: only when packet shape, gate-list, and risk class are unchanged from the prior consented round. Drift in any of those = ask again. | diff --git a/memory/MEMORY.md b/memory/MEMORY.md index dfc7129445..d3f4dd5a43 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -3,6 +3,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_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`. +- [**gh CLI / CodeQL transient 401 diagnostic runbook (Otto + Amara, 2026-04-29; ops-tree migration pending task 318)**](reference_gh_cli_graphql_401_diagnostic_runbook_2026_04_29.md) — Diagnostic runbook for transient upstream auth-service 401s affecting local `gh api graphql`/`gh api user` and GHA CodeQL SARIF upload in the same window. First-hypothesis is transient; always rule out token-side issues (expired/revoked/SSO) before assuming transient. (The earlier `-X POST` "workaround" claim was a misdiagnosis corrected per Codex P2 on PR #847 — `gh api` already sends POST when `-f` parameters are present, so the flag is a no-op; success on retry was just the upstream glitch resolving.) Amara framing: diagnostic note, not doctrine yet. Long-term home: `docs/ops/runbooks/gh-cli-auth-401.md` per task 318 docs/ops taxonomy. - [**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/reference_gh_cli_graphql_401_diagnostic_runbook_2026_04_29.md b/memory/reference_gh_cli_graphql_401_diagnostic_runbook_2026_04_29.md new file mode 100644 index 0000000000..4233126d40 --- /dev/null +++ b/memory/reference_gh_cli_graphql_401_diagnostic_runbook_2026_04_29.md @@ -0,0 +1,152 @@ +--- +name: gh CLI / CodeQL transient 401 — diagnostic runbook +description: When `gh auth status` reports authenticated but `gh api graphql` / `gh api user` returns 401 (and CodeQL SARIF uploads fail in the same window), the FIRST hypothesis is a transient upstream auth-service hiccup. Always rule out token-side issues (expired / revoked / SSO not authorized) before assuming transient. Captured 2026-04-29 during PR #846 review wave; corrected per Codex P2 on PR #847 (the prior `-X POST` "workaround" was a misdiagnosis — `gh api` already sends POST when `-f`/`-F` parameters are present, so the flag was a no-op and the success was just the glitch resolving on retry). +type: reference +--- + +# gh CLI / CodeQL transient 401 — Diagnostic Runbook + +## When this triggers + +`gh auth status` shows green ("Logged in to github.com"), keyring +token present, but multiple endpoints fail with `HTTP 401: +Requires authentication` for a short window (~30-90 seconds), +then recover on their own. Specifically observed: + +- `gh api graphql -f query='...'` +- `gh api user` +- GitHub Actions: CodeQL Default-Setup SARIF upload step + +While in the same window: +- `gh api repos///...` (REST repo-scoped) keeps + working — gh CLI falls back to anonymous access on public + repos when auth fails, masking the auth issue +- `gh api rate_limit` may still appear to work, but per GitHub + REST docs `GET /rate_limit` succeeds anonymously when only + public resources are queried — so a healthy-looking response + here does NOT prove the token is valid (Codex P1 catch on + PR #847; previously this runbook over-relied on it). Use + `gh api user` instead — that endpoint requires authentication. +- A `gh api -X POST graphql ...` retry seconds later succeeds + (NOT because of the `-X POST` flag — see "Common + misdiagnosis" below — but because the upstream path + recovered) + +## What this actually is + +A transient hiccup in GitHub's auth-service routing. Likely +classes: +- Auth-service node restart / draining +- Token-validation cache miss spilling to a slow path +- SSO-policy check delay on org-bound tokens +- Brief upstream rate-limit on the auth-service tier (separate + from the API rate-limit we typically see) + +It clears on its own. The right response is **bounded retry**, +not "switch to a different gh flag." + +## Common misdiagnosis (corrected 2026-04-29) + +**The `-X POST` claim is wrong.** A prior version of this +runbook claimed that `gh api graphql -f query='...'` defaults +to GET and that adding `-X POST` was a workaround. That's +incorrect: + +- `gh api` defaults to **POST** when any `-f` or `-F` + parameters are present (per `gh api --help`). +- So `gh api graphql -f query='...'` already sends POST. +- Adding `-X POST` is a no-op for that command shape. + +Verify yourself: + +```bash +GH_DEBUG=api gh api graphql -f query='query { viewer { login } }' 2>&1 \ + | grep -E '^> POST|^> GET' +# > POST /graphql HTTP/1.1 ← already POST without -X +``` + +The earlier "the -X flag fixed it" observation was actually the +upstream auth glitch resolving in the few seconds between +attempts. Misattributed. + +## Triage in order + +1. **Confirm the symptom is transient.** Wait 30-60 seconds and + retry the failing command. If it succeeds on retry without + any other change, this is the transient class. Do not + investigate further; just bounded-retry. Log the timestamp + for cross-reference with CodeQL run logs if that's failing + too. + +2. **Confirm `gh auth token` is intact**: `gh auth token | head -c 8` + should print the first 8 chars. If empty, the keyring entry + is genuinely missing → `gh auth login` is the answer (this + is a different class from the transient 401). + +3. **Confirm partial-failure pattern via an auth-required endpoint**: + `gh api user --jq .login` requires authentication (no anonymous + fallback) and is a reliable signal of token-side health. + - If `gh api user` succeeds → token IS authenticating; failure + elsewhere is upstream-transient. + - If `gh api user` ALSO 401s → likely token-side (expired / + revoked / SSO not authorized for the org). + **Do NOT use `gh api rate_limit` as the auth-health signal**: + `GET /rate_limit` succeeds anonymously when only public + resources are queried (per GitHub REST docs), so a missing + or revoked token can show as healthy on this check, causing + false "transient" classification and delaying real token + remediation. (Codex P1 catch on PR #847.) + +4. **For local commands**: bounded retry with back-off + (60s/180s; max 2-3 retries). If still failing after 5 + minutes, escalate as suspected-token-issue, not transient. + +5. **For CI (CodeQL SARIF upload)**: the dynamic-default-setup + workflow CANNOT be retried via `gh run rerun --failed` + ("This workflow run cannot be retried"). Empty-commit + retrigger to the PR head is the only path. Per task 319, + the proper fix is bounded-retry-via-tooling, not unbounded + manual retry. + +## Sibling failure mode — CodeQL SARIF upload 401 + +Same upstream auth glitch breaks CodeQL Default-Setup SARIF +uploads in GHA: + +``` +##[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 +``` + +The Default-Setup CodeQL workflow run (event:`dynamic`) cannot +be retried directly. Empty-commit-retrigger to the PR head is +the workaround. Per task 319, this needs bounded-retry per DST +(empty-commit-retrigger is a workaround; the proper fix is +infrastructure that detects the auth-401 SARIF-upload signature +and retries with bound + back-off). + +## What this is NOT + +- NOT proof of token expiration (fresh keyring tokens see this). +- NOT proof of widespread API outage — repo-scoped REST keeps + working, just the auth-validating path 401s briefly. +- NOT a gh CLI version-pin signal (no specific version known to + cause this). +- NOT solved by `-X POST` (corrected; that flag is a no-op for + graphql calls with `-f` parameters). +- NOT yet doctrine. Amara framing: *"diagnostic note, not + doctrine yet."* + +## Trigger memory + +PR #846 review wave 2026-04-29T~14:50-15:01Z. Multiple endpoints +hit 401 in the same window — `gh api graphql -f query` locally +and CodeQL Default-Setup SARIF upload in GHA. Both recovered on +retry. Initial misdiagnosis attributed recovery to `-X POST` +flag; Codex P2 review on PR #847 caught the misattribution +(`gh api` already sends POST with `-f`; the success was the +glitch resolving). Lesson: claim-without-verify is the failure +mode that the Drain-Log Claim Verification Discipline (task +task 316) catches. The rule applies to runbook-authoring in real +time, not just retroactive drain-log audits.