Repository navigation
feat(actions): extract the Claude lane composite trio (PR-A1) - #274
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ositive actionlint 1.7.12 rejects the GA `concurrency.queue` key (rhysd/actionlint#654); GitHub accepts and honors it at both workflow and job level, verified by the Phase 0 probe runs recorded in docs/topics/claude-review-lanes/PLAN.md. Suppression pre-approved (PLAN.md Approval record item 3), scoped to the single syntax-check message, with a dated removal trigger. Phase 0 marked DONE with the full probe evidence block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…come, marker) Structural extraction, behavior-preserving (PR-A1 of the claude-review-lanes plan): the freshness guard, outcome reporter + infra-failure classifier, and marker-comment lifecycle that both review lanes carry as embedded steps become three shared composite actions. The classifier is rewritten from the generated bash/jq embed into classify.cjs on the github-script runtime (removes the last runner-tool dependency), with the full 23-case shell corpus ported to node --test. Nothing references the composites yet — the reusable workflows repoint in a follow-up PR once these have a mergeable SHA (self-reference pins resolve only post-merge); the four generated-embed classifier files retire in that same follow-up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 5m 30s —— View job PR Review — feat(actions): extract the Claude lane composite trio (PR-A1)
Overall AssessmentClean, behavior-preserving extraction. The three composite actions are faithful ports of the inline steps in SecurityLog hygiene contract maintained. Injection surface. The comment body in Fork guard. Moved from a step-level if (pr.head?.repo?.full_name !== `${context.repo.owner}/${context.repo.repo}`)Functionally equivalent to the original Correctness1. jq-to-Node behavioral difference on empty array — minor improvement. The inline jq: 2. 3. 4. Composite action output naming bridge. Test Coverage5. 504 HTTP status not explicitly tested on the numeric path. 6. Temp directory not cleaned up in Observations
SummaryNo blocking issues. Items 3 and 4 above are the ones most worth a second look before PR-A2 begins wiring callers — specifically: confirming the |
|
Claude finished @kyle-sexton's task in 4m 36s —— View job Security Review — PR #274
FindingsNo CRITICAL or IMPORTANT security vulnerabilities found. The design is notably careful in the places it matters most: model-authored free-text is explicitly excluded from the projection, all inputs are passed via SUGGESTION —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3438f83c7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. 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".
…nt findings Commits the 2b/2f Phase 1 verifier addenda (default-prompt lane alignment; kill-switch reopening the REVIEW.md presence-predicate window) that were written to the working tree at handoff time, and fixes the four markdownlint findings failing PR-A1 CI: two wrapped lines whose leading "+" parsed as a plus-bullet (MD004), a double blank line (MD012), and a line-initial "#237" parsed as a heading (MD018). Rewraps only; no content change outside the addenda. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 54s —— View job PR Review — feat(actions): extract the Claude lane composite trio (PR-A1)
Overall AssessmentClean, behavior-preserving extraction. The three composite actions are faithful ports of the inline steps in No blocking issues. One moderate correctness bug in the marker-comment action worth fixing before PR-A2 wires callers to it. CLAUDE.md Ground Rules
Bug — Empty marker matches all
|
|
Claude finished @kyle-sexton's task in 4m 39s —— View job Security Review — PR #274
No CRITICAL or IMPORTANT security vulnerabilities found. The trust-boundary and data-flow analysis confirms the design is correctly structured for a public-repo AI action. All inputs to the three github-script blocks flow through
|
…er-comment An empty marker input would make comment.body?.startsWith(marker) match every github-actions[bot] comment, so the lifecycle would update or delete the bot's latest unrelated comment. Validate the marker is a nonempty HTML comment before listing or mutating anything (Codex review finding on PR #274). Callers invoke this action with continue-on-error, so the fail-fast stays advisory at the lane level. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 6s —— View job PR Review — feat(actions): extract the Claude lane composite trio (PR-A1)
What's New in This SyncThe latest commit ( Fix Verification — Empty/Malformed Marker Guard
if (!/^$/.test(marker ?? "")) {
core.setFailed(
`Marker must be a nonempty HTML comment like "" (got "${marker}") — ` +
"an empty or malformed marker would match unrelated bot comments.",
);
return;
}The fix is correct and is a meaningful improvement over the minimum viable guard:
The regex validates form (must be a well-formed HTML comment with at least one character inside), not just non-emptiness. This is stronger than the minimum fix suggested in the prior review and closes a broader class of misconfiguration. The error message echoes the received value, which is useful when a caller's expression silently evaluates to an unexpected string. Placement is correct. The marker guard runs before the mode guard and before any GitHub API calls — no comment is ever listed or mutated if the marker is invalid. Consistent with the existing validation pattern.
Open Items from Prior Reviews (unchanged, all low priority)These were identified before this sync and are still accurate — none are blocking:
SummaryThe moderate bug is fixed. The fix is correct, stronger than the minimum viable guard, and consistent with the action's existing validation conventions. No regressions introduced. All CLAUDE.md pin and security requirements remain satisfied. The four low-priority items above are carry-forwards from prior reviews — none are blocking for merge or for PR-A2. |
|
Claude finished @kyle-sexton's task in 2m 31s —— View job Security Review — PR #274 (latest commit
|
…osites (PR-A2) (#276) ## Summary PR-A2 of the claude-review-lanes plan (`docs/topics/claude-review-lanes/PLAN.md`, Phase 2a): both reusable review lanes replace their embedded freshness / outcome / marker-comment steps with the composite trio merged in PR-A1 (#274), pinned at its merge SHA `b5d54bf7cb386b1f2c35426c6c5fb8d1686671bd`. Local `./` refs cannot work from a reusable workflow (they resolve against the caller's checkout), so the references are full-SHA self-reference pins with `# <short-sha> <date>` comments. - `claude-review.yml` + `claude-security-review.yml`: freshness, outcome, and both marker-comment steps become composite references; downstream gates move to the composites' kebab-case outputs (`review-failed`, `failure-class`, `review-detail`). - The four generated-embed classifier files retire (`classify-infra-failure.sh`, its `.test.sh`, `render-classify-infra-failure.cjs`, `classify-infra-failure-render.test.cjs`), with their `ci.yml` test step and `selector-conformance.yml` path triggers + test step. - Security lane keeps #266's fail-closed contract: the outcome composite records failure without failing; a new inline `Fail closed on an in-scope non-run` step owns the required-check red under the same pull_request-only carve-out. Its expanded marker body rides `body-copy` as blockquote-continuation lines (input description updated — docs-only, behavior identical at the pinned SHA). - Test suites re-pinned: superseded-guard asserts the freshness composite pin; the fail-closed suite drops executed-bash classifier cases (owned by `classify.test.cjs`'s ported corpus) and pins the new wiring shape. - PLAN.md: Phase 1 marked DONE with merged-main sanity evidence; 2a-addendum records this execution shape. Verified locally: `node --test .github/scripts/*.test.cjs` (276 pass), `node --test .github/actions/claude-lane-outcome/*.test.cjs`, actionlint on all four touched workflows, zizmor findings identical to the pre-change baseline, markdownlint clean. No linked issue. ## Related - #274 (PR-A1 — composite extraction this repoints at) - #266 (fail-closed contract preserved through the repoint) - standards#278 (Phase 1, merged) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…retry, kill-switches, copy (PR-B, 2b-2i) (#280) Phase 2 feature set of the claude-review-lanes plan (`docs/topics/claude-review-lanes/PLAN.md`), delivered as PR-B on top of the merged composite extraction (PR-A1 #274) and repoint (PR-A2 #276). ## What's in here - **2b config currency**: claude-code-action pinned at v1.0.183; `claude-sonnet-5` defaults on all three lanes; inline-comment MCP tool allowed on both review lanes; `exclude_comments_by_actor` widened to both Dependabot spellings (upstream #1514) and lifted to an input on the security lane; skip-actors self-trigger ban; org-secret posture corrected (visibility: all); code-review default prompt names its lane and defers security scope to REVIEW.md's split. - **2c cadence**: code-review lane reviews on open/ready/reopen only (draft gate + no `synchronize`, dogfooded in the self-caller); `max-reviews-per-pr` (default 5) counted via a visible status comment that doubles as the human signal — fail-open, deletion resets. Security lane keeps `synchronize` (its check certifies execution at the merge head). - **2d retry**: gated, jittered single retry on all three lanes — retries only on a parsed execution file proving zero assistant turns AND a non-auth failure class; orphan tracking-comment cleanup between attempts; step-level attempt timeouts inside documented job budgets. Replaces the #266-era unconditional retry. - **2e**: per-lane caller concurrency shapes documented (review: per-PR cancel + repo-wide `queue: max`; security: `cancel-in-progress: false`, no queue — a cancelled required check is not a skip). - **2f kill-switches**: `CLAUDE_LANES_DISABLED` + per-lane variables on all three lanes; name-stable skip; repo overrides org; README + headers record the security-lane coverage-gap window. - **2g copy**: single-pass-correct marker copy (live via explicit body-copy; composite defaults follow at the Phase 3g re-pin); lane-aware annotation noun in the outcome composite. - **2h**: e2e lane gets the mechanical set only (pin, model, kill-switch, retry) — no marker/class adoption. - **2i dependabot**: daily; claude-code-action exempt from cooldown and grouped batching. - Post-review steps swap `always()` for `!cancelled()` across all lanes — cancellation is the concurrency group's retirement mechanism. ## Verification Two fresh-context verifier passes (2b/2i/2c and 2d-2g) — all checks PASS, overall SHIP; their findings (doc drift, count-gate hardening, tracking-comment authorship, retry evidence guard) are folded in as dedicated commits. 280 script tests + 10 composite tests green; actionlint clean; zizmor identical to baseline. ## Related - Closes #150 — `synchronize` dropped for the code-review lane; the security lane deliberately keeps it (QF1: a required execution check must report on the latest head; the paths gate makes non-relevant pushes skip in seconds). - Part of the claude-review-lanes effort (#228/#237/#238 observability workstream; #266 fail-closed posture preserved). Issue sweep for the remaining mapping happens in Phase 3f per the plan. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
What
PR-A1 of the approved claude-review-lanes plan (
docs/topics/claude-review-lanes/PLAN.md, committed here) — structural, behavior-preserving:claude-lane-freshness— live superseded-head guard (github-script).claude-lane-outcome— outcome reporter with the infra-failure classifier rewritten from the generated bash/jq embed intoclassify.cjson the github-script runtime (resolves the plan's F7: no more jq/runner-tool dependency). Full 23-case shell corpus ported tonode --test(classify.test.cjs, co-located; wired into ci.yml).claude-lane-marker-comment— marker-comment lifecycle (upsert on failure / clear on success), owning the fork-PR guard; lane strings are inputs..github/actionlint.yaml— pre-approved suppression for actionlint 1.7.12's rejection of the GAconcurrency.queuekey (concurrency: Add support forqueuekey rhysd/actionlint#654), scoped to that one syntax-check message, with removal trigger. Probe evidence in PLAN.md Phase 0.The four generated-embed classifier files (
classify-infra-failure.*,render-classify-infra-failure.*) retire in PR-A2 with the embed replacement — the render tripwire still guards the live embeds until then.No linked issue (the plan's issue sweep closes #150/#158/#227/#242 at Phase 3f).
Related
docs/topics/claude-review-lanes/PLAN.md— the approved plan; this is Phase 2 PR-A1.queuekey rhysd/actionlint#654 — upstream gap behind the actionlint suppression.Verification
node --test .github/actions/claude-lane-outcome/*.test.cjs— 10/10 pass (ported corpus).node --test .github/scripts/*.test.cjs— 273 pass;bash .github/scripts/classify-infra-failure.test.shstill green (untouched here).🤖 Generated with Claude Code