Skip to content

perf(security-cve-allocate): decide and render the allocation rules as code - #1705

Merged
potiuk merged 3 commits into
mainfrom
perf/security-3-cve-allocate
Oct 19, 2026
Merged

potiuk merged 3 commits into
mainfrom
perf/security-3-cve-allocate

Conversation

@potiuk

@potiuk potiuk commented Oct 19, 2026

Copy link
Copy Markdown
Member

Layer 3 of the security-family deep split (#1672), after #1680 (import) and #1686 (triage and invalidate): security-cve-allocate's rule-shaped steps move into a cve-allocate family of tools/security-management.

What moves to code

security-management cve-allocate <command> --input <file> prints JSON and runs nothing; tracker text reaches it only in files the agent wrote.

Step Command Decides / renders
Inputs selector the tracker and an optional CVE-YYYY-NNNNN override; a malformed or second CVE token is refused
0 item 5 preflight the vulnogram-api-check exits as the Step 3 path, the next check, or the setup to offer
1 blockers closed, CVE already in the field or cve allocated, duplicate, not exactly one scope label, undecided field; needs triage warns only when nothing blocks
2 title the strip cascade, from the project's names and tracker prefixes; over-strip warning under 3 words
3 recipe, allocate-result, cve the API proposal (title shell-quoted), self-service recipe or terse relay; what an allocation exit means next (never re-run on its own); the one CVE ID in the paste-back
4 draft-plan, check-draft, proposal, render-rollup whether the reporter gets a status draft and how; the draft's leak check; items 1–5; the rollup entry
5 parse-reply, apply-plan the confirmation forms (nothing applies by default); the per-backend apply order
7 render-recap the recap with every link

The model keeps writing the reporter draft; the user keeps the allocation. The draft-backend choice and leak scan move unchanged from issue_invalidate to shared.drafting, so both skills use one copy.

SKILL.md becomes a router (7,679 → 7,324 tokens). Every heading and golden-rule headline is unchanged, and the blocker list moved to outcomes/blockers.md. The step-1, 2, 3, 4, 5 and 7 model suites are now pytest cases named after each former case (tests/test_cve_allocate.py). A new step-4-draft-body model suite covers the reporter draft, the one step the model still owns, and passes 3/3 on a self-eval.

Behaviour changes

  • The reporter status draft names the bare CVE ID, never the CVE-tool record URL, which a reporter cannot open (editorial guidelines). The skill and the canned-response template said the opposite; both are fixed.
  • A malformed or second CVE token, in the invocation or the paste-back, is refused, never repaired.
  • Two scope labels, or a CVE tool link field github-body-field will not decide on, block instead of being guessed.
  • A re-run whose override is already wired into the field (a partial apply) is a resume, not an "already allocated" blocker.
  • A draft ID is claimed pending in the rollup only after checking Drafts.
  • An allocation is never re-run automatically; after an expired token it needs a fresh yes.
  • A free-form reply applies nothing: it is an edit, and the proposal is confirmed again.

Spec security-issue-lifecycle describes the new family.

Part of #1672

Generative AI disclosure

Drafted with Claude Code (Claude Opus 5) and reviewed by the author.

🤖 Generated with Claude Code

…s code

A new cve-allocate family in tools/security-management takes the rules of
security-cve-allocate that are pure functions of tracker state: the
selector and its CVE override, the Step 1 blockers, the Step 2 title
cascade, the Step 0 API pre-flight and the allocation exits, the Step 3
API proposal, recipe and relay, the paste-back CVE ID, the reporter draft
plan and its leak check, the Step 4 numbered proposal and rollup entry,
the Step 5 reply grammar and per-backend apply order, and the Step 7
recap. Writing the reporter draft stays with the model, and allocating
the CVE with the user.

The draft backend choice and the leak scan move from issue_invalidate to
shared.drafting, unchanged, so both skills use one copy.

SKILL.md becomes a router (7,679 -> 7,324 tokens); every heading and
golden-rule headline is unchanged, and the blocker list moved to
outcomes/blockers.md. The title cascade leaves the inline Python recipe
for `cve-allocate title`, which takes the project's names and tracker
prefixes from title-normalization.md. The step-1, 2, 3, 4, 5 and 7
suites become pytest cases named after each former case; a new
step-4-draft-body model suite covers the one step the model still owns.

Behaviour changes:
- The reporter status draft names the bare CVE ID and never the CVE-tool
  record URL, which a reporter cannot open (editorial guidelines); the
  canned-response template said the opposite and is fixed.
- A malformed or second CVE token in the invocation or the paste-back is
  refused, never repaired.
- Two scope labels, or a CVE tool link field github-body-field will not
  decide on, block instead of being guessed.
- A re-run with the CVE already wired into the field (a partial apply) is
  a resume, not an "already allocated" blocker.
- A draft id is claimed pending in the rollup only after checking Drafts.
- An allocation is never re-run automatically; after an expired token it
  needs a fresh yes.
- A free-form reply applies nothing: it is an edit, and the proposal is
  confirmed again.

Part of #1672

Generated-by: Claude Opus 5
@github-actions github-actions Bot added family:security security-* skills family:setup setup-* skills family:tools tools/* family:docs Docs, MISSION.md, READMEs capability:resolve Close-out: invalidate, dedupe, CVE allocate, announcement substrate:analytics Tool substrate: read-only metrics / dashboards / renderers substrate:framework-dev Tool substrate: build / validate / eval the framework itself labels Oct 19, 2026
Comment thread tools/security-management/tests/test_cve_allocate.py Fixed
- The item-list pattern of the confirmation grammar allowed whitespace
  on both sides of a whitespace separator, so a reply of many spaced
  zeros backtracked exponentially (py/redos). The separators are now a
  comma, `and`, or whitespace alone, which cannot overlap.
- A recap test asserted on `dict.pop` (py/side-effect-in-assert); it
  reads the key instead.

Generated-by: Claude Opus 5
…#1707)

A new issue-deduplicate family in tools/security-management takes the
rules of security-issue-deduplicate that are pure functions of tracker
state: the selector (the kept side first, never guessed), the Step 1
checks and CVE rules, the Step 2 field reads and conflicts, the Step 3
merged body, both Step 4 rollup entries, the Step 5 proposal, reply
grammar and per-backend apply order, and the Step 6 recap. Judging the
shared root cause, the headline and analysis, and a merged summary or
widened version range stay with the model.

The merged body is the kept body rewritten field by field through
github-body-field's replace_field, which refuses any rewrite that would
change another field, so the CVE JSON attachment, a project's extra
fields and every unchanged value stay byte-exact.

The numbered-proposal reply grammar moves from cve_allocate to
shared.numbered and the Reporter-notification line to
shared.rollup.notification_line, so both skills use one copy.

SKILL.md becomes a router (6,312 -> 6,029 tokens); every heading and
golden-rule headline is unchanged. The step-1 to step-6 suites become
pytest cases named after each former case; a new step-3-merge-inputs
model suite covers what the model still writes.

Behaviour changes:
- Reporter-supplied CVSS vectors, scores and severity labels are removed
  from the appended report mechanically, and listed for the user.
- A dropped report cannot add, end or hide a field: field-ending and
  machine-marker lines are escaped, an unmatched </details> is defused,
  and a body github-body-field will not decide on is refused.
- A CVE only on the dropped side, a dropped CVE further along than the
  kept one, or a tracker without exactly one scope label blocks the merge.
- Both summaries or both version ranges differing needs the model's
  merged value; the merge is refused without it.
- The apply plan is refused while a blocker (a CWE conflict) is open.
- A list with a comment ("1,2,3,4 — skip 5 and 6 for now") applies the
  list only when the comment names other items to hold them back.

Part of #1672

Generated-by: Claude Opus 5
@potiuk
potiuk merged commit cb6bb8b into main Oct 19, 2026
11 checks passed
@potiuk
potiuk deleted the perf/security-3-cve-allocate branch October 19, 2026 11:35
potiuk added a commit that referenced this pull request Oct 19, 2026
Hand-sync of tools/spec-loop/specs/ with the functionality that landed
between ccb53a3 and 03c15a6.

Specs changed:
- security-issue-lifecycle: the tools/security-management shared library
  gains drafting, recipients and numbered; the package reuses
  github-body-field, generate-cve-json and magpie-vcs (the embargo
  scrub); every skill of the family now has its CLI family, completing
  the deep split (#1672); the Validation block runs its pytest suite.
- .last-sync bumped to 03c15a6.

No spec change needed (specs already updated in the commit itself):
03c15a6 (#1712), c819c90 (#1711), dacf00a (#1710),
cb6bb8b (#1705).

Exempt: aee01bf (the previous sync), 0bd021f (npm pin bump in prek
hooks).

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:resolve Close-out: invalidate, dedupe, CVE allocate, announcement family:docs Docs, MISSION.md, READMEs family:security security-* skills family:setup setup-* 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.

2 participants