Skip to content

[finding] sync-template-versions.mjs's GAP 1 note says Test Core is skipped in full for a diff confined to it — no longer true once the scripts filter lands #10016

Closed

Description

@claude

Blocked-by: #10014 (only becomes true when that PR lands)

Found while implementing #9829. Filed unassigned.

scripts/sync-template-versions.mjs's --self-test header argues the flag's existence from two
measured gaps. GAP 1 (lines ~376-401) reads:

GAP 1 — SCHEDULING. create-objectstack#test is reached only from ci.yml's test job, and that
job is if: ... needs.filter.outputs.core != 'false'. […] a diff confined to this file yields
core=false, so Test Core is skipped in full and the vitest never runs, on precisely the PR that
changes the rewriter.

PR #10014 changes the second half. core=false stays true — that filter is untouched — but the
test job now also gates on a new scripts filter output, so on a diff confined to this file the
job runs, --union-into runs inside it, and create-objectstack is pulled into the shard's package
set. Measured on that branch:

$ node scripts/check-cross-package-test-inputs.mjs --union-into ls.json --changed changed.txt
Cross-package scans pulled into this run because the diff touched their declared inputs:
  + @objectstack/spec  (declared glob matched scripts/sync-template-versions.mjs)
  + create-objectstack  (declared glob matched scripts/sync-template-versions.mjs)

So after that PR the paragraph states a scheduling fact that is no longer the case, in a header whose
whole job is to justify why the self-test lives in lint.yml. Same shape as #9651: a rationale
comment that stopped being true and would have the next reader re-derive the wrong conclusion.

What is NOT affected, and why the flag itself should stay: GAP 2 (the red paths — every failure
contract in the script's header, the clean-corpus control, the problems collection) is untouched,
and lint.yml carries no paths filter at all, so it still runs on every pull request, push and
merge-queue build. The fix is a comment edit — record that the scheduling half was closed and by
what — not a relocation of the self-test.

Deliberately not folded into #10014: that PR's diff is confined to .github/workflows/ci.yml under a
minimal-diff ruling, and editing this file would pull check:template-version-sync into its gate
set for a comment.

Refs: #9829, #10014, #9348 (the card that added the flag), #9651 (same class).


Generated by Claude Code


Generated by Claude Code

Activity

  1. claude commented on Aug 19, 2026

    @claude
    ContributorAuthor

    Claim: PM loop round 22
    Session: session_01XqDQYVU5smx29ts9pAErja
    Branch: claude/issue-10016-gap1-header-scheduling
    Worktree: objectstack-issue-10016
    Domain: domain:devx
    File surface: scripts/sync-template-versions.mjs (the GAP 1 header) (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (node scripts/pm/dispatch-gates.mjs --tier scripts/sync-template-versions.mjs — content limb no, comment prose only)
    Clause-②: no
    Serial constraints cleared: swept all open PRs for any touching sync-template-versions — none. UNBLOCKED: the Blocked-by PR #10014 (#9829) is now MERGED, which is precisely what makes this card's premise true — the header's scheduling claim stopped being accurate the moment that landed.


    Generated by Claude Code

  2. claude commented on Aug 19, 2026

    @claude
    ContributorAuthor
    {
      "issue": 10016,
      "status": "done",
      "branch": "claude/issue-10016-gap1-header-scheduling",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/10047",
      "premise_still_valid": true,
      "summary": "The GAP 1 header in scripts/sync-template-versions.mjs is rewritten to record that the scheduling gap CLOSED, with the mechanism attached, instead of asserting a fact ci.yml no longer supports. Both halves of the gap were measured separately per ruling 1, and BOTH turn out closed: (a) scheduling -- core=false still, but the test job now ORs in a second filter output (scripts: 'scripts/**'), so its if: resolves to RUN; (b) coverage -- the vitest that covers this script really does execute on such a diff, traced link by link and then confirmed end-to-end with turbo reporting 'Cached: 0 cached, 1 total'. The header therefore says GAP 1 no longer justifies the flag and GAP 2 (the red paths) carries it alone; it records GAP 1 rather than deleting it so the next reader does not re-derive the retired conclusion. Also corrected in the same paragraph: the header cited picomatch 4.0.5 as 'the matcher dorny/paths-filter uses' -- the action's own lockfile resolves 2.3.1. Diff is comment-only (48 insertions / 16 deletions, every changed line a // comment, verified mechanically); Clause-2 respected, no behaviour change, no changeset (skip-changeset label applied and read back).",
      "tests": "All at HEAD bf46ce42 (final commit). GATE UNION re-derived from the real changeset with `node scripts/pm/dispatch-gates.mjs` (no path args; it took the change set from merge base c1731d023 and named 1 path, 3 gate families). Gates, each quoted from its own verdict line, exit codes captured before any pipe: `pnpm check:template-version-sync` -> EXIT=0, '✓ sync-template-versions --self-test: 40 assertions over temp fixtures, running the real CLI.'; `pnpm check:cross-package-test-inputs` -> EXIT=0, 'All 52 self-test cases passed.' + 'OK: 12 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.'; `node scripts/check-cross-package-test-inputs.mjs` (the bare form ci.yml spells) -> EXIT=0, same OK line; `pnpm check:nul-bytes` -> EXIT=0, 'check-nul-bytes: OK (scanned 6358 text file(s) -- 6358 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).' H1 MEASUREMENT: parsed the filter YAML out of the merged .github/workflows/ci.yml (not transcribed) and evaluated it against changed=['scripts/sync-template-versions.mjs'] with picomatch 2.3.1 and {dot:true}, SOME quantifier, matching dorny/paths-filter@v4's createRuleItem -- 'picomatch version used: 2.3.1 / action: dorny/paths-filter@v4 / filter core => false (no packages/**, no examples/**, no apps/!(docs)/**, no package.json, no pnpm-lock.yaml, no tsconfig.json, no .github/workflows/ci.yml) / filter scripts => true (MATCH scripts/**)'. 2.3.1 is what dorny/paths-filter@v4's own package-lock.json resolves for picomatch (runtime, non-dev, ncc-bundled), fetched and read rather than recalled; the 4.0.5 in this tree agrees on these globs, cross-checked separately. So `!cancelled() && (core != 'false' || scripts != 'false')` = false || true = RUN. H2 TRACE (each link run, not inferred): `turbo ls --affected` with TURBO_SCM_BASE=origin/main -> 'packageCount: 0, items: []' on turbo 2.10.10, so the affected set alone tests nothing; `node scripts/check-cross-package-test-inputs.mjs --union-into ls.json --changed changed.txt` -> '+ @objectstack/spec  (declared glob matched scripts/sync-template-versions.mjs)' and '+ create-objectstack  (declared glob matched scripts/sync-template-versions.mjs)'; `node scripts/partition-test-shards.mjs ls.json --shard 2/3 --exclude @objectstack/dogfood` -> 'shard 2/3: 1/2 packages, weight 7' naming create-objectstack (spec lands on 1/3, 3/3 empty); turbo cache -- create-objectstack#test declares $TURBO_ROOT$/scripts/sync-template-versions.mjs in turbo.json, and `turbo run test --filter=create-objectstack --dry=json` gave hash fdb9dd70563b8fb5 at HEAD vs 9fa6c426413e2f96 with a one-line edit to that script, so no cached green can be replayed; create-objectstack's test script is a bare `vitest run` whose config includes src/**/*.test.ts. END-TO-END, the shard's own command under the shared verify lock (flock -E 99 -w 540 /tmp/os-heavy-verify.lock, acquired first try): `pnpm turbo run test --filter=create-objectstack --concurrency=2` -> '✓ src/template-version-stamps.test.ts (8 tests) 338ms', 'Test Files 7 passed (7)', 'Tests 81 passed (81)', 'Tasks: 1 successful, 1 total', 'Cached: 0 cached, 1 total'. That last line is the load-bearing one: the task executed rather than replaying cache. NO ABLATION was run -- this PR changes no executable line, so there is nothing whose removal could move a diagnostic; the reverse-verification here is the picomatch/filter evaluation itself, which was run against the merged workflow rather than against a claim. COMMENT-ONLY PROOF: `git diff -U0 | grep -E '^[+-]' | grep -v '^[+-][+-]' | grep -vE '^[+-]// ' | grep -vE '^[+-]//$'` matched nothing (exit 1); `node --check` passes; control-byte scan `grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]'` clean on the edited file and on the PR body.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #10045: .github/workflows/lint.yml (~536-556), the comment above the 'Template version-time rewriter self-test' step, is a second near-verbatim carrier of the SAME retired claim ('Test Core is skipped ENTIRELY ... and with it the vitest', '--union-into ... is a step inside the skipped job', 'The queue build catches it, one merge late') plus the same wrong picomatch version. Reported, not edited: ruling 3 reserves ci.yml and the gate wiring for the change that just landed there, and the claim's declared file surface is scripts/sync-template-versions.mjs.",
        "filed as #10046 (finding): check-cross-package-test-inputs.mjs's --union-into appends to packages.items but never updates packages.count, so the turbo-ls document it hands partition-test-shards.mjs contradicts itself (measured: count 0 alongside two items). Inert today -- partition-test-shards.mjs reads items and nothing in either script reads count -- but that document is the input to a shape assertion whose stated purpose is to stop a silently empty shard."
      ]
    }
    

    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions