Skip to content

docs(pm-dispatch): advisory_report needs the same advisory write grant as advisory_create - #29619

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-7gpiq3
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-7gpiq3

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Irene · project thread

Part of #29448

What changes

Two text drifts from the card, items 1 and 2. Item 3 (the workflow comment) is a separate Tier H PR so this diff stays out of Tier H.

  • .claude/skills/pm-dispatch/references/security-findings.md §3: the advisory_report bullet said the row is for a repository where the App has no advisory write grant. It now says advisory_report and advisory_create mint the same advisory write grant, so a repository without it refuses both, and that a report also has a per-account daily limit. The fallback stays the existing "both refused ⇒ session hand-off" bullet two lines below. Reworded in place on one line; the file stays at 56 lines (ceiling 56) and the line is 117 bytes (budget 120).
  • scripts/pm/fleet-write/execute.mjs, the header of "The four advisory rows": it pointed at ops.mjs's section by its old name, "The three rows that touch a security advisory". It now names the current "The four rows that touch a security advisory", and ops.mjs's separate "The one row that READS an advisory" for the advisory_read subsection below it. Comment only.

Why

The code mints repository-advisories: write for advisory_report exactly as for advisory_create (OPS.advisory_report.permission is repository-advisories with no grant, pinned by validate.mjs --self-test), so the old bullet sent a seat to a row that dies at the mint on the very repositories it was "kept for". The execute.mjs cross-reference named a section heading that no longer exists in ops.mjs.

Verification

  • pnpm check:pm-skill-ratchet exit 0 (security-findings.md 56/56, no line over the byte budget), pnpm check:pm-skill-id-lint exit 0, node scripts/check-skills-token-ratchet.mjs exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands derived 42 commands for this diff; all 42 exit 0 on this head, including check:pm-fleet-write-execute, check:pm-fleet-write-validate, check:pm-fleet-write-dispatch, check:scripts-symbol-anchors, check:skill-frame-sync, check-comment-mask-corpus and check:doc-formula-expressions (after building @objectstack/formula and @objectstack/lint).
  • node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD exit 0.

Clause-②: no
Metadata-protocol: none

Keep one value on each of the two lines above, each line starting with its key.
Human Minimum
item 5 says what they mean.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (not touched)
  • 2. Every name I added uses the casing for its kind. (no names added)
  • 3. No formatter ran; pnpm lint passes. (no formatter ran; pnpm lint itself was not run locally, the diff touches no linted package source)
  • 4. One issue, one branch off an up-to-date main, one pull request. (the card is split in two PRs by the seat's order, both off main, neither stacked)
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (publishes nothing: skip-changeset)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English. (the skill file's own text is Chinese, as the file already is)
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J8VVAjYkaBE16yPTYraBmt

…t as advisory_create

security-findings.md §3 said `advisory_report` was for a repository where the
App has no advisory write grant. The relay mints `repository-advisories: write`
for both rows, so on such a repository both are refused at the mint and the
fallback is the session hand-off. The bullet now says so, on one line.

execute.mjs pointed at ops.mjs's section by its old name ("The three rows");
it now names "The four rows that touch a security advisory" and the separate
read section for `advisory_read`.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAjYkaBE16yPTYraBmt
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 2, 2026
@huangyiirene huangyiirene self-assigned this Nov 2, 2026
@huangyiirene
huangyiirene self-requested a review November 2, 2026 22:03
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Nov 2, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract-review-claim: session_01J8VVAnMUWA9rufXzFaEh4J · head 1d36ecf · 2026-11-02T22:04Z

The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent (the seat session is not at that tier).

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1d36ecfa038487494fe943ff266d7383a958ae08
Local-runs: probe — on a detached worktree of the head (merge-base with origin/main dd4a21f; origin/main at 454ee1a when fetched; none of security-findings.md, execute.mjs, ops.mjs, validate.mjs or fleet-write.yml moved on main since the merge-base): node scripts/pm/check-skill-line-ratchet.mjs (exit 0; security-findings.md 56 lines against ceiling 56, no line over the 120-byte budget, the reworded line 116 bytes without its newline) and --self-test (164 cases, exit 0); node scripts/pm/check-skill-id-lint.mjs (108 files clean, exit 0); node scripts/pm/check-governed-merges.mjs --branch HEAD and --pr 29619 (exit 3, GOVERNED, Tier S, one hit .claude/** via security-findings.md, execute.mjs not on the register, 7 changed lines); node scripts/pm/fleet-write/execute.mjs --self-test (259 cases, 22 batteries, exit 0), validate.mjs --self-test (303 cases, exit 0), dispatch.mjs --self-test (315 cases, exit 0); node scripts/check-skills-token-ratchet.mjs (57 bundle files within ceilings, exit 0); node scripts/check-commit-card-trailers.mjs --range dd4a21f8..HEAD (exit 0, no model identifier); node scripts/pm/dispatch-gates.mjs --commands (its own count line: 42 commands, matching the PR body's 42; the sweep itself NOT MEASURED here, read from CI); git grep of the two stale phrases over the head tree and over origin/main. The worktree was removed after the runs and the main checkout was not touched.
Scope: .claude/skills/pm-dispatch/references/security-findings.md (the governed hit: §3 bullet 3 reworded on one line), scripts/pm/fleet-write/execute.mjs (one header comment, three lines) + read, not reviewed: scripts/pm/fleet-write/ops.mjs (the two section headings the comment names, the five advisory rows, PERMISSIONS, STROKE_SCOPED_PERMISSIONS, the header prose on the per-account report cap), scripts/pm/fleet-write/validate.mjs (levelOf, tokenPermissionsOf, the permission_<name> output line and the self-test cases pinning the advisory grants), .github/workflows/fleet-write.yml (the mint step: a refused mint fails the step with zero writes), scripts/pm/check-skill-line-ratchet.mjs (the ceiling row and the byte budget), card #29448 body, comments 6581779817 (triage) and 6587178205 (claim), PR #29619 body and its one comment 6589621568 (the seat's review claim on this head)

Reviewer: an isolated contract reviewer at CONTRACT_REVIEW_TIER, read-only on GitHub (REST reads only; nothing written, pushed, labelled or commented), fed the card body and comments, the PR body, the diff against the merge-base, the head's check-runs, contract-review.md and review-checklist.md. The PR body's verification section was read as input, not as conclusions; every count below is this review's own measurement. No environment variable value is printed anywhere in this record, and no advisory, finding or mechanism is named: the diff is rule text and a code comment about the relay's advisory rows.

① Derived judgments

  1. File surface. One commit (1d36ecf, author Claude, PR author objectstack-fleet[bot], head repo = base repo, draft, base main, trailers Claude-Session: + Co-Authored-By: Claude, no model identifier). git diff --numstat dd4a21f8 1d36ecfa, the REST file listing and the PR body agree on exactly two paths: .claude/skills/pm-dispatch/references/security-findings.md +1/−1 (blob 5b7442e0 → 7acd15ca), scripts/pm/fleet-write/execute.mjs +3/−2 (c328a12c → 4eb92b0d). Total +4/−3. The claim's file surface for PR A (6587178205) was these two paths with stop-on-breach; nothing else is touched. Correct, and on surface.
  2. The security-findings.md bullet says what the code does. On the head, OPS.advisory_report has permission: 'repository-advisories' and no grant; OPS.advisory_create the same. validate.mjs's levelOf returns OPS[op].grant ?? PERMISSIONS[OPS[op].permission], and PERMISSIONS['repository-advisories'] is 'write', so tokenPermissionsOf carries repository-advisories: write for a stroke of either row; the self-test battery pins all four writing rows to permission_repository_advisories=write. The workflow's mint step reads that output as permission-repository-advisories, and its own comment states that a refused mint fails the step with zero writes. So on an installation without the advisory write grant, a report stroke and a create stroke both die at the mint: the new bullet's first clause (both rows mint the same advisory write grant; a repository without it refuses both) is what the code does. The old bullet, which kept advisory_report for exactly those repositories, named a fallback the relay cannot run; the card's item 1 premise holds against the head and against origin/main. Correct.
  3. The bullet's second clause (a private report has a separate per-account daily cap) is what ops.mjs's header says in the same section: GitHub caps the new private reports an account files per day, every relay report is filed as the one App, and the cap does not reach a created draft. The old bullet's "the whole fleet shares one App" nuance is no longer on the skill line; ops.mjs still carries it, the line sits at 116 bytes of a 120-byte budget, and the rule's reader needs the cap, not the quota's sharing, to choose a row. Correct, with that one nuance moved rather than lost.
  4. The fallback stays where it was. Bullet 5 of §3 (both operations refused ⇒ session hand-off, option A) is byte-identical to the merge-base and two lines below the reworded one, so the rule still names exactly one path for a repository without the grant, and it is the one the relay can run. The card offered the maintainer a different fallback as an alternative; none was ruled, so the "what the code does" branch is the right one. Correct.
  5. The execute.mjs comment names headings that exist. On the head, ops.mjs's header has ## The four rows that touch a security advisory — no advisory text on a public surface (line 376) and ## The one row that READS an advisory — advisory_read, sealed to a key the seat alone holds (line 502); the comment's two quoted names are exact prefixes of those two headings, and the advisory_read sub-bullet the comment points "below" is in the same block. git grep for "three rows that touch" over the whole head tree returns nothing; over origin/main it returns exactly execute.mjs line 195, the one line this PR changes. Correct.
  6. No reader of the old text remains, and no other surface says the old thing. git grep advisory_report over .claude/**, AGENTS.md and docs/agents/** on the head returns only the reworded line; the only other stale phrase the card lists ("THREE consumers") is in fleet-write.yml, which this PR leaves alone by the claim's split and PR ci(fleet-write): the advisory mint comment names its four write rows and the read mint #29620 carries. Correct.
  7. Ratchets and lints. The file is 56 lines against a ceiling of 56 (check-skill-line-ratchet.mjs line 1311 row); the reworded line is 116 bytes without its newline (the body's 117 counts the newline), under the 120-byte budget; the ratchet, its 164-case self-test, the id-lint and the skills token ratchet all exit 0 on the head. The three fleet-write self-tests (execute 259, validate 303, dispatch 315 cases) exit 0 without node_modules, so a comment-only edit to execute.mjs breaks none of its own batteries. Correct.
  8. Governance. check-governed-merges.mjs --branch HEAD and --pr 29619: 2 paths, 1 register hit (.claude/**), Tier S, 7 changed lines under the 3000 threshold, exit 3 as designed; execute.mjs is not on the register. The PR is a draft with no reviews; Governed Surface Queue Guard is success on the head. This record is the Tier S at-tier review of record the guard asks for on the current head; landing follows the seat's queue once every check is green. Correct.
  9. PR body against the head. First content line Part of #29448 with the card number beside zero verbs; the body's only issue number is 29448, so no closing keyword sits beside any card and item 3 is named as "a separate Tier H PR" without a number; the PR-body guards check is success. Clause-②: no and Metadata-protocol: none are right (no published package, no spec, no changeset; skip-changeset and Check Changeset success). The body's 56/56, 42 derived commands, "comment only" for execute.mjs and the fallback-stays-at-bullet-five reading all reproduce here. "Part of" is right: the card closes on the last of the two PRs, which is ci(fleet-write): the advisory mint comment names its four write rows and the read mint #29620 by the seat's plan. Human Minimum item 3 is left unchecked with a reason (no formatter ran, pnpm lint not run locally); Lint · ESLint is success on the head, so the gate it stands for is read from CI. Correct.
  10. Nothing new on any surface: no gate, no label, no workflow, no register row, no package, no new rule; §8 of the file (no new gates, no new labels) still holds. The card asked for a reword to what the code does; this PR is that, on one line, plus the one cross-reference fix.

② Semver level

None. No published package, no packages/spec/src/**, no TypeScript; a skill reference file and a comment in a scripts/pm tool. skip-changeset is the right declaration and Check Changeset is success on the head.

③ Boundary flags

  • Dev open_questions: none in the PR body; the card's one open alternative (the maintainer ruling a different fallback) was not taken up, and the PR chose the branch the card itself names first. No flag.
  • Assignee and requested reviewer huangyiirene on the PR: the PR's assignee mirrors the card's by pr_create, per AGENTS.md; no second claim, no approval, no review submitted. No flag.
  • Both branches off main at dd4a21f, not stacked: PR ci(fleet-write): the advisory mint comment names its four write rows and the read mint #29620's merge-base is the same commit and its one path is disjoint from this PR's two. Confirmed.
  • Independence: PR author objectstack-fleet[bot], commit author Claude; no off-relay author note is owed. The PR thread carries the seat's Contract-review-claim: for this head (6589621568) and no other record.
  • Tier S: this record is the at-tier review; the owning seat lands through the queue once every check on the head is green (the Check-runs line below).

④ Design judgment

Per hits file, against the card's scenario (a seat meeting a security finding reads §3 and must be sent to a row the relay can run):

  • .claude/skills/pm-dispatch/references/security-findings.md: rewording the bullet in place, on one line, keeps the file at its ceiling and keeps §3's shape (preferred rows, read row, the report row's standing, the never-as-self rule, the hand-off, private repositories). The new sentence states the grant the two rows share and what a missing grant does to both, which is the one fact the old bullet got wrong, and leaves the hand-off bullet to say what happens next, so the rule has no second fallback and no contradiction. The per-account cap stays because it is the only thing that still distinguishes a report from a draft for the reader. Holds.
  • scripts/pm/fleet-write/execute.mjs: naming both ops.mjs headings, verbatim as prefixes, is the right fix: the block below already measures the read row with the four writing rows, so pointing at the write section alone would have left the read row's authority unnamed. Comment only; no battery, no export, no behaviour changes, and the three self-tests exit 0. Holds.

Must-fix: none.

Should-fix: none.

Check-runs at record time (2026-11-02T22:23Z): 46 check-runs on 1d36ecf, 26 success, 20 skipped, 0 failure, 0 in progress on the second read; the first read ten minutes earlier had 45 runs, 24 success, 20 skipped and Test Core (1/8) in progress, and the second read added Test Core (1/8) and the Test Core aggregator as success with no non-success completion at either read; combined status pending (statuses API, 0 statuses). Success: Lint & Repo Gates, Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · ESLint, Lint · scoped · tooling self-tests, Lint · scoped · slot lookup & corpus, Lint · scoped · query-options erasure, TypeScript Type Check, Type Check · workspace / source gates / debt ledger / consumer gates, Governed Surface Queue Guard, PR-body guards, Check Changeset, Check PR Size, Dogfood Regression Gate, Plan Test Core shards, Test Core and its two shards (1/8, 2/8), Test UI, Auto Label, filter. Skipped by path filter or opt-in: Build Core, Build Docs, Build UI Deps, Build & E2E UI, Live E2E UI, Lint UI, Type Check UI, Test UI shards, Dogfood Verify CLI, UI Published Artifacts, Temporal Conformance, Schedule gate, 18.x upgrade harness, Packed-tarball smoke. mergeable_state blocked, draft, auto_merge null, labels documentation, size/xs, skip-changeset; Tier S, every check on the head complete and none red, landing by the owning seat through the queue.

Implemented-by: claude/project-thread-7gpiq3
Reviewed-by: session_01J8VVAnMUWA9rufXzFaEh4J

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

维护者速读

  • 改了什么: security-findings.md §3 一条规则改写为代码的实际行为:advisory_report 与 advisory_create 一样要铸 repository-advisories: write,仓库没有这项授权时两者都在铸令牌一步失败,退路是第 4 条的会话交接;execute.mjs 一行注释改为引用 ops.mjs 现有的章节名。+4/−3,2 个文件。
  • 为什么改: 原规则把 advisory_report 写成无授权仓的退路,但中继跑不通,会把遇到安全问题的席位引向一次必然的拒绝。
  • 风险与回滚: 只改规则文本和一行注释,不改任何代码路径或权限;可整 PR revert。
  • 先看: security-findings.md §3 第 3 条。
  • 两分钟验证: node scripts/pm/check-skill-line-ratchet.mjs,该文件 56/56 行。
  • 需要你做的: 无需审批(受治理面 Tier S,本席落地)。
  • 席位意见: ACCEPT。达档复核 PASS(6590010188)。

席位核对 — ACCEPT · domain:skills#1 · head 1d36ecfa038487494fe943ff266d7383a958ae08

  1. 形态: draft → main,Part of #29448(卡由 Tier H 的 ci(fleet-write): the advisory mint comment names its four write rows and the read mint #29620 收尾关闭);skip-changeset;作者 objectstack-fleet[bot];文件面与认领一致。
  2. 前提实测: 复核方对照 ops.mjs 与 validate.mjs:四个写公告的行都铸 write,新句与代码一致;旧的「three rows」引用在本 head 上已消失。
  3. 门禁 check-runs(钉 head 1d36ecfa): 46 条全部完成,success 26 / skipped 20 / failure 0。check-governed-merges:受治理 Tier S(一处 .claude/**)。
  4. 接受的偏差: 无。
  5. 范围外去向: fleet-write.yml 头部一段仍只写 write 级别、未提 read 级别,不在本卡三项之内,记为后续卡素材。Skills-docs: 本 PR 即技能文本改动。
  6. 落地条款: 受治理 Tier S。复核即达档记录;本席 pr_ready + automerge_enable。ci(fleet-write): the advisory mint comment names its four write rows and the read mint #29620 带 Fixes #29448,须在本 PR 之后合入。

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 2, 2026 22:27
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 2, 2026 22:27
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit fa07650 Nov 2, 2026
47 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-7gpiq3 branch November 2, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants