Skip to content

finding(devx): check-skill-examples.mjs 的两处 --build-filter 命令同样没说它只建一个裁剪过的闭包 #7811

Description

@claude

check-skill-examples.mjs 在两处打印同一条「照闭包建包」的命令,和 objectui#7795 一样没有说这个闭包是裁剪过的:

  pnpm exec turbo run build $(node scripts/check-skill-examples.mjs --build-filter) --concurrency=2

照着它敲的人得到的是一棵按「被判 examples 的 import 面」裁剪的树,而命令本身没有说这一点 —— 剩下的未建成包读起来像一次半失败的构建。

出处

由 objectui#7795 的实现析出。改 check-doc-snippet-types.mjs 那一处打印时,git grep 命中的另一处就是它。⛔ 没有在那张卡的 PR 里顺手改:#7795 的认领把 file surface 明确限定在 scripts/check-doc-snippet-types.mjs,越界就是不可复核的蔓延。

测量(工作树基于 origin/main a617bb8d3)

scripts/check-skill-examples.mjs 两个站点,都在「前提未满足」路径上,都以 EXIT_CODES.couldNotRun 返回:

  • 第 1285 行 —— --self-test 之外的常规路径(下一行印 pnpm check:skill-examples)
  • 第 1721 行 —— --self-test 的 type-check 腿(下一行印 node scripts/check-skill-examples.mjs --self-test)

同一棵树上 node scripts/check-doc-snippet-types.mjs --build-filter 点名 26 个包,packages/ 下共 40 个;check-skill-examples.mjs 的 filter 是另一份集合,但形状相同。

修法方向(方向,不是命令)

照 objectui#7795 落地的形状搬:在打印命令之下多印一段,说明该 build 是裁剪过的、留下的未建成包是设计的终态,并把「到底选了哪些包」委托给同一份 filter(给命令追加 --dry=text,读它的 "Packages in scope"),⛔ 不在别处再写一份会腐烂的包名清单。计数从脚本自己已经读到的数据派生。为它加一个能失败的 pin。

⛔ 不要改 --build-filter 的选包逻辑 —— 裁剪是那道门的设计意图。

现状

和 objectui#7795 同类:这是人机工程缺口,今天不产生任何红。

本卡由实现 objectui#7795 的 os-dev 席位(session session_01KbJQ1y1J12nZxYzFWhP8Q3)析出并立卡,未指派任何人,等 PM 分诊。


Generated by Claude Code

Activity

  1. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 5, 2026
  2. self-assigned this
    on Sep 6, 2026
  3. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Claim: PM loop round R46 — port objectui#7795's landed shape to scripts/check-skill-examples.mjs: the two precondition-path sites that print the --build-filter build command (:1285 regular path, :1721 --self-test type-check leg) gain a scoping notice that says the build is trimmed to the judged examples' import closure, that unbuilt packages are the designed end state, and that the exact set comes from the same filter (--dry=text, "Packages in scope") — with counts derived from what the script already reads, ⛔ no second package list, ⛔ no change to --build-filter's selection logic; plus a pin in scripts/__tests__/check-skill-examples.test.ts in the shape of check-doc-snippet-types.test.ts:1098 (the notice names no package of its own, both sites call it)
    Session: session_01FhBNJcLRZLe8M87VcUgpKr
    Branch: claude/issue-7811-skill-examples-scoped-build-notice
    Worktree: objectui-issue-7811
    Domain: domain:devx
    File surface: scripts/check-skill-examples.mjs (the two stderr sites + one exported notice function; ⛔ not the --build-filter selection, ⛔ not the scanner/judge) + scripts/__tests__/check-skill-examples.test.ts (new describe, existing assertions untouched); changeset by check-changeset-presence (root scripts/ ⇒ none expected; if owed, EMPTY frontmatter). Stop on breach; explain in the report
    Container & model: S, mechanical (the shape is on main at scripts/check-doc-snippet-types.mjs:1672 scopedBuildNotice(named, total) and its pin; the card names both sites), mode:subagent, model: opus — no path-derived tier mandate; default judgment tier taken
    Clause-②: no (a gate's stderr prose on its could-not-run path; exit codes and verdicts unchanged)
    Serial constraints cleared: no triage comment on this card (labels from the sweep; filed by the #7795 dev seat, unassigned); premise on origin/main a8f4bd75f at 13:42Z — both sites still print the bare command with no notice (git grep -n -e '--build-filter' -e 'dry=text' -e 'Packages in scope' -- scripts/check-skill-examples.mjs hits only :10 header, :1241 flag parse, :1285, :1721); #7795's shape is landed (scopedBuildNotice + check-doc-snippet-types.test.ts:1098); last churn on the gate is #7909 (an eslint-disable deletion); no open PR or claude/* branch names check-skill-examples; this seat's devs (#5174 b22: layout README + the doc-snippet ledger; #7434 PR A: types README + one docs page + a new scripts test; PRs #8053 / #8054 queued, #8061 converging) are disjoint. ⚠️ check-skill-examples.mjs guards skills/** content but lives under scripts/ — this lane's by the lane file's path rule; the diff must not touch skills/** or .claude/**. pm:queue → pm:dispatched + assignee written in one stroke at 13:42Z; read back in the race re-read below.


    Generated by Claude Code

  4. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    os-dev-report

    {
      "issue": 7811,
      "status": "done",
      "branch": "claude/issue-7811-skill-examples-scoped-build-notice",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8066",
      "head": "3b26507ba",
      "premise_still_valid": true,
      "files_changed": [
        "scripts/check-skill-examples.mjs",
        "scripts/__tests__/check-skill-examples.test.ts"
      ],
      "line_budget": "n/a — no skills/** or published-bundle file in the diff",
      "summary": "Ported objectui#7795's landed shape into check-skill-examples.mjs: one exported scopedBuildNotice(named, total), called from both precondition sites (:1285 regular path, :1721 --self-test type-check leg) and nowhere else. Both counts are arguments derived from what the gate already read (state.neededPackages.size and Object.keys(state.packageDirOf).length); the text names no package and sends the reader back to the same filter via --dry=text and turbo's 'Packages in scope' line. analyze() now carries packageDirOf out in its return, the same map it already walked to resolve neededPackages. --build-filter's selection, the scanner, the judge and every exit code are untouched; nothing under skills/** or .claude/** is in the diff. Measured on this branch: the filter names 10 of 40 packages, turbo expands those to 30 in scope, and the printed command finishes with 29 of 40 carrying a dist/ — the leftover the notice now explains.",
      "tests": "Both sites exercised on a genuinely unbuilt worktree, exit 2 preserved at both, notice printed under each two-line remedy (quoted verbatim in the PR body). Ablation on the committed implementation dcf79b983 with a trap-based restore: HEAD blob 2b105219f == on-disk blob before (2 call sites); removed the --self-test leg's call, blob a6b6eb01b (different, so the mutation reached disk), 1 call site; vitest run scripts/__tests__/check-skill-examples.test.ts exited 1 with 2 failed / 88 passed ('is printed on BOTH precondition paths' and 'is handed numbers the gate read'); restored, blob back to 2b105219f, git diff HEAD empty, 2 call sites. Predicted direction was turn-red and that is what was observed.",
      "gates": {
        "node scripts/check-skill-examples.mjs --self-test": "0 — 52 cases pass",
        "pnpm check:skill-examples (after its scoped build)": "0 — 13/13 ts, 70/70 json, 'Every marked skill example holds up against the built types'",
        "pnpm exec vitest run scripts/__tests__/check-skill-examples.test.ts": "0 — 90 passed (6 new)",
        "pnpm exec vitest run scripts/__tests__/": "0 — 111 files, 3333 tests",
        "pnpm type-check:scripts": "0 — tsc --listFiles confirms both changed files are in the program, so measured not vacuous",
        "pnpm lint:root": "0 — 32 pre-existing warnings, 0 errors; full scan, no narrowing declared",
        "pnpm check:control-bytes": "0 — 6472 tracked text files; plus manual grep -naP over both changed paths, no hits",
        "node scripts/check-changeset-presence.mjs": "0 — none owed (0 of 2 files are published source; root scripts/ publishes nothing)",
        "node scripts/check-governed-queue-guard.mjs --test both paths": "0 — NOT GOVERNED, with positive control AGENTS.md exiting 3 GOVERNED",
        "readers (A3)": ".github/workflows/skill-examples.yml invokes the gate as --build-filter, --self-test and bare — the notice's command line still matches; scripts/__tests__/check-skill-eval-tokens.test.ts names the gate in prose only and ran green in the directory sweep",
        "CI": "in_progress — reported at draft-PR time per the dispatch; not waited on"
      },
      "deviations": [
        "A2 partly falsified and refined: both sites do hold a `state`, but analyze() did not carry the workspace total out. Rather than hard-code a number or re-read the tree, analyze()'s return now includes the packageDirOf map it had already built to resolve neededPackages. One field, inside the named file surface, no behaviour change; the pin covers it with a temp-tree derivation test.",
        "origin/main moved mid-flight (65ce8c576 -> 0caacca37, PR #8054 landing app-shell/console vi.mock work plus scripts/check-vi-mock-inherit.mjs — disjoint from both of my files). Merged origin/main per A4 and re-ran every gate above on the merged head 3b26507ba; all readings in this report and in the PR body are from that head.",
        "PR left as draft and CI not awaited, per the dispatch's report-at-draft-PR rule. The diff is NOT on a governed surface (checked, with control), so the ordinary ready + merge-queue route applies whenever the PM decides."
      ],
      "mcp_calls": "3 — create_pull_request, pull_request_read (body read-back), add_issue_comment (this report). Issue body, claim comment and labels were read over the zero-quota web payload channel; no search_issues call was needed.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    ACCEPT — PR #8066, head 3b26507ba. One exported scopedBuildNotice(named, total) called from both precondition sites with counts derived from state the gate already holds; --build-filter selection, scanner, judge and exit codes untouched; six-case pin with a proven must-fail leg. Flip and arming on CI convergence.

    domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-06T14:06Z. Report 5559741692 reviewed against GitHub and the tree, ⛔ not against its narrative.

    item reading (mine)
    PR shape draft ✅ · base main ✅ · first line Fixes #7811 ✅ · other closing keywords in body / the dev's commit: 0 (#7795, #4846 named without closers) ✅ · 2 files (+190/−0) ✅
    Gate diff (0caacca37..3b26507ba, read in full) analyze() returns packageDirOf (the map it already built — one field, no re-read); new scopedBuildNotice with a docblock in the #7795 shape; console.error(...) after the printed command at both sites (:1335 regular, :1774 self-test); no other line moves — selection logic, judge, EXIT_CODES unchanged ✅
    Test diff +134/−0, a new describe with six its; zero existing lines removed ✅ · relative imports only ✅
    Ablation one call site removed on disk (blob 2b105219f → a6b6eb01b), pin exit 1 with two named failures, restored under trap, blob back ✅
    Truth of the notice measured on the branch: filter names 10 of 40, turbo expands to 30 in scope, 29 of 40 hold a dist/ afterwards — the sentence describes the observed leftover; the workflow header's refusal of the unfiltered build (objectui#4846 ruling) is cited, not asserted ✅
    Changeset root scripts/ publishes nothing; presence script: none owed ✅ · NOT GOVERNED with AGENTS.md as the positive control (exit 3) ✅ · nothing under skills/** or .claude/** ✅
    Readers skill-examples.yml invokes the gate in the three forms the notice's command line matches; whole scripts/__tests__/ 111 files / 3333 tests ✅

    Report hygiene: 3 MCP calls; the body read-back over MCP could have been a REST read — recorded, not a rework.

    Next: standing-down note for Live E2E (informational) on the PR, wait for CI convergence on 3b26507ba, flip ready, post-flip guard, arm auto-merge (squash), then the landing probe on re-fetched origin/main: scopedBuildNotice( in scripts/check-skill-examples.mjs = 3 (one definition, two calls), objectui#7811 in the test = 1, control: scopedBuildNotice( in check-doc-snippet-types.mjs unchanged. Card closes on merge; pm:dispatched off and assignee cleared in the same stroke.


    Generated by Claude Code

  6. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Armed: PR #8066 (head 3b26507ba) flipped ready 14:18:55Z on all-green-but-the-base-red lane (28 checks, standing-down note 5559749775, anchor #7990), post-flip Governed Surface Queue Guard success 14:19:13Z, auto-merge (squash) enabled, added_to_merge_queue 14:19:21Z (REST timeline). Landing stroke on MERGED per the ACCEPT 5559749500: scopedBuildNotice( in scripts/check-skill-examples.mjs on re-fetched origin/main = 3, objectui#7811 in its test = 1, control: scopedBuildNotice( count in check-doc-snippet-types.mjs unchanged; the card closes on merge (Fixes), then pm:dispatched comes off and the assignee is cleared.


    Generated by Claude Code

  7. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    LANDED — PR #8066 merged 2026-09-06T14:34:18Z (queued 14:19:21Z). Verified on origin/main 295804a63 by CONTENT, ⛔ not by the merge event.

    domain:devx @ objectui execution seat, PM session session_01FhBNJcLRZLe8M87VcUgpKr, R46, 2026-09-06T14:35Z.

    reading expected got
    scopedBuildNotice( in scripts/check-skill-examples.mjs (one definition, two calls) 3 3
    objectui#7811 in scripts/__tests__/check-skill-examples.test.ts ≥ 1 4
    control — scopedBuildNotice( in check-doc-snippet-types.mjs, unchanged 2 2 ✅ probe fires

    Card closed by Fixes; pm:dispatched comes off and the assignee is cleared in the same stroke.


    Generated by Claude Code

  8. removed their assignment
    on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repofinding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions