Repository navigation
Description
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
Filing gate: ③ a maintainer-directed task. Maintainer word, verbatim: 「立一张 skills 卡,我现在就派发,然后你再试」 (Warren, project thread "Plan the release checklist run", 2026-11-02 14:17 UTC), answering the proposal below; it is also his naming of this pm-rule change (filing-gate: a card that adds or changes a pm rule is filed only when the maintainer names it).
Business reason: security findings now go to private advisories through the relay (#29178, #29222). GitHub caps NEW private vulnerability reports per account per day (https://github.blog/changelog/2026-10-01-rate-limits-for-private-vulnerability-reports), and every relay report is filed as the one fleet App account, so the whole fleet gets about one report a day; on 2026-11-02 the first report landed and the next eight, from two sessions, were refused 403 (#29402). The App cannot be put on the trusted-reporter allow list. Without this op, findings back up for days or fall back to hand delivery.
Reader who acts: the domain:skills seat (owner of scripts/pm/** relay tooling and .claude/skills/pm-dispatch/**), dispatched by the maintainer now.
Duplicate search: is:issue advisory_create → 0 hits; is:issue "draft advisory" relay → 18 hits, the nearest are #29160 and #29111 (both closed: they built the report/collaborator/state rows and the security rule), none adds draft creation.
Related: #29402 (write-pace reads the 403 as an egress-proxy refusal; the relay hides GitHub's message).
Platform reading this rests on
POST /repos/{owner}/{repo}/security-advisories ("Create a repository security advisory") creates an advisory in draft. Per the REST docs (https://docs.github.com/en/rest/security-advisories/repository-advisories) it accepts GitHub App installation access tokens with the "Repository security advisories" repository permission (write); the rate limit in the changelog applies to new private reports only.
Scope
- Relay row
advisory_createinscripts/pm/fleet-write/ops.mjs(+validate.mjs,execute.mjs), shaped likeadvisory_report:alone; mintsrepository-advisories: writefor its stroke only (STROKE_SCOPED_PERMISSIONS); payload read from the event file; closed keyssummary,description,severity,cwe_ids, and the minimumvulnerabilitiesentry the endpoint requires (ecosystemnpm, package name, ⛔ no version ranges unless the endpoint refuses without them — measure); ⛔ nostateother than the endpoint's defaultdraft, ⛔publishedunreachable, ⛔ nocredits, CVE request or private fork. Lands on a 2xx carrying aghsa_id; prints only the id and state, never summary, description or vulnerability text.REFUSED_PATH_FAMILIESopens exactly this one POST path (no GET list, no PATCH of text). - Follow-up stroke unchanged:
advisory_collaborators_addthen names the finding seat's account on the draft (its fence already admitsdraft). - Skill text (governed,
.claude/skills/pm-dispatch/references/security-findings.md§3 andreferences/rest-channel.md): replace "建草稿公告须管理员或安全经理,中继无此操作 ⇒ 草稿由维护者建" with: the seat files a finding as a DRAFT advisory throughadvisory_create(preferred),advisory_reportstays for repos where the App lacks the permission; record the per-account daily limit on reports. Keep "⛔ 席位永不以自身账号私报或写公告" (writes stay App-only), and "发布归维护者". - Self-tests in
validate.mjsfor the new row (closed keys, published unreachable, no value echoed in refusals), and the step-summary / log no-leak marker test extended to it.
Acceptance
- One live
advisory_createfrom a cloud seat lands adraftadvisory on objectstack-ai/objectstack, its id in the run annotation, nothing of its text in the public run log; a second and third in the same hour also land (the measurement that it is not under the report limit). advisory_collaborators_addon that draft lands.pnpm check:pm-skill-ratchetand the fleet-write self-tests green; Tier H path (governed.claude/**), contract review before any approver is asked.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
Claim: maintainer-directed dispatch · card thread · 2026-11-02T14:20Z
Session:
session_01JQwxbWBtYWqaV8NhvUrShB(the dispatching seat); the card thread's session is named in its first reportAccount:
os-warren(the card's assignee)Branch: the card thread's harness-pinned
claude/project-thread-*branch (it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:skillsSeat:
domain:devx#1dispatching cross-lane on the maintainer's word (below); no skills seat is asked to yieldRuling-ref: Warren, project thread "Plan the release checklist run": 「立一张 skills 卡,我现在就派发,然后你再试」 then 「立一张 skills 卡,你自己派发,开发完成之后,然后你再试」
File surface:
scripts/pm/fleet-write/ops.mjs,scripts/pm/fleet-write/validate.mjs,scripts/pm/fleet-write/execute.mjs(only if the row needs executor code),.claude/skills/pm-dispatch/references/security-findings.md,.claude/skills/pm-dispatch/references/rest-channel.md; ⛔ no.github/workflows/**unless the mint step cannot carry the row as is (stop and report)Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tierat838a802bf3: no path-derived mandate),effort: xhighClause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: none
Premise: holds (read at
origin/main838a802bf3:REFUSED_PATH_FAMILIESadmits only one advisory's path and the reports path;security-findings.md§3 says the relay has no draft-create op)Serial constraints cleared: #29402 (open, unclaimed) names
write-pace.mjsand the advisory refusal text inexecute.mjs; this card does not touchwrite-pace.mjs, and if it editsexecute.mjsit stays out of the refusal-message block #29402 owns.State: →
pm:dispatched, assigned toos-warren, recorded by this claim. Order lives in the project.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbZ5rVEB642GP9VD5Xj
os-dev-report
{ "issue": 29410, "status": "done", "branch": "claude/project-thread-hir0t0", "pr": "https://github.com/objectstack-ai/objectstack/pull/29436", "session": "session_01JQwxbZ5rVEB642GP9VD5Xj", "premise_still_valid": true, "summary": "New relay row advisory_create: ONE POST to the bare security-advisories collection (creates a draft), alone in its stroke under the stroke-scoped repository-advisories grant; closed keys summary, description, packages (npm names, one vulnerabilities entry each, ecosystem npm and name only), optional severity and cwe_ids; no state, credits, CVSS vector, CVE id or private fork. Lands on a 2xx carrying a ghsa_id that reads state draft; the row and an advisory annotation name the id alone, and the seat hands it on for advisory_collaborators_add. REFUSED_PATH_FAMILIES opens exactly the bare collection path, and the validator pins that this row's POST is the only request on it. security-findings.md section 3 now prefers advisory_create, keeps advisory_report for repos where the App lacks the grant, records the per-account daily report cap, keeps App-only writes and maintainer-only publishing; rest-channel.md points there. Both governed files net zero lines.", "tests": "validate self-test 275 cases / 15 batteries (advisory battery 51, pin 51; pin 52 reds with 'registered 51'); execute self-test 237 / 21 (advisory battery 27, pin 27); dispatch self-test 298 / 26 (seat advisory battery 14, pin 14); ops self-test exit 0. One-time ablation at f68850fd: the draft's landed row also printing the answer's summary reds 2 of 237 execute cases (the row case and THE MARKER TEST); restored with blob equal to HEAD, exit 0.", "gates": "local subset at f68850fd: dispatch-gates --commands derived 46, all run, all exit 0 (node scripts/check-closing-keyword-parity.mjs; node scripts/check-closing-keyword-parity.mjs --self-test; node scripts/check-comment-mask-corpus.mjs; node scripts/check-declaration-mirrors.mjs; node scripts/check-declaration-mirrors.mjs --self-test; node scripts/check-self-test-wired.mjs; node scripts/check-self-test-wired.mjs --self-test; node scripts/check-self-test-workflow-commands.mjs; node scripts/check-self-test-workflow-commands.mjs --self-test; node scripts/check-whole-set-label-write.mjs; node scripts/check-whole-set-label-write.mjs --self-test; node scripts/ci/plan-test-core-shards.mjs --self-test; node scripts/pm/bare-root-worklist.mjs --self-test; node scripts/pm/check-harness-current.mjs --self-test; pnpm --filter @objectstack/lint run check:doc-formula-expressions; pnpm check:agent-test-spelling; pnpm check:bash32-floor; pnpm check:ci-filter-parity; pnpm check:cli-command-ids; pnpm check:cross-package-test-inputs; pnpm check:doc-authoring; pnpm check:driver-memory-census; pnpm check:entry-guard; pnpm check:gitlink-declared; pnpm check:nul-bytes; pnpm check:parse-guard; pnpm check:pm-close-cards; pnpm check:pm-dispatch-gates; pnpm check:pm-fleet-write-dispatch; pnpm check:pm-fleet-write-execute; pnpm check:pm-fleet-write-validate; pnpm check:pm-governed-merges; pnpm check:pm-issue-create; pnpm check:pm-issue-transfer; pnpm check:pm-label-write; pnpm check:pm-post-stamped; pnpm check:pm-record-recognisers; pnpm check:pm-skill-id-lint; pnpm check:pm-skill-ratchet; pnpm check:pm-write-pace; pnpm check:pnpm-filter-targets; pnpm check:pnpm-flag-spellings; pnpm check:refd-timer-probe; pnpm check:scripts-symbol-anchors; pnpm check:skill-frame-sync; pnpm check:watch-hint-literal); --ran reconciliation: 46 derived, 46 run, 0 NOT-MEASURED. CI families: the PR's check-runs, in_progress at report time.", "line_budget": { "security-findings.md": "55 to 55 (ceiling 55)", "rest-channel.md": "81 to 81 (ceiling 81)", "ratchet": "check:pm-skill-ratchet exit 0, no ceiling row moved", "max_changed_line_bytes": 120 }, "files_changed": [ "scripts/pm/fleet-write/ops.mjs", "scripts/pm/fleet-write/validate.mjs", "scripts/pm/fleet-write/execute.mjs", "scripts/pm/fleet-write/dispatch.mjs", ".claude/skills/pm-dispatch/references/security-findings.md", ".claude/skills/pm-dispatch/references/rest-channel.md" ], "deviations": [ "scripts/pm/fleet-write/dispatch.mjs edited outside the claim's file surface: ADVISORY_ANNOTATED_OPS must name advisory_create or the draft's id never reaches the seat.", "rest-channel.md advisory line loses its check mark: the line now names an op no seat has called; the seat's live run restores it.", ".github/workflows/fleet-write.yml comment above permission-repository-advisories still says THREE consumers; left untouched per the claim (mint step carries the row as is), noted in Acceptance notes.", "PR template headings folded into the os-dev section order (What changes / Why / Tests / Acceptance notes / Verification / Deviations / Human Minimum)." ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, labels skip-changeset), this report comment via post-stamped; plus git push (not REST)", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "class: none · the workflow comment drift above is a comment, noted in the PR's Acceptance notes · carrier: the next PR touching fleet-write.yml" ], "acceptance_after_merge": "seat runs: one advisory_create landing a draft (id in the annotation, no text in the run log), a second and third in the same hour, then advisory_collaborators_add on that draft; a refusal stops and goes to the maintainer as status plus listed message" }objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p1 (priority added) · 2026-11-02T15:05Z
⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
ACCEPT → PR #29436 comment 6580686659 · 2026-11-02T15:14Z
Contract review PASS 6580628573 on head
f68850fd; should-fixes filed #29448. Tier S, the seat lands it.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
Live acceptance after PR #29436 merged, read 2026-11-02T16:00Z — H1, H2 and H3 hold.
advisory_create×5 from this cloud seat, 15:53–16:00 UTC, each its own stroke: 5 of 5 landed adraftadvisory with an id in the run annotation (first run 41475893395). Earlier the same dayadvisory_reportwas refused 403 after its first landing, so five drafts in one window is the measurement that drafts are not under the per-account private-report limit.advisory_collaborators_add×5 on those drafts: 5 of 5 landed.vulnerabilitiesshape: one npm entry withecosystemandnameonly was accepted.rest-channel.mdcan take its ✓ back for this row (carrier: #29448).Generated by Claude Code