Skip to content

The weekly OSV scan has no outlet, so a new advisory is discovered by whichever PR author next touches a package.json — six occurrences in a month #14645

Closed

Description

@huangyiirene

Split out of #14639 by triage. That card is the current instance — four fixable OSV advisories red in the lockfile — and is queued as a take-the-fix repair. This card is the question it records but deliberately does not answer: why this class keeps being discovered by accident.

The measured lineage (from #14639, which assembled it)

Card Advisory Disposition
#4945 brace-expansion closed, took the fix ("cleared in ten minutes")
#5032 undici / hono / fast-uri, 8 fixable, red on main closed
#5039 fast-uri / hono / undici, "队列级阻塞" closed
#6407 dompurify via mermaid closed
#6506 nanoid, "有 fix,缺 override" closed
#14639 @xmldom/xmldom ×2, qs ×2 open

Six in a month. Every one was fixable at the time it was found. Every one was found by whichever seat happened to trip over it, never by anything watching.

The mechanism

.github/workflows/validate-deps.yml runs on two triggers that do different jobs and are not synchronised:

  • schedule: cron '0 3 * * 1' — weekly, Mondays. This is the discovery trigger.
  • **/package.json, pnpm-lock.yaml, .changeset/config.json, pnpm-workspace.yaml, osv-scanner.toml — per-PR. This is the blocking trigger.

Between Monday scans, a new advisory lands in the OSV database and nothing in the repo changes. The first PR that touches any manifest then runs the scan and eats a red that has nothing to do with its diff. So the blocking trigger is doing the discovery, six days late, on a random author.

Options

  • A — tighten the scan cadence (daily rather than weekly). Discovery moves ahead of blocking without adding anything new. Does not change who acts on it.
  • B — give the scheduled scan an outlet: a red scheduled run opens a card. The job already holds issues: write, so the capability is present and unused.
  • C — status quo. Keep discovering by collision. Six data points say what that costs.

A and B are not exclusive.

What this card does NOT cover

⛔ The four current advisories. Those are #14639's, and that card is pm:queue — do not fold the repair in here, and do not wait for this ruling to take the fix.

<!-- os-decision-facets -->

  • ① 项目长远合理性(权重 ≥50%,领起推荐) —— 平台有两道触发器:一道每周扫一次(负责发现),一道对每个碰 manifest 的 PR 生效(负责阻塞)。两者之间有六天的窗口,于是阻塞那一道在替发现那一道干活 —— 而且是在一个跟这件事毫无关系的作者身上。长远终态很朴素:发现要早于阻塞。①指向「让定时扫描的红有一个出口」,而不是继续让下一个提 PR 的人充当探测器。
  • ② 实际业务拉动 —— 一个月六次,每次都是「某个席位恰好撞上」,而且每次都跨车道。这是已测的、重复发生的代价,不是假想。
  • ③ 防 AI 犯错 —— 出错时谁看到什么:一个 agent 提了个只加一行 scripts 的 PR,CI 红了,红的原因跟它的改动毫无关系。它会去读 OSV 报告、可能去动锁文件、甚至可能去 osv-scanner.toml 加豁免 —— 而那个文件的规则明令有 fix 时禁止豁免。⚠️ 把不相关的红扔给最不该修它的人,正是最容易诱发错误修法的形状,而这里连正确的修法都写在一个它未必会读的文件头里。
  • ④ 创业阶段不扩散 —— ⚠️ 这一棱反对 B:自动开卡是往 backlog 里新增一个自动生产者,而生产者集合是有永久代价的 —— 每张自动卡都要被分诊、去重、关闭,而这正是本席这个座位的负载。提频(A)不新增生产者,只是把同一条信号提早。④明确偏 A。

推荐:A —— 先提频到每日,不自动开卡。 ②有重复拉动、③要的是提早发现,提频就足以给到;④明确反对新增自动生产者;①两者都满足,而 A 更便宜。
回退:B —— 若维护者判定「提频只是让红更早出现,而没有人负责去看」,那就给定时扫描一个出口(该 job 已持有 issues: write)。代价必须同批裁定:自动卡的去重规则、关闭规则,以及它算不算 finding 箱的输入 —— ⛔ 否则它会变成一个没有人负责清空的第二条队列。
⛔ 不荐 C。 六次是已测数据。
置信缺口(本分析看不见什么): 没有量提频后的噪声 —— 每日扫描会不会在同一条未处理的通告上连续红七天,取决于谁在看 scheduled run 的结果,而「谁在看」本轮没量。这是 A 唯一可能不成立的地方,也正是 B 想解决的那件事。

Refs: #14639 (the current instance, and the card that assembled this lineage) · #4945 · #5032 · #5039 · #6407 · #6506.

Generated by Claude Code

Activity

  1. os-project-manager commented on Sep 3, 2026

    @os-project-manager
    Collaborator

    Maintainer ruling recorded — A: the OSV scan runs daily; no automatic card producer yet

    Director seat, summon #11, session session_01ShyhexkB2d1AeRZ85tgAAe, 2026-09-03.

    Provenance (who / verbatim / where): maintainer, live PM chat with the director seat, 2026-09-03, replying to decision batch #20 in which this card was item 5 with the recommendation A (fallback B). Verbatim reply: 「其他同意」 — adopts A.

    Ruled: A. The osv-scanner.yml schedule moves from weekly to daily (one cron line), so the discovery window for a new advisory shrinks from up to six days to one and a seat is far more likely to see the scheduled red before an unrelated PR collides with it. Option B (a scheduled red opens a card automatically) is not built now: it is a new automatic producer whose dedupe and close rules would have to be ruled with it, and the measured pull (six collisions in a month) is answered by the cadence first. Recorded fallback: if a daily red is measured going unseen until a PR collides with it, B returns as its own card with the dedupe / close rules in the same proposal.

    Execution: domain:devx lane, S, .github/workflows/osv-scanner.yml; skip-changeset; Clause-②: no.

    State transition, same stroke: needs-user-decision → pm:queue. Ledger: director seat post #12708, summon #11.


    Generated by Claude Code

  2. claude commented on Sep 3, 2026

    @claude
    Contributor

    Claim: PM loop round 1
    Session: session_012zGPuVVX3deAx9LdjK8jCk
    Branch: claude/issue-14645-osv-daily-cadence
    Worktree: objectstack-issue-14645
    Domain: domain:devx
    File surface: .github/workflows/validate-deps.yml (stop on breach; explain in the report)
    Container & model: S mechanical, mode:subagent, model: sonnet (dispatch-gates --tier at 11:02Z: no path-derived mandate; floor sonnet applies — one cron field, correctness judged by the gate farm)
    Clause-②: no
    Serial constraints cleared: none — no in-flight devx card touches .github/workflows/**; verified against the four live PRs #14853/#14872/#14896/#14856, whose ten pairwise file intersections are all 0


    Generated by Claude Code

  3. baozhoutao commented on Sep 3, 2026

    @baozhoutao
    Contributor

    Claim (dev agent): starting implementation.
    Session: session_012zGPuVVX3deAx9LdjK8jCk
    Branch: claude/issue-14645-osv-daily-cadence
    Worktree: ../objectstack-issue-14645

    Note: the ruling names .github/workflows/osv-scanner.yml, which does not exist on origin/main at my base commit 450e73b. The card body correctly names .github/workflows/validate-deps.yml (schedule cron on line 22, issues: write present). Applying the ruling's substance — weekly → daily, one cron line — to that file, per the card's own correction note.


    Generated by Claude Code


    Generated by Claude Code

  4. baozhoutao commented on Sep 3, 2026

    @baozhoutao
    Contributor

    os-dev-report

    {
      "issue": 14645,
      "status": "done",
      "branch": "claude/issue-14645-osv-daily-cadence",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14934",
      "premise_still_valid": true,
      "summary": "Moved the OSV/dependency-scan schedule trigger in .github/workflows/validate-deps.yml from weekly ('0 3 * * 1', Mondays) to daily ('0 3 * * *'), same 03:00 UTC hour — Option A per the maintainer ruling (issue comment 5523306978). The ruling names .github/workflows/osv-scanner.yml, which does not exist on origin/main; applied the ruling's substance to validate-deps.yml, the file the card's own body correctly names and which actually carries the schedule trigger and issues: write. Did not build Option B (no issue-opening step added) and did not fold in #14639's four advisories, per scope fence.",
      "tests": "HEAD 663dc667 (matches pushed branch tip). All 29 commands dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived from this changeset ran via scripts/pm/os-verify-lock.sh, foreground, exit code captured before any pipe (redirect-then-$?-then-read pattern), each read from its own printed verdict line, all exit 0: check-aggregator-roster, check-changeset-fixed, check-closing-keyword-parity, check-comment-mask-corpus (5790 files, 0 disagree), check-osv-exemptions (--self-test + real run), check-position-name-fold-loaders, check-required-contexts, check-self-test-wired, check-self-test-workflow-commands, check-shard-attestation, check-step-collectors, check-whole-set-label-write, docs-audit/check-drift-comment, pm/ci-failure --self-test, check:agent-test-spelling, check:declared-population-live, check:node-version, check:nul-bytes, check:override-consistency (9 override(s) resolve to targets), check:pm-dispatch-gates (dispatch-gates self-test: 1288 cases pass), check:pnpm-acquisition, check:pnpm-filter-targets, check:refd-timer-probe, check:required-contexts, check:shard-attestation, check:stall-guard-budget, check:stall-guard-headroom, check:watch-hint-literal, check:workflow-status-functions (30 workflow files, 53 jobs). Re-derived the family list post-commit at HEAD 663dc667 (dispatch-gates.mjs --commands again): identical list, no new gates introduced by the final commit. YAML validated with python3 yaml.safe_load. On-CI (informational, not waited on beyond what completed during this turn): PR #14934 checks — 'Validate Package Dependencies' (validate-deps.yml itself, pull_request trigger) succeeded; 27 of 30 check runs completed successful/skipped; 'Lint & Repo Gates' was still in_progress when this report was written (in_progress, CI convergence is PM's to track per dispatch instructions, not re-polled here).",
      "mcp_calls": 10,
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. claude commented on Sep 3, 2026

    @claude
    Contributor

    ACCEPT — PR #14934, reviewed 2026-09-03T11:24Z by session_012zGPuVVX3deAx9LdjK8jCk

    Checked against the diff and origin/main, not the report.

    item reading
    PR form draft, base main, first line Fixes #14645, skip-changeset + size/xs
    governed surface clean — .github/workflows/** is explicitly NOT governed (docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md is the whole list) ⇒ normal ready→queue path
    scope 1 file, +5/−2 — .github/workflows/validate-deps.yml only
    the change - cron: '0 3 * * 1' → + cron: '0 3 * * *' — one field, same 03:00 UTC hour
    ruling fidelity Option A exactly; ⛔ no Option B issue-opening step; ⛔ #14639's four advisories not folded in

    The judgement call in it that was right

    The dispatch asked for "one cron line". The dev also rewrote the adjacent comment — which reads as scope creep for about two seconds, and is in fact the correct minimum: the old comment said "Run weekly on Monday at 03:00 UTC". Changing only the cron would have left a comment asserting weekly directly above a daily schedule — a fresh declared ≠ enforced contradiction, in the same three lines, introduced by a card whose whole subject is discovery lag. The four added lines say what changed and why, and cite the card. ⇒ Correct, not creep.

    The ruling's filename slip, handled the way I asked

    The ruling names .github/workflows/osv-scanner.yml. That file does not exist — I measured this at 11:01Z before dispatching, and the dev re-measured it independently. The ruling's substance (weekly → daily) was applied to validate-deps.yml, the file the card's own body names and the one that actually carries both the schedule: trigger and issues: write. ⛔ Nothing was re-adjudicated; the slip is clerical and is recorded in the PR body.

    Gates

    29 dispatched families derived by the dev from its own tree post-commit and re-derived at the final HEAD (identical list — so no gate was introduced by the last commit and then left unrun), all exit 0, captured before any pipe by the redirect-then-$?-then-read pattern. YAML re-validated with yaml.safe_load, which is the one check that matters for a workflow edit and is not implied by any of the 29.

    Landing — not yet armed, deliberately

    CI on 663dc6670f at 11:23Z: 17 success / 12 skipped / Lint & Repo Gates still in_progress. Enqueue eligibility is every check green, not the required subset, so this waits. Flip + arm on convergence; a red there is this PR's to explain, not to re-run.

    ⚠️ Process note recorded against this dispatch: the dev's first turn ended with the gate suite handed to a background watcher, which is a stall, not a completion — nothing would have restarted it. It was reset to foreground execution immediately rather than after any silence threshold, and the second turn ran all 29 gates in-turn. The delivery above is that second turn's.


    Generated by Claude Code

  6. claude commented on Sep 3, 2026

    @claude
    Contributor

    LANDED — PR #14934 MERGED 12:01:13Z; probe on origin/main

    domain:devx seat, session session_012zGPuVVX3deAx9LdjK8jCk, R1.

    $ git show origin/main:.github/workflows/validate-deps.yml | sed -n '20,24p'
      schedule:
        # Run daily at 03:00 UTC — narrows the discovery window for a new OSV
        # advisory from up to six days (weekly) to one, ...
    

    Merge commit 3210b3d5d confirmed an ancestor of origin/main (git merge-base --is-ancestor, exit 0). Option A as ruled; ⛔ no Option B producer built; ⛔ #14639's advisories untouched.

    ⚠️ A reading worth recording, because it nearly became a false regression report. My first probe after the merge notification still showed cron: '0 3 * * 1' — weekly. The change had not reverted: my local origin/main ref was fetched before the 12:01:13Z merge. origin/main is a local ref that only a fetch moves, and a merge notification does not move it. Re-fetch before every post-merge probe; without that step this close-out would have reported a landed change as missing.

    ACCEPT: 5524960911. pm:dispatched stripped, assignee cleared.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions