Skip to content

ci: 20 inline workflow scripts over 80 lines (4,385 lines, largest 872) cannot be self-tested, and 16 check:* gates are run by copying their command line into the YAML instead of pnpm run, so they drift from package.json #26086

Closed

Description

@objectstack-fleet

Filing gate ③: a maintainer-directed task. Maintainer, 2026-10-26, verbatim: 「完整的评估本项目, 还有哪些可以优化的地方。包括 ci 和文档」 then 「使用 pm-dispatch 技能创建 issue,需要决策的立为决策卡。」 and 「低优先级的先不考虑」. Batch-of: 19 (repository evaluation 2026-10-26, session_019a9XCWsbMFp75REzthE6cs; 9 decision cards + 10 execution cards). ⛔ Filed bare: grading, domain:* and area:* are triage's. ⛔ Not a claim. Reader: the domain:devx execution seat (gate wiring) — one os-dev, two PRs (one per mechanism), Tier H. Dedupe: REST list (439 issues), grep inline script|github-script → 0 hits. New.

谁付代价(业务筛): a bug in an 872-line github-script body is found in production (a wrong triage comment on a real PR) because no --self-test can reach it; a gate whose command line is copied into YAML silently stops matching the script's package.json definition when someone edits one of the two.

Measured (HEAD 0d83ee8)

  • 20 inline run: / github-script bodies over 80 lines, 4,385 lines in total. Largest: merge-queue-triage.yml "Post the triage comment" (872 lines), docs-drift-check.yml "Comment on PR" (597), cross-repo-issue-closer.yml (416).
  • AGENTS.md 「Writing a --self-test」 (line 1049) is the repo's rule for scripts; 271 of 316 scripts/** entry points have one; an inline body has none by construction.
  • 16 check:* scripts invoked by inlining the command rather than pnpm run check:<name>: check:adr-links (check-links.yml:115), check:undeclared-dep-imports (lint.yml:918), check:empty-changeset (pr-automation.yml:919), check:registry-log-declared / check:rest-log-declared / check:rest-log-spy-declared (lint.yml:3614-3644), and ten more (the dev lists them with grep -n 'node scripts/' .github/workflows/*.yml cross-checked against package.json script values).

Wanted

  • PR 1: move each inline body over about 80 lines into scripts/ci/<name>.mjs with a --self-test (fixture event JSON in, expected comment/markdown out); the YAML step becomes node scripts/ci/<name>.mjs with the event passed by env or --event-file. ⛔ Behaviour-preserving: the self-test's expected outputs are captured from the current inline body first.
  • PR 2: replace the 16 inlined command lines with pnpm run check:<name> (or pnpm check:<name>), so package.json is the one definition. Where the inline copy differs from the package.json value today, the PR body says which one CI was actually enforcing.
  • Out of scope (ruled on docs: narrative cost — 42.5% of source lines are comments, workflows 58.6%, AGENTS.md is 103 KB with three stale claims, ROADMAP.md still says v3.3.2 and 80 Storybook stories #25919, 「存量不横扫」): rewriting the workflows' comment prose, including the stale counts at ci.yml:23 ("23 job-runs per PR event") and ci.yml:680,1557 ("two matrix jobs") — fix those two literals only if the step they annotate is touched.

Acceptance

  • No run: or github-script body in .github/workflows/ over 80 lines (the dev states the count before/after).
  • grep -c 'pnpm run check:\|pnpm check:' .github/workflows/*.yml rises by 16; the 16 inlined node scripts/… lines are gone.
  • Each new scripts/ci/*.mjs has --self-test wired where the other self-tests run (lint-repo-tooling lane).

Size: M (PR 1), S (PR 2). Clause-②: no. Metadata-protocol: none. Tier: H.

Related

#25919 (open, ruled A).

Activity

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — tooling · priority:p2 · domain:devx · area:devpath · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-26T12:10Z

    ⛔ Not a claim, ⛔ not a dispatch. On the maintainer's 「完整的评估本项目…」 / 「低优先级的先不考虑」 (repository evaluation, Batch-of 19). Low priorities were excluded at filing, so the execution cards grade p2.

    • Two mechanisms, two PRs, both Tier H (.github/**). Lift the inline scripts over 80 lines into scripts/ci/*.mjs with --self-test, and call the gates through pnpm run. The behaviour is unchanged: each moved script's self-test pins today's outputs.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 8 · 2026-10-27T00:34Z
    Session: session_01Q4MDXRbEJCNdPAP4SiXwp9 (devx seat 2) · card thread cmsg_01FdL1XeUyvVNxLreh3F4Qi95YovdFSHTxz132KjPG4TAa
    Account: os-steve
    Branch: claude/project-thread-y83svr (the harness-pinned branch of the card thread; it names no issue, so this claim is the identity record; amended on spawn)
    Worktree: objectstack-issue-26086
    Domain: domain:devx
    Seat: domain:devx#2 (seat post #20163)
    File surface: two serial PRs on one branch. PR 1 (Part of #26086): each inline run: / github-script body over ~80 lines moves to scripts/ci/<name>.mjs with a --self-test whose expected outputs are captured from the current inline body first (behaviour-preserving), and the YAML step becomes node scripts/ci/<name>.mjs; if the moved lines pass ~1,500, split PR 1 by workflow file. PR 2: the 16 inlined check:* command lines become pnpm run check:<name> so package.json is the one definition, and where the two copies differ today the PR body says which one CI enforced; PR 2 also carries #26091's Wanted 2 (the same mechanism, claimed there). ⛔ Workflow comment prose is not rewritten (#25919 「存量不横扫」); ⛔ no ui/ path (stop on breach; explain in the report). ⛔ Tier H: each PR is a draft until a GOVERNED_APPROVERS approval
    Container & model: L, mode:thread, model: default tier (TIER_DEFAULT, from dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — repository evaluation 2026-10-26, triaged p2 at 6415662358
    Thread-read: 6415662358
    Premise: the 20 inline bodies over 80 lines and the 16 inlined check:* command lines are still on main (the dev re-counts both first; #26294 changed merge-queue-triage.yml's body since filing)
    Serial constraints cleared: the ci.yml hold named in this seat's orders bound ui/ cards while #25869 and #25902 edited it; #25869 is closed and #25902 merged, and the only open PR touching ci.yml/lint.yml is #26367 (sdui, small hunks elsewhere). #26085 (this seat) adds timeout-minutes/concurrency to some of the same files at other lines; whichever lands second merges main


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26086,
      "status": "in_progress",
      "branch": "claude/project-thread-y83svr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26386",
      "session": "session_01ADHkmQq9EYQdTQwmRutQTS",
      "premise_still_valid": false,
      "summary": "PR 1 of 2 (Part of #26086). The premise holds for a minority of the volume: of 20 inline bodies over 80 lines (4,414 lines) on 6390fe52, about 2,870 lines are already executed or text-pinned by gates that read the YAML, and release.yml Guard/Render/Validate sit on a trust boundary. This PR moves the 3 bodies nothing reached (scheduled-full-run-card, test-nightly-tiers card, board-snapshot R2 upload; 404 lines) into scripts/ci with offline self-tests wired into lint-ci-engine. Whether to move the harnessed rest is a scope decision in front of Steve. PR 2 (pnpm run check:* and #26091 Wanted 2) follows after PR 1 merges.",
      "tests": "Behaviour capture vs inline bodies at 6390fe52: scheduled-full-run-card 7/7 identical full traces, nightly-tiers-card 7/7; R2 selftest passes against inline block and moved script; negative control (drop --delete) turns 2 checks red. Self-tests: '✓ nightly-tiers-card --self-test: 7 cases', scheduled-full-run-card 7 cases, '✓ board-snapshot-r2-upload self-test: 5 cases, 27 checks'.",
      "gates": "dispatch-gates --commands: 60 families; round 1 had 4 reds caused by this diff (check:bash32-floor, check-step-collectors and its --self-test, check:declared-population-live), fixed in b422bbdf; round 2 all 60 exit 0. --ran: '60 derived famil(ies) accounted for — 60 run, 0 NOT-MEASURED'. CI check-runs on the PR pending at report time.",
      "line_budget": "404 lines moved (card cap ~1500); diff vs base 9 files, +1348 / -410",
      "deviations": [
        "github-script steps keep their step and import the module (scheduled-full-run-card.yml precedent) instead of 'node scripts/ci/X.mjs'; seat accepted",
        "bash body moves to .sh + .selftest.sh, not .mjs",
        "scope reduced to the 3 unharnessed bodies pending Steve's decision; ci.yml waits for #26084, cut-rc.yml belongs to #26196",
        "module named nightly-tiers-card.mjs because .gitignore ignores test-*.mjs",
        "adoption lists in board-snapshot.yml and scripts/pm/board-snapshot.mjs changed FOUR to FIVE files (literal made false by the touched step)"
      ],
      "files_changed": [
        ".github/workflows/board-snapshot.yml",
        ".github/workflows/lint.yml",
        ".github/workflows/scheduled-full-run-card.yml",
        ".github/workflows/test-nightly-tiers.yml",
        "scripts/ci/board-snapshot-r2-upload.selftest.sh",
        "scripts/ci/board-snapshot-r2-upload.sh",
        "scripts/ci/nightly-tiers-card.mjs",
        "scripts/ci/scheduled-full-run-card.mjs",
        "scripts/pm/board-snapshot.mjs"
      ],
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "write_budget": "git push to claude/project-thread-y83svr; 1 relay pr_create (#26386, draft, assignee os-steve, label skip-changeset); 1 relay comment (this os-dev-report)",
      "mcp_calls": "7 — read-only: mcp__github__issue_read ×5, mcp__github__pull_request_read ×2; no write tool",
      "api_writes": "0 direct — all GitHub writes went through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches)",
      "open_questions": [
        {
          "question": "Should PR 1 also move the ~10 harnessed bodies?",
          "options": [
            "A: keep this scope; harnessed bodies stay where their gates read them",
            "B: move all per the card; rewrite ~10 harnesses and grant contents: read to jobs that hold none"
          ],
          "recommendation": "A, because moving buys no test reach and widens job permissions"
        }
      ],
      "out_of_scope_findings": [],
      "governed": "Tier H (.github/workflows/**): draft, not ready, no auto-merge; waits for a GOVERNED_APPROVERS approval (os-zhuang, hotlong)"
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    devx seat 2 · PR 1 landed: PR #26386 (Part of #26086) merged as 671df265, and its +/- lines on main match the reviewed head b422bbdf in all 9 files. The card stays pm:dispatched with the same card thread for PR 2 (pnpm run check:*, closing #26086 and #26091 W2). Whether the other 17 inline bodies over 80 lines also move waits on the maintainer's decision; PR 2 does not close this card while that is open.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26086,
      "status": "in_progress",
      "branch": "claude/project-thread-y83svr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26409",
      "session": "session_01ADHkmQq9EYQdTQwmRutQTS",
      "premise_still_valid": false,
      "summary": "PR 2 of #26086, also carrying #26091 Wanted 2; Part of both. Step census on main e677770a: 9 workflow steps inline a command byte-identical to a root check:* alias (the card counted 16; the other partial matches are different invocations, where CI enforces the inline form). 7 lint.yml steps now run pnpm check:NAME; the 2 left (check-links ADR links, board-snapshot self-test) sit in jobs deliberately built without pnpm. check-system-context-census's self-test wiring pin now pins the alias. Root check:* aliases with no caller: 11 -> 4 (three symbol-anchor aliases, pm-closed-card-sweep; their steps are split on purpose). #26091 also still lacks a --self-test for check-changeset-fixed.mjs, so neither card is closed by this PR.",
      "tests": "7 aliases run locally via pnpm -s check:NAME: all exit 0. check-system-context-census --self-test: all cases passed; negative control (lint.yml line removed) -> 'FAIL WIRING: lint.yml invokes this gate through its root alias'. pnpm exit-code passthrough checked with a script exiting 3 -> exit 3.",
      "gates": "dispatch-gates --commands: 56 families, all 56 exit 0 captured before any pipe; --ran: '56 derived famil(ies) accounted for — 56 run, 0 NOT-MEASURED'. CI check-runs on the PR pending at report time.",
      "line_budget": "+27 / -23 over 2 files (.github/workflows/lint.yml, scripts/check-system-context-census.mjs)",
      "deviations": [
        "7 replacements, not the card's 16: only 9 steps duplicate an alias exactly, and 2 of those are in no-pnpm jobs",
        "#26091 carried as Part of, not Fixes: 4 uncalled aliases remain (claim forbids removing or adding gates) and check-changeset-fixed.mjs --self-test is outside this claim",
        "two pointer comments ('Invoked as node rather than through a pnpm check:* alias') corrected because the touched steps made them false"
      ],
      "files_changed": [
        ".github/workflows/lint.yml",
        "scripts/check-system-context-census.mjs"
      ],
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "write_budget": "git push (branch recreated after PR 1 merge); 1 relay pr_create (#26409, draft, assignee os-steve, label skip-changeset); 2 relay comments (this report on #26086 and #26091)",
      "mcp_calls": "read-only since PR 1 report: mcp__github__issue_read x3, mcp__github__pull_request_read x2; no write tool",
      "api_writes": "0 direct — all GitHub writes through the fleet-write relay",
      "open_questions": [
        {
          "question": "How should #26091's last 4 uncalled aliases be settled?",
          "options": [
            "A: leave them as the local one-command form and accept them as callerless",
            "B: delete them (CI runs every leg directly)",
            "C: call them from CI and drop the split steps"
          ],
          "recommendation": "A, because the split steps are deliberate and the claim forbids removing gates; B needs a ruling"
        }
      ],
      "out_of_scope_findings": [
        "carrier: #26091 · --self-test for scripts/check-changeset-fixed.mjs still owed (deferred from Wanted 3)"
      ],
      "governed": "Tier H (.github/workflows/**): draft; waits for a GOVERNED_APPROVERS approval (os-zhuang, hotlong)"
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    devx seat 2 · PR 2 landed: PR #26409 (Part of #26086) merged as e0d63174, content matching the reviewed head 491624d2. With PR 1 (#26386), the three bodies no gate read are moved and the 7 byte-identical inline commands now run their alias. The card stays pm:dispatched with its card thread: whether the remaining 17 inline bodies over 80 lines also move is with the maintainer (decision card in the seat's thread). The card closes or goes on from that answer.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    devx seat 2 · released and closed. The maintainer ruled at 04:03Z (letter A, "move only the bodies no test battery reads"): the other 17 inline bodies over 80 lines stay inline, since each is either read byte-for-byte by an existing gate or sits on a trust boundary. The card's delivery is therefore complete:

    Both merges were content-checked against their reviewed heads. #26091's remaining items continue on that card (claim 6432932050).


    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

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:devxpriority:p2Medium: important, M3tooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions