Skip to content

perf(security-issue-sync): load stage-specific rules only when they apply - #1997

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:perf/issue-sync-prose-to-code
Nov 5, 2026
Merged

potiuk merged 1 commit into
apache:mainfrom
potiuk:perf/issue-sync-prose-to-code

Conversation

@potiuk

@potiuk potiuk commented Nov 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Moves the stage-specific Step 2b bullets of security-issue-sync out of signals-to-actions.md into siblings, behind pointers that name their triggers, and trims the Step 5b prose that push-decision already decides.
  • Fixes two gaps found by comparing that prose with the code, so the cut does not change behaviour.
  • Adds a pointer-routing eval step for the new pointers.
Run type Tokens saved (estimate, characters ÷ 4)
Routine sync ~5.3k
Closed announced tracker ~4.1k
Run with a hand-off transition ~2k

Moved byte for byte:

  • release-manager-comments.md: the fill-fields, release-manager hand-off and publication-ready comments.
  • post-advisory-records.md: the advisory-records update and the security-pages reminder.

Code fixes:

  • Failed state fetch. After a push, a fetch that failed or returned unknown fell through to "fire the fill-fields comment". The skill says to post nothing on the hand-off front and retry on the next sync; push-decision now does that, with a recap blocker.
  • Version noise in titles. Wrong label in the UI in Apache Foo 2.1.0 and Wrong label in the UI (Foo 2.1.0) passed the title gate, although the gate promises no version-noise suffix.

Type of change

  • Skill change (.claude/skills/<name>/) — eval fixtures updated below
  • Python package (tools/*/ with pyproject.toml)

Test plan

  • prek run --all-files --skip workspace-pytest passes, including lychee
  • workspace-pytest passes for the changed files
  • 4 new test cases failed before the fixes and pass now
  • Validator exits 0; no surface_hash changed
  • security-issue-sync evals: 45/45 before, 53/53 after, no original case regressed
  • New pointer-routing step: 8/8 on the real skill; with both pointers deleted, all 6 cases that need a file fail and the 2 that need none pass

The output spec names no file, so the agent has to get each name from the skill text.
case-5 covers an existing marker comment with no label transition, the easiest trigger to miss.

RFC-AI-0004 compliance

  • Vendor neutrality — placeholders kept; the check-placeholders hook passes

No new mutation, host access, outbound message or LLM routing.

Linked issues

None.

Notes for reviewers

  • security-cve-allocate changes too. The version-noise fix is in the shared strip(), so that skill now removes these suffixes as well. This matches its own rule (no redundant version suffix), but it is a behaviour change in a second skill.
  • The Step 5b trim is the least tested part. Nothing checks that an agent acts on push-decision's reason the way it followed the deleted prose, and those strings are terser, for example the expired-session reminder.
  • The verify step still only runs for allocated records. The removed prose said "when the pushed JSON carried review-ready", under the heading of the allocated → review-ready gate. The code's narrower reading is unchanged.
  • Less than the earlier 8–10k estimate. The four judged gates and the push mechanics must stay, the comment bodies are already template files, and the Step 5d sweep needs adopter configuration and judgement, so no render or apply-plan commands were added.
  • pointer-routing records a stated decision. The agent says which files it would open; it does not run with file tools.
  • Evals predate the rebase. They ran before rebasing over generate-cve-json: warn when a credit line joins several names by comma #1741, which touches none of these files; prek and workspace-pytest ran after it.
  • Single model. No cross-model pass and no adversarial review were run.
  • tools/spec-loop/.last-sync is not bumped. The lifecycle spec is updated by hand here.

🤖 Generated with Claude Code

…pply

Most Step 2b bullets about release-manager comments and post-advisory
records apply at one lifecycle stage, yet every sync loaded them. Move
them byte-for-byte to sibling files, behind pointers that name their
triggers, and trim the Step 5b prose that push-decision already decides.
A routine sync reads about 5.3k fewer tokens.

Comparing that prose with the code found two gaps, fixed here so the cut
changes nothing:

- a state fetch that fails after the push fired the fill-fields comment;
  it now posts nothing about the hand-off and retries on the next sync
- version noise such as "in Apache Foo 2.1.0" passed the title gate; the
  shared strip cascade now removes it, for security-cve-allocate as well

Add a pointer-routing eval step that shows the agent the lookup without
the sibling text, so a pointer that stops working fails a case.

Generated-by: Claude Opus 5
@potiuk potiuk added the family:security security-* skills label Nov 5, 2026
@github-actions github-actions Bot added family:tools tools/* family:docs Docs, MISSION.md, READMEs capability:intake Import external signal + sync tracker state substrate:analytics Tool substrate: read-only metrics / dashboards / renderers substrate:framework-dev Tool substrate: build / validate / eval the framework itself family:dev Repo dev: .asf.yaml, spec-loop specs, Node manifests, .claude/settings.json labels Nov 5, 2026
@potiuk
potiuk enabled auto-merge (squash) November 5, 2026 00:33
@potiuk
potiuk disabled auto-merge November 5, 2026 00:39
@potiuk
potiuk merged commit 9130233 into apache:main Nov 5, 2026
12 checks passed
potiuk added a commit that referenced this pull request Nov 5, 2026
…1997 (#2004)

* fix(security-issue-sync): read the hand-off rules when a gate blocks the label

The pointer to release-manager-comments.md fired only when a pass proposed
a transition. With a shipped release and a record still DRAFT the label
cannot flip, so with no marker comment the agent never read the
fill-fields rule. Trigger on the tracker's state instead: any open tracker
labelled `pr merged` or `fix released`.

Also strip a version suffix after a short project name in a title, such
as "in Foo 2.1.0", which the earlier fix missed. A bare short name stays,
since it may be a real word in the title.

Generated-by: Claude Opus 5

* fix(adversarial-review): review a PR's head, not an empty directory

The pre-PR block and security-issue-import-from-pr told agents to pass an
empty temporary directory as --repo-dir for a PR with no local checkout.
Reviewers there can read only the diff, so no findings is not a clean
review. Give an export recipe that uses a throwaway repository, because
that skill runs in the private tracker checkout, and warn in the report
when --repo-dir is empty.

Generated-by: Claude Opus 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capability:intake Import external signal + sync tracker state family:dev Repo dev: .asf.yaml, spec-loop specs, Node manifests, .claude/settings.json family:docs Docs, MISSION.md, READMEs family:security security-* skills family:tools tools/* substrate:analytics Tool substrate: read-only metrics / dashboards / renderers substrate:framework-dev Tool substrate: build / validate / eval the framework itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant