From 9cde15d4bafa4a44f60cf4f97292fdfc44dede75 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Jul 2026 07:39:49 +0000 Subject: [PATCH 1/3] chore: claim #2206 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > 🤖 Generated by the Daily AI Engineer (Cursor cloud instance) Co-authored-by: Nikolai Emil Damm From 2ae87d6317417e2df3c61625913ea3ea4f2c96b6 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Jul 2026 07:41:53 +0000 Subject: [PATCH 2/3] fix(ai-engineer): distinguish REST 5xx from invalid gh credentials Preflight was treating GitHub REST/service failures as a bad saved login. Add a GraphQL viewer.login fallback and classify 5xx separately from 401/403. Fixes #2206 Co-authored-by: Nikolai Emil Damm --- .claude/scripts/maintainer-preflight.test.sh | 21 +++++++++++++++- .claude/skills/portfolio-maintenance/SKILL.md | 24 ++++++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.claude/scripts/maintainer-preflight.test.sh b/.claude/scripts/maintainer-preflight.test.sh index 5db3213c..4b3f4cba 100755 --- a/.claude/scripts/maintainer-preflight.test.sh +++ b/.claude/scripts/maintainer-preflight.test.sh @@ -38,9 +38,28 @@ grep -Fq 'classify the saved login as indeterminate' "${run_loop}" || grep -Fq 'authentication verification unavailable' "${run_loop}" || fail "missing the unavailable host-verification classification" -grep -Fq 'Only an explicit credential rejection from that host-level check proves the saved login invalid.' "${run_loop}" || +grep -Fq 'Only an explicit credential rejection' "${run_loop}" || fail "missing the host-confirmed invalid classification" +grep -Fq 'GitHub service degraded' "${run_loop}" || + fail "missing the REST 5xx / service-degraded classification" + +grep -Fq "gh api graphql -f query='{viewer{login}}'" "${run_loop}" || + fail "missing the authenticated GraphQL viewer.login fallback" + +grep -Fq 'HTTP 401/403' "${run_loop}" || + fail "missing the explicit 401/403 authentication-rejection criterion" + +grep -Fq 'A REST 5xx with a successful GraphQL' "${run_loop}" || + fail "missing the REST-503-plus-GraphQL-success regression rule" + +grep -Fq 'recommend' "${run_loop}" && grep -Fq 'gh auth login' "${run_loop}" || + fail "missing the gh-auth-login-only-on-confirmed-rejection handoff rule" + +# The handoff must be gated on confirmed rejection — not on every auth-status failure. +grep -Fq 'and **only then** recommend' "${run_loop}" || + fail "missing the confirmed-rejection gate before recommending gh auth login" + grep -Fq 'record only these gate classifications in durable memory' "${run_loop}" || fail "missing the credential-safe memory rule" diff --git a/.claude/skills/portfolio-maintenance/SKILL.md b/.claude/skills/portfolio-maintenance/SKILL.md index ffe06e49..39eed2be 100644 --- a/.claude/skills/portfolio-maintenance/SKILL.md +++ b/.claude/skills/portfolio-maintenance/SKILL.md @@ -57,14 +57,22 @@ card. If only the host-level saved-login check succeeds, run every subsequent `gh` command through that approved host-level execution path. Clearing the injected tokens does not make a sandboxed macOS Keychain readable. - Only an explicit credential rejection from that host-level check proves the saved login invalid. - If the host-level check instead authenticates a different account, hard-block as `wrong GitHub identity` - without describing the credential as invalid. - If the host-level check cannot run or fails - for a transport reason, hard-block as `authentication verification unavailable` instead of instructing - the maintainer to replace a credential that was never tested. Keep the injected-token result, saved-login - result, and `git fetch` result as separate gates, because repository reachability cannot prove GitHub API - identity (and vice versa); record only these gate classifications in durable memory, never credential output. + **Distinguish authentication rejection from GitHub service degradation** (monorepo#2206): a REST + `/user` (or `gh auth status`) probe that returns HTTP 5xx, HTML, or other non-JSON service noise is + **not** proof the credential is bad — classify that outcome as `GitHub service degraded` and run a + bounded authenticated GraphQL fallback + `env -u GH_TOKEN -u GITHUB_TOKEN gh api graphql -f query='{viewer{login}}'` (same cleared-env / + host-level path as the REST probe). Accept the identity when GraphQL returns `devantler`. + Only an explicit credential rejection from that host-level check proves the saved login invalid — + meaning HTTP 401/403, or `gh` reporting the token rejected / not logged in — and **only then** recommend + `gh auth login`. A REST 5xx with a successful GraphQL `viewer.login` must never be + reported as an invalid saved login. If the host-level check instead authenticates a different + account, hard-block as `wrong GitHub identity` without describing the credential as invalid. + If the host-level check cannot run or fails for a transport reason (and the GraphQL fallback is + likewise unreachable), hard-block as `authentication verification unavailable` instead of + instructing the maintainer to replace a credential that was never tested. Keep the injected-token + result, saved-login result, and `git fetch` result as separate gates, because repository + reachability cannot prove GitHub API identity (and vice versa); record only these gate classifications in durable memory, never credential output. 3. **Check the boot memory surface fits in one read — BEFORE you read it.** A boot-loaded file past the Read cap is **truncated silently**: the run continues on a partial cursor with no signal that carry-forwards, stand-down notes, or `HANDS-OFF` records beyond the cut are missing (the 2026-06-05 blinding; From bd409765c492ceb64b00ee709c812884bc40b481 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 28 Jul 2026 15:50:16 +0000 Subject: [PATCH 3/3] fix(ai-engineer): treat rate-limit 403 as service degradation Pin the GraphQL auth fallback to github.com, keep the failing probe's credential context, and stop classifying rate-limited 403/429 as a bad login. Updates the preflight contract test accordingly. Co-authored-by: ned --- .claude/scripts/maintainer-preflight.test.sh | 19 +++++++++---- .claude/skills/portfolio-maintenance/SKILL.md | 27 ++++++++++++------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/.claude/scripts/maintainer-preflight.test.sh b/.claude/scripts/maintainer-preflight.test.sh index 4b3f4cba..7ca42fbe 100755 --- a/.claude/scripts/maintainer-preflight.test.sh +++ b/.claude/scripts/maintainer-preflight.test.sh @@ -44,13 +44,22 @@ grep -Fq 'Only an explicit credential rejection' "${run_loop}" || grep -Fq 'GitHub service degraded' "${run_loop}" || fail "missing the REST 5xx / service-degraded classification" -grep -Fq "gh api graphql -f query='{viewer{login}}'" "${run_loop}" || - fail "missing the authenticated GraphQL viewer.login fallback" +grep -Fq "gh api graphql --hostname github.com -f query='{viewer{login}}'" "${run_loop}" || + fail "missing the authenticated GraphQL viewer.login fallback pinned to github.com" -grep -Fq 'HTTP 401/403' "${run_loop}" || - fail "missing the explicit 401/403 authentication-rejection criterion" +grep -Fq 'rate-limited 403/429' "${run_loop}" || + fail "missing the rate-limit-as-service-degradation classification" -grep -Fq 'A REST 5xx with a successful GraphQL' "${run_loop}" || +grep -Fq 'same host and credential context' "${run_loop}" || + fail "GraphQL fallback does not preserve the failing probe's credential context" + +grep -Fq 'HTTP **401**' "${run_loop}" || + fail "missing the explicit HTTP 401 authentication-rejection criterion" + +grep -Fq 'non-rate-limit' "${run_loop}" || + fail "missing the non-rate-limit 403 credential-rejection criterion" + +grep -Fq 'A REST 5xx (or' "${run_loop}" || fail "missing the REST-503-plus-GraphQL-success regression rule" grep -Fq 'recommend' "${run_loop}" && grep -Fq 'gh auth login' "${run_loop}" || diff --git a/.claude/skills/portfolio-maintenance/SKILL.md b/.claude/skills/portfolio-maintenance/SKILL.md index 39eed2be..fac789be 100644 --- a/.claude/skills/portfolio-maintenance/SKILL.md +++ b/.claude/skills/portfolio-maintenance/SKILL.md @@ -58,16 +58,23 @@ card. approved host-level execution path. Clearing the injected tokens does not make a sandboxed macOS Keychain readable. **Distinguish authentication rejection from GitHub service degradation** (monorepo#2206): a REST - `/user` (or `gh auth status`) probe that returns HTTP 5xx, HTML, or other non-JSON service noise is - **not** proof the credential is bad — classify that outcome as `GitHub service degraded` and run a - bounded authenticated GraphQL fallback - `env -u GH_TOKEN -u GITHUB_TOKEN gh api graphql -f query='{viewer{login}}'` (same cleared-env / - host-level path as the REST probe). Accept the identity when GraphQL returns `devantler`. - Only an explicit credential rejection from that host-level check proves the saved login invalid — - meaning HTTP 401/403, or `gh` reporting the token rejected / not logged in — and **only then** recommend - `gh auth login`. A REST 5xx with a successful GraphQL `viewer.login` must never be - reported as an invalid saved login. If the host-level check instead authenticates a different - account, hard-block as `wrong GitHub identity` without describing the credential as invalid. + `/user` (or `gh auth status`) probe that returns HTTP 5xx, HTML, other non-JSON service noise, **or + a rate-limited 403/429** (GitHub may return either status when the limit is exceeded — check + `x-ratelimit-*` headers or a rate-limit message body) is **not** proof the credential is bad — + classify that outcome as `GitHub service degraded` and run a bounded authenticated GraphQL + fallback against the **same host and credential context** as the failing probe: + `gh api graphql --hostname github.com -f query='{viewer{login}}'`. Prefix with + `env -u GH_TOKEN -u GITHUB_TOKEN` **only when the failing probe itself was the cleared-env + saved-login check**; otherwise keep the injected `GH_TOKEN`/`GITHUB_TOKEN` so a transient REST + failure cannot be misread as a bad keychain login. Always pass `--hostname github.com` so + `GH_HOST` cannot redirect the fallback to an unrelated enterprise host. Accept the identity when + GraphQL returns `devantler`. + Only an explicit credential rejection proves the login invalid — meaning HTTP **401**, a **non-rate-limit** + 403 that is clearly a credential/permission rejection (never a rate-limit 403), or `gh` reporting + the token rejected / not logged in — and **only then** recommend `gh auth login`. A REST 5xx (or + rate-limit) with a successful GraphQL `viewer.login` must never be reported as an invalid saved + login. If the host-level check instead authenticates a different account, hard-block as + `wrong GitHub identity` without describing the credential as invalid. If the host-level check cannot run or fails for a transport reason (and the GraphQL fallback is likewise unreachable), hard-block as `authentication verification unavailable` instead of instructing the maintainer to replace a credential that was never tested. Keep the injected-token