Skip to content

Sync claude/fix-all-issues-cSPLB with main#7

Merged
fvegiard merged 170 commits into
claude/fix-all-issues-cSPLBfrom
main
May 28, 2026
Merged

Sync claude/fix-all-issues-cSPLB with main#7
fvegiard merged 170 commits into
claude/fix-all-issues-cSPLBfrom
main

Conversation

@fvegiard
Copy link
Copy Markdown
Owner

No description provided.

actions-user and others added 30 commits February 5, 2026 17:47
…ew-comment-update

fix: Do not comment if --comment is not present
Introduce a simple, mechanical daily sweep that closes issues with
lifecycle labels past their timeout:

- needs-repro: 7 days
- needs-info: 7 days
- needs-votes: 30 days
- stale: 30 days

The sweep checks when the label was last applied via the events API,
and closes the issue if the timeout has elapsed. No AI, no comment
checking — if the label is still there past its timeout, close it.
Removing a label (by a triager, slash command, or future AI retriage)
is what prevents closure.

Each close message directs the reporter to open a new issue rather
than engaging with the closed one.

The script supports --dry-run for local testing:
  GITHUB_TOKEN=$(gh auth token) \
  GITHUB_REPOSITORY_OWNER=anthropics \
  GITHUB_REPOSITORY_NAME=claude-code \
  bun run scripts/sweep.ts --dry-run

## Test plan

Ran --dry-run against anthropics/claude-code. Correctly identified 3
issues past their timeouts (1 needs-repro at 12d, 2 needs-info at
14d and 26d). No false positives.
…lifecycle-labels

Add daily sweep to enforce issue lifecycle label timeouts
…pics#25352)

* Unify issue lifecycle labeling and sweep into a single system

Consolidate issue triage, stale detection, and lifecycle enforcement into
two components: a Claude-powered triage workflow and a unified sweep script.

Triage workflow changes:
- Add issue_comment trigger so Claude can re-evaluate lifecycle labels when
  someone responds to a needs-repro/needs-info issue
- Add concurrency group per issue with cancel-in-progress to avoid pile-up
- Filter out bot comments to prevent sweep/dedupe triggering re-triage
- Hardcode allowed label whitelist to prevent label sprawl (was discovering
  labels via gh label list, leading to junk variants like 'needs repro' vs
  'needs-repro')
- Replace MCP GitHub server with gh CLI — simpler, no Docker dependency,
  chaining is caught by the action so permissions are equivalent
- Add lifecycle labels (needs-repro, needs-info) for bugs missing info
- Add invalid label for off-topic issues (Claude API, billing, etc.)
- Add anti-patterns to prevent false positives (don't require specific
  format, model behavior issues don't need traditional repro, etc.)

Sweep script changes:
- Absorb stale issue detection (was separate stale-issue-manager workflow)
- Mark issues as stale after 14 days of inactivity
- Skip assigned issues (team is working on it internally)
- Skip enhancements with 10+ thumbs up (community wants it)
- Add invalid label with 3-day timeout
- Add autoclose label support to drain 200+ legacy issues
- Drop needs-votes (stale handles inactive enhancements)
- Unify close messages into a single template with per-label reasons
- Run 2x daily instead of once

Delete stale-issue-manager.yml — its logic is now in sweep.ts.

## Test plan

Dry-run sweep locally:
GITHUB_TOKEN=$(gh auth token) GITHUB_REPOSITORY_OWNER=anthropics   GITHUB_REPOSITORY_NAME=claude-code bun run scripts/sweep.ts --dry-run

Triage workflow will be tested by opening a test issue after merge.

* Update .github/workflows/claude-issue-triage.yml

Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>

---------

Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
The sweep job (https://github.com/anthropics/claude-code/actions/runs/21983111029/job/63510453226)
was silently failing when closeExpired tried to comment on a locked issue,
causing a 403 from the GitHub API.

Two issues:

1. closeExpired didn't skip locked issues like markStale already does.
   Adding the same `if (issue.locked) continue` guard fixes this.

2. The error was swallowed by `main().catch(console.error)` which logs
   to stderr but exits 0, so CI reported success despite the crash.
   Replaced the main() wrapper with top-level await so unhandled errors
   properly crash the process with a non-zero exit code.

## Test plan

YOLO
actions-user and others added 25 commits May 9, 2026 06:33
…hropics#61584)

Replace the static ANTHROPIC_API_KEY secret with Workload Identity
Federation inputs in claude.yml, claude-issue-triage.yml, and
claude-dedupe-issues.yml. The federation rule, organization, service
account, and workspace IDs are read from repository variables.
Copilot AI review requested due to automatic review settings May 28, 2026 00:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR syncs the branch with main by updating repository security/reporting docs, adding/adjusting GitHub automation for issue lifecycle management, and landing a major security-guidance plugin v2 update (hooks + supporting Python modules). It also adds MDM deployment templates and updates several workflows to authenticate to Anthropic via Workload Identity Federation (OIDC) instead of a static API key.

Changes:

  • Replace stale-issue GitHub Script automation with Bun-based lifecycle tools (scripts/sweep.ts, scripts/lifecycle-comment.ts) and new workflows.
  • Introduce security-guidance plugin v2 (pattern warnings + Stop-hook LLM diff review + agentic commit review) with new hook plumbing and utilities.
  • Add MDM deployment examples (macOS + Windows) and update security/reporting documentation and workflow auth configuration.

Reviewed changes

Copilot reviewed 43 out of 46 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
SECURITY.md Updates HackerOne submission URL and renames disclosure section.
scripts/sweep.ts Adds Bun script to mark issues stale and auto-close lifecycle-labeled issues.
scripts/lifecycle-comment.ts Adds Bun script to post a warning comment when lifecycle labels are applied.
scripts/issue-lifecycle.ts Defines lifecycle labels, timeouts, nudges, and upvote threshold.
scripts/gh.sh Adds a restricted gh wrapper to constrain allowed subcommands/flags.
scripts/edit-issue-labels.sh Adds workflow-bound label editor (issue number from event payload).
scripts/comment-on-duplicates.sh Changes duplicate-commenting to bind base issue to the triggering event payload.
plugins/security-guidance/README.md Documents the security-guidance plugin layers, configuration, and data handling.
plugins/security-guidance/hooks/sg-python.sh Adds Python interpreter shim (esp. for Windows Git Bash python3 stub).
plugins/security-guidance/hooks/session_state.py Adds per-session state file management with optional file locking and GC.
plugins/security-guidance/hooks/review_api.py Adds importable public API for agentic review prompt building/filtering/formatting.
plugins/security-guidance/hooks/patterns.py Defines built-in security patterns and stable numeric RuleId mapping.
plugins/security-guidance/hooks/hooks.json Updates hook wiring to include SessionStart bootstrap and async Stop/commit/push reviews.
plugins/security-guidance/hooks/gitutil.py Adds git/diff helpers and diff parsing/source classification logic.
plugins/security-guidance/hooks/extensibility.py Adds project/user/local guidance + custom pattern rule loading/validation.
plugins/security-guidance/hooks/ensure_agent_sdk.py Adds SessionStart bootstrap to ensure the agent SDK is available via a persisted venv.
plugins/security-guidance/hooks/diffstate.py Adds git-derived diff/review state helpers and reviewed-SHA tracking.
plugins/security-guidance/hooks/_base.py Adds shared helpers (debug logging, plugin version, token/cost usage metrics).
plugins/security-guidance/.claude-plugin/plugin.json Bumps plugin version to 2.0.0 and updates metadata/homepage.
plugins/code-review/commands/code-review.md Updates code-review command instructions (terminal summary + conditional commenting).
feed.xml Adds Atom feed for CHANGELOG release entries.
examples/settings/README.md Fixes grammar and adds a pointer to MDM templates.
examples/mdm/windows/Set-ClaudeCodePolicy.ps1 Adds Intune script example to deploy managed-settings.json on Windows.
examples/mdm/windows/en-US/ClaudeCode.adml Adds Group Policy resource strings for Claude Code managed settings.
examples/mdm/windows/ClaudeCode.admx Adds Group Policy definition for managed settings JSON registry value.
examples/mdm/README.md Adds README for MDM templates across platforms.
examples/mdm/managed-settings.json Adds minimal managed-settings.json template.
examples/mdm/macos/com.anthropic.claudecode.plist Adds Jamf/Kandji custom settings plist template.
examples/mdm/macos/com.anthropic.claudecode.mobileconfig Adds macOS configuration profile template for managed settings.
.github/workflows/sweep.yml Adds scheduled workflow to run scripts/sweep.ts.
.github/workflows/stale-issue-manager.yml Removes old GitHub Script-based stale issue manager.
.github/workflows/oncall-triage.yml Removes old oncall triage workflow.
.github/workflows/non-write-users-check.yml Adds workflow to warn when allowed_non_write_users is introduced/modified.
.github/workflows/issue-lifecycle-comment.yml Adds workflow to post lifecycle comments on issues:labeled.
.github/workflows/claude.yml Switches Claude action auth to Workload Identity Federation inputs.
.github/workflows/claude-issue-triage.yml Updates triage to run on issue open + human comments, uses slash command + WIF auth.
.github/workflows/claude-dedupe-issues.yml Switches to WIF auth and adds script caps + improved Statsig logging inputs.
.github/workflows/backfill-duplicate-comments.yml Pins Bun setup action by SHA.
.github/workflows/auto-close-duplicates.yml Pins Bun setup action by SHA.
.claude/commands/triage-issue.md Adds triage slash command instructions using restricted scripts.
.claude/commands/oncall-triage.md Removes oncall triage slash command content.
.claude/commands/dedupe.md Updates dedupe command to use the restricted scripts/gh.sh wrapper.
.claude-plugin/marketplace.json Updates marketplace schema URL.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/sweep.ts
Comment on lines +34 to +37
if (!response.ok) {
if (response.status === 404) return {} as T;
const text = await response.text();
throw new Error(`GitHub API ${response.status}: ${text}`);
Comment thread scripts/sweep.ts
Comment on lines +115 to +122
const events = await githubRequest<any[]>(`${base}/events?per_page=100`);

const labeledAt = events
.filter((e) => e.event === "labeled" && e.label?.name === label)
.map((e) => new Date(e.created_at))
.pop();

if (!labeledAt || labeledAt > cutoff) continue;
Comment thread scripts/sweep.ts
Comment on lines +127 to +133
const comments = await githubRequest<any[]>(
`${base}/comments?since=${labeledAt.toISOString()}&per_page=100`
);
const hasHumanComment = comments.some(
(c) => c.user && c.user.type !== "Bot"
);
if (hasHumanComment) {
Comment on lines +359 to +369
xy, path = e[:2], e[3:]
if xy == "??":
untracked.add(path)
else:
tracked.add(path)
# Rename/copy entries are XY old\0new\0 — second NUL field is
# the origin path; consume it so it isn't misparsed as a new
# 2-char-status entry.
if "R" in xy or "C" in xy:
i += 1
i += 1
Comment on lines +207 to +222
# ─── push-sweep reviewed-commit tracking ────────────────────────────────────
#
# Repo-local (not session-local) record of which commits the commit-review
# hook has already reviewed, so the push-sweep can advance its diff base past
# the contiguous reviewed prefix and skip entirely when everything pushed was
# already covered. Lives under `.git/` (same precedent as CC's
# `.git/claude-trailers`) so it survives across sessions and is per-clone.
#
# Format: one line per reviewed sha, append-only:
# <40-hex-sha>\t<unix-ts>\t<pv>\t<vulns_found>
#
# The trailing columns are observability only — load reads just the sha set.
# GC keeps the last _REVIEWED_SHAS_CAP entries; the file is small (~64 bytes
# per line) so even at the cap it's ~32KB.


Comment on lines +107 to +113
try:
state_dir = os.path.dirname(state_file)
if state_dir:
os.makedirs(state_dir, exist_ok=True)

with open(state_file, "w") as f:
json.dump(state, f)
Comment on lines +140 to +143
lock_fd = None
try:
lock_fd = os.open(lock_file, os.O_RDWR | os.O_CREAT)
fcntl.flock(lock_fd, fcntl.LOCK_EX)
Comment on lines 10 to +12

REPO="anthropics/claude-code"
BASE_ISSUE=""

Comment on lines +15 to +17
- `./scripts/gh.sh` — wrapper for `gh` CLI. Only supports these subcommands and flags:
- `./scripts/gh.sh label list` — fetch all available labels
- `./scripts/gh.sh label list --limit 100` — fetch with limit
@fvegiard fvegiard merged commit f86fcac into claude/fix-all-issues-cSPLB May 28, 2026
4 of 7 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4087798616

ℹ️ 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".

Comment on lines +8 to +9
permissions:
issues: write
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Grant checkout read access for the sweep

This workflow explicitly restricts GITHUB_TOKEN to only issues: write, so the later actions/checkout@v4 step has no contents: read permission to fetch the repository before running scripts/sweep.ts. Add contents: read here, as the other checkout-based workflows do, otherwise the scheduled/manual sweep can fail before enforcing lifecycle timeouts.

Useful? React with 👍 / 👎.

Comment on lines +7 to +8
permissions:
issues: write
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Grant checkout read access for lifecycle comments

This workflow also narrows GITHUB_TOKEN to only issues: write, but it checks out the repo before running scripts/lifecycle-comment.ts. Without contents: read, actions/checkout@v4 can fail before any lifecycle label comment is posted, so labels such as needs-info/stale would not notify users about the timeout.

Useful? React with 👍 / 👎.

(github.event_name == 'issue_comment' && !github.event.issue.pull_request && github.event.comment.user.type != 'Bot')
concurrency:
group: issue-triage-${{ github.event.issue.number }}
cancel-in-progress: true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid cancelling the initial category triage

When a reporter adds a human comment shortly after opening an issue, this shared concurrency group cancels the still-running issues triage run and replaces it with the issue_comment run. The comment-mode prompt explicitly says not to add or remove category labels, so the issue can be left without the required bug/enhancement/question/invalid/duplicate label from the opened flow.

Useful? React with 👍 / 👎.

Comment on lines +61 to +62
- If the issue has `needs-repro` or `needs-info` and the missing information has now been provided, remove the label:
`./scripts/edit-issue-labels.sh --remove-label "needs-repro"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the matching lifecycle label

For a needs-info issue where the user supplies the requested information, the only concrete command shown here removes needs-repro instead, leaving needs-info in place and allowing the sweep to auto-close the issue despite the requested response being provided. The example should remove the actual satisfied label, or show both cases explicitly.

Useful? React with 👍 / 👎.

Comment thread scripts/sweep.ts

const base = `/repos/${owner}/${repo}/issues/${issue.number}`;

const events = await githubRequest<any[]>(`${base}/events?per_page=100`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Paginate label events before skipping closure

For long-running issues with more than 100 issue events before a lifecycle label is applied, this fetch only reads the first events page, so the later labeled event is never seen and labeledAt remains empty. Those issues will be skipped forever by the sweep even after the timeout expires unless the events API is paginated or queried via a source that includes the relevant label event.

Useful? React with 👍 / 👎.

)
if r.returncode == 0:
full_shas.append(r.stdout.strip())
_append_reviewed_shas(repo_root, full_shas, vulns_found=len(vulns or []))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t mark failed reviews as covered

When the LLM review fails transiently (for example, the API call returns no result and analyze_code_security yields (None, [])), this still writes the commit SHA to sg-reviewed-shas. A later push sweep will treat that SHA as already reviewed and advance past it, so the commit never gets retried after the API recovers; only append the SHA after a successful review/no-finding response, not after an API failure.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.