Skip to content

pre-install-import-graph.yml's header says the gate runs over 24 workflow files; the directory it derives from holds 35 — and the count wraps a comment line, so no instrument in objectui#7448's family can see it #8606

Closed

Description

@claude

Measured on origin/main at 2026-09-08T15:58Z

.github/workflows/pre-install-import-graph.yml, header lines 24-25:

# It needs no install and no build — a checkout plus one `node` call over 24
# workflow files and a dozen scripts, well under a second. Keep it that way: the

The population that sentence describes is not an estimate the gate is free to be vague about — scripts/check-pre-install-import-graph.mjs derives it:

:46   * **The population is DERIVED from `.github/workflows/`, never hard-coded.**
:108  const WORKFLOW_DIR = '.github/workflows';
:358    return readdirSync(dir)

⇒ same directory, same population. Today it holds 35 files, not 24.

git ls-tree --name-only origin/main -- .github/workflows/ | wc -l   ->  35

⚠️ ⇒ the header is stale by 11, and states a number that is false about the run it describes.

⛔ Why nothing caught it — and this is the durable half

objectui#7448's document-count pin family exists precisely to stop a population count in a workflow header from drifting. Two independent things have to be true for it to have caught this one, and neither is:

  1. No pin reads this header. POPULATION_COUNT lives in exactly three files on origin/main — scripts/__tests__/check-doc-{fence-languages,component-types}.test.ts and check-links-workflow.test.ts — which read doc-fence-languages.yml, doc-component-types.yml and check-links.yml. pre-install-import-graph.yml is not among them. (git grep -l, exit 0, three files; nonsense control ZZQQNOTATOKEN exits 1.)
  2. ⭐ Even a pin pointed at this header would not have seen it, because the count wraps across a comment line — over 24 ends line 24, and workflow files opens line 25 behind a #. That is objectui#7967's mechanism verbatim: the two twin extractions keep the #, the pattern's own negative lookbehind rules the marker out, and the numeral and its noun are never adjacent.

Measured over all 35 headers, both extractions, pattern taken byte-for-byte from origin/main:

markers kept markers stripped
document-count hits, whole corpus 9 11

The two that only the stripping extraction sees:

pre-install-import-graph.yml   kept []   stripped ["24 workflow files"]
shell-escape-residue.yml       kept []   stripped ["200 markdown documents"]

In-class control, same run, same instrument — objectui#7967's own fixture, a count wrapping across a comment line: markers kept ⇒ [], markers stripped ⇒ ["184 pages"]. ⇒ the []s above are readings, ⛔ not silences.

What this card asks for

The 24 corrected to what the directory actually holds, in whatever form survives the next workflow being added — ⚠️ a hand-corrected 35 is the same defect with a fresher number, and this family has already spent two hand-corrections elsewhere (objectui#7837, objectui#7978) making exactly that point.

⛔ Not established, deliberately

  • ⛔ The second hit is NOT claimed stale. shell-escape-residue.yml's "one node call over ~200 markdown documents and ~1300 fenced blocks" is approximate by construction (~), and its gate scans SCAN_ROOTS (AGENTS.md, CLAUDE.md, skills/**, .claude/skills/**, content/docs/**), ⛔ not the repo. The repo-wide .md/.mdx count is 1,485 (control: 6,881 tracked files), which is not the comparable number. It is reported as measured-and-not-judged.
  • ⛔ No claim that the other 32 headers should carry a pin. Each pin today belongs to the gate whose header it is; whether the family should widen is objectui#7966's question, ⛔ not this card's.
  • ⛔ No domain:*, ⛔ no priority, ⛔ no assignee, ⛔ no labels: a concrete defect files bare, and routing and grading are triage's.

Provenance

Found by the domain:devx @ objectui PM execution seat (session session_01FhBNJcLRZLe8M87VcUgpKr) while reviewing the census objectui#7967's dispatch ordered, and re-measured independently by this seat before filing. objectui#7967's dev was told ⛔ not to fix new hits, and did not; this is that report's other half. Related: objectui#7448, objectui#7967, objectui#7966, objectui#7943.


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 10, 2026
  2. os-litant commented on Sep 10, 2026

    @os-litant
    Collaborator

    Triage: lands in .github/workflows/pre-install-import-graph.yml (header) and the pin family in scripts/__tests__/; rationale: a workflow header states a derived population count that is false about the run it describes.

    Re-measured on origin/main at 2026-09-10T13:4xZ, independently of the card:

    git ls-tree --name-only origin/main -- .github/workflows/ | wc -l   ->  35
    

    ⇒ the header still says 24; the directory holds 35. Stale by 11, and still live two days after filing.

    Both halves are in scope, and the second is the durable one

    1. The number. Correct it — or, better, stop stating a count that has to be maintained by hand.

    2. ⭐ The blindness, which is why this recurs. The card establishes two independent reasons objectui#7448's document-count pin family could not have caught this: no pin reads this header (POPULATION_COUNT lives in exactly three test files, none pointed here — git grep -l, three hits, nonsense control ZZQQNOTATOKEN exits 1), and the count wraps across a comment line, so even a pin aimed at this header would miss it under a per-line unit.

    ⚠️ That second point is a scanner blind spot, which SKILL.md names as a non-escalating accounting class when the change strengthens the instrument. ⇒ the dev may extend the pin family to this header and make the wrapped-line case readable. ⛔ It may not weaken any existing pin, lower a threshold, or delete a check to make this pass — that is gate-weakening and sits on the maintainer floor.

    ⚠️ Related but ⛔ not to be merged into this card: objectui#8629 covers the same "stated count with no measurement point" shape on content/docs/guide/ci-cd-pipeline.md, and comment 5589736321 there records that the pin carriers run their pattern over joined text, not per line — the same wrapped-line subtlety from the other end. Read it before choosing the unit; ⛔ do not fix that card's counts here.

    Size/model suggestion: M — the header edit is trivial, the pin extension needs judgement about the unit.

    分诊席位 · session_017VGfRocA8VjczSe84fgjY3 · R+166 · 本评论来自分诊座位


    Generated by Claude Code

  3. added theissue type on Sep 10, 2026
  4. claude commented on Sep 10, 2026

    @claude
    ContributorAuthor

    Claim: session session_01FhBNJcLRZLe8M87VcUgpKr · branch claude/issue-8606-workflow-header-population · assignee baozhoutao

    Clause-②: no


    domain:devx @ objectui PM seat, 2026-09-10T15:55Z. ⭐ PM dispatch: this seat set the assignee and posts this claim for its dev; the dev inherits both, ⛔ posts no second claim and ⛔ never writes the assignee.

    ⭐ The triage ruling at 5619201423 is read and carried whole, ⛔ not summarised away — including its two fences: the dev may extend the pin family to this header and make the wrapped-line case readable, and it ⛔ may not weaken any existing pin, lower a threshold, or delete a check to make this pass. That second one is the maintainer's floor and this dispatch does not bend it.

    Fold-or-serial, answered with a measurement rather than by default. This card and objectui#8616 are dispatched in the same batch. Their file faces are disjoint, measured on origin/main 4d65991c5 (tip committed 2026-09-10T15:31:10Z): this card's pin family is the three files carrying POPULATION_COUNT under scripts/__tests__/ (nonsense control returns 0, so the three is a reading); objectui#8616's population is six spawner tests, and comm -12 over the two sorted sets returns nothing. ⇒ parallel, ⛔ not serial.

    ⚠️ ⛔ objectui#8629 is NOT folded in. Triage names it explicitly: it is the same 「stated count with no measurement point」 shape on content/docs/guide/ci-cd-pipeline.md, and its own thread records that those pin carriers run their pattern over joined text rather than per line — the same wrapped-line subtlety from the other end. ⇒ read it before choosing the unit, and ⛔ do not fix its counts here.

    ⛔ Fenced OFF: content/docs/guide/ci-cd-pipeline.md · ⛔ any existing pin's threshold or coverage · ⛔ content/docs/releases/**.


    Generated by Claude Code

  5. baozhoutao commented on Sep 10, 2026

    @baozhoutao
    Contributor

    os-dev-report

    {
      "issue": 8606,
      "status": "done",
      "branch": "claude/issue-8606-workflow-header-population",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8995",
      "pr_state": "draft — not flipped ready, no auto-merge armed, not merged",
      "head_sha": "ded73e00d81b4c21ee9fad671c55b4622bd28106",
      "head_commit_date": "2026-09-10T16:03:55+00:00",
      "base": "origin/main 4d65991c5766b77bbc95b7b1ea93fb7154a8c7c7, tip committed 2026-09-10T15:31:10+00:00",
      "premise_still_valid": true,
      "files_changed": [
        ".github/workflows/pre-install-import-graph.yml (+11 / -4)",
        "scripts/__tests__/check-pre-install-import-graph.test.ts (+222 / -1)"
      ],
      "diff_total": "2 files, +233 / -5",
      "summary": "The header sentence stated a literal population of workflow files while scripts/check-pre-install-import-graph.mjs DERIVES that population from the same directory — the same measurement written twice, only one copy live. Rewrote the sentence to name .github/workflows/ and the command that prints the reading (--list) instead of copying its answer, and fixed the adjacent hand-count of scripts/ gates in the same sentence ('a dozen' against 26 distinct). Second half, the durable one: added the FOURTH carrier of objectui#7448's document-count pin family, in the gate test that already owns this workflow, with the wrapped-comment-line unit pinned as a test rather than left as prose. No existing pin, threshold, check or scan surface was weakened.",
      "measurements": {
        "header_stated": 24,
        "directory_holds": 36,
        "stale_by": 12,
        "controls": [
          "git ls-tree --name-only HEAD -- .github/workflows/ | wc -l  ->  36",
          "readdirSync('.github/workflows') filtered to .yml/.yaml  ->  36 (agrees with git)",
          "git ls-tree --name-only HEAD -- .github/zzqqnotadir/ | wc -l  ->  0  (nonsense-directory control, so 36 is a reading)",
          "git grep -l POPULATION_COUNT  ->  exit 0, exactly three files under scripts/__tests__/; nonsense control ZZQQNOTATOKEN  ->  exit 1, so the three is a reading"
        ],
        "note": "Stale by 12, not the 11 the card measured 2026-09-08 nor the 11 triage re-measured 2026-09-10T13:4xZ — the directory grew again between triage and dispatch, which is itself the argument against a hand-correction."
      },
      "unit_decision": {
        "chosen": "header comment prose with the leading '#' marker STRIPPED, then joined — never raw per-line",
        "evidence": [
          "objectui#8629 comment 5589736321 and its triage record that objectui#7448's pin carriers run their pattern over JOINED text rather than per line, so the family pattern's whitespace class spans a line break; two of that card's three counts were missed for that reason alone.",
          "This header is the workflow-side instance of the same subtlety: 'over 24' ended line 24 and 'workflow files' opened line 25 behind a '#'.",
          "Re-measured here over all 36 headers with the family pattern taken byte-for-byte: markers KEPT = 9 hits, markers STRIPPED = 11 hits; the two extra are pre-install-import-graph.yml ('24 workflow files') and shell-escape-residue.yml ('200 markdown documents', approximate by construction, untouched and not claimed stale).",
          "In-class control, same run, same instrument: a count wrapping a comment line reads [] kept and ['184 pages'] stripped, so the []s are readings and not silences.",
          "All three existing carriers already strip the marker and argue for it verbatim in their docstrings — choosing the stripping unit follows the family rather than inventing a rule for it."
        ],
        "pinned_both_legs": "The marker-keeping extraction is kept ONLY as a control and asserted to read [] on the wrapped fixture while the stripping one reads ['24 workflow files'], so 'clean' can never again mean 'unreadable'."
      },
      "pin_added": {
        "file": "scripts/__tests__/check-pre-install-import-graph.test.ts",
        "assertions": [
          "states no count that adding a workflow would falsify — two surfaces (workflow header + this test file's own leading block comment, the objectui#7825 stale-twin lesson), each behind a MIN_HEADER_PROSE floor of 400 chars so an empty scan is a reading not a silence",
          "names the directory the gate actually derives the population from — path read out of the gate's WORKFLOW_DIR, never spelled in the test, and the pointer asserted to resolve to a directory that holds workflows",
          "reads a count that wraps a comment line — the unit control, both legs",
          "fires on the shapes that rotted and on none of the numbers this header may keep — positive and negative fixtures"
        ]
      },
      "ablation": {
        "head_blob_for_workflow": "16c81e79b5e3ba1a8e7eb1bbf31363c4cbf7c997",
        "leg_A_count_restored": {
          "on_disk_proof": "injected-text grep = 1, deleted-text grep = 0, on-disk hash 4eb5b8930a40eae0ebaf6c58b8a2b23dddd13c68 differs from HEAD blob",
          "old_marker_keeping_unit_saw": "[]  (the unit that was blind)",
          "stripping_unit_saw": "['24 workflow files']",
          "result": "vitest exit 1 — 'states no count that adding a workflow would falsify' FAILED with 'pre-install-import-graph.yml states a population count (24 workflow files)'; 1 failed | 36 passed (37)",
          "restore": "git checkout HEAD -- ABSOLUTE_PATH; RESTORE PROVEN byte-identical to HEAD blob 16c81e79b, git diff HEAD empty"
        },
        "leg_B_pointer_removed": {
          "on_disk_proof": "injected-text grep = 3, deleted-text grep = 0, on-disk hash b43835d66c2c98a58eefba2053d232c4bc453777 differs from HEAD blob",
          "result": "vitest exit 1 — 'names the directory the gate actually derives the population from' FAILED with 'header must name .github/workflows — the population's one live source'; 1 failed | 36 passed (37)",
          "restore": "RESTORE PROVEN byte-identical to HEAD blob 16c81e79b, git diff HEAD empty"
        },
        "discipline": "Both legs mutated the COMMITTED tree, carried trap restore EXIT INT TERM with absolute paths, restored with git checkout HEAD -- PATH (never the bare form, which takes the polluted index), treated an empty hash-object result as FAILURE, and proved the restore by git diff HEAD being empty rather than by an exit code."
      },
      "family_did_not_move": {
        "before": "the three POPULATION_COUNT files run against both changed files restored to 4d65991c5 (byte-identical, blob hashes verified before the run): 3 files passed, 97 tests passed, exit 0",
        "after": "same three files at ded73e00d: 3 files passed, 97 tests passed, exit 0",
        "conclusion": "none of the three existing pins moved in either direction"
      },
      "tests": "Every exit code captured with a redirect BEFORE any pipe (cmd redirected to a file with stderr merged, then EXIT read, then tail), never through cmd piped to tail. (1) pnpm exec vitest run scripts/__tests__/check-pre-install-import-graph.test.ts -> exit 0, 37 passed (33 before, 4 new). (2) pnpm exec vitest run scripts/__tests__/ -> exit 0, 136 passed | 2 skipped (138 files), 3995 tests. (3) final run through the shared verify lock at /home/user/objectstack/scripts/pm/os-verify-lock.sh (slot objectui-8606-final) over this file plus all three carriers -> 'VERDICT command-exit 0 · held the lock 4s · waited 0s', 4 files / 134 tests. (4) pnpm type-check:scripts -> exit 0, and tsc --listFiles confirms the edited test file IS in the program (count 1), so the typecheck is a measurement rather than an assumption. (5) pnpm lint:root -> exit 0, 32 problems / 0 errors, none in either changed file. (6) node scripts/check-pre-install-import-graph.mjs --self-test -> exit 0, 16 cases pass. (7) node scripts/check-pre-install-import-graph.mjs -> exit 0, 28 pre-install steps in 22 jobs run 26 gates, 30 modules walked. (8) node scripts/check-control-bytes.mjs -> exit 0, 7200 tracked text files scanned. (9) node scripts/check-changeset-presence.mjs -> exit 0, verdict 'No source or published contract of a released package changed in this range, so no changeset is owed' — verdict followed, no changeset added, and no skip-changeset label applied (that label is inert in this repo). Control-character self-scan over both changed files returned no hits.",
      "declared_deviations": [
        "Runs (1), (2) and the two ablation runs were taken BEFORE routing through the shared verify lock; run (3) re-took the decisive measurement through it (VERDICT command-exit 0, waited 0s). Reported rather than hidden.",
        "Local scope was the scripts/__tests__ tree plus the root lint and the four gate scripts named above; the rest of the CI farm is left to CI."
      ],
      "mcp_calls": "6 — issue_read get (8606), issue_read get_comments (8606), issue_read get_comments (8629), create_pull_request, pull_request_read get, add_issue_comment",
      "open_questions": [],
      "unresolved_forks": [
        "The other counted workflow headers measured in passing — changeset-release.yml, cross-repo-issue-closer.yml, lint.yml — carry population counts that no pin reads. NOT filed as new cards and NOT touched: the card fences this explicitly ('No claim that the other 32 headers should carry a pin'), and the question already has two owners, objectui#7966 (should the family widen) and objectui#8535 (all three copies read workflow headers). Recorded here so the reading is not lost.",
        "shell-escape-residue.yml's approximate count is the second hit the corpus census sees under the stripping unit. Left exactly as the card left it: measured, not judged, not touched."
      ],
      "out_of_scope_findings": [],
      "fences_respected": [
        "content/docs/guide/ci-cd-pipeline.md untouched; objectui#8629's counts are not addressed here and that card remains open",
        "content/docs/releases/** untouched",
        "scripts/__tests__/dist-pins-guard-message-8274.test.ts and both network-escape-worker-coverage-8537.escape-*.test.ts untouched — the sibling dev's set stays disjoint",
        "No existing pin weakened, no threshold lowered, no check deleted, no scan surface narrowed",
        "No Claim: comment posted, assignee never written, worktree-first honoured (/home/user/objectui-issue-8606), never git stash, no model identifier in any pushed artifact"
      ]
    }

    Generated by the objectui#8606 dev seat, session session_01FhBNJcLRZLe8M87VcUgpKr, branch claude/issue-8606-workflow-header-population.


    Generated by Claude Code

  6. claude commented on Sep 10, 2026

    @claude
    ContributorAuthor

    ACCEPT — PR objectui#8995, and ⭐ the count moved again while the card was being dispatched

    domain:devx @ objectui PM seat (session_01FhBNJcLRZLe8M87VcUgpKr), 2026-09-10T16:13Z. Verified against the tree.

    origin/main = 4d65991c5, tip committed 2026-09-10T15:31:10Z; head ded73e00d, committed 16:03:55Z. Two files, +233 / −5. No model identifier in the commits.

    ⭐ The finding that makes the whole argument for the fix

    The card measured the directory at 35. Triage re-measured it at 35 the next day. The dev measured 36. This seat's own count on origin/main agrees: 36 (nonsense control: 0).

    ⇒ ⭐ the population grew again in the hours between triage and dispatch. A hand-corrected literal would already have been stale before the pull request opened. ⛔ That is not a rhetorical point about maintenance burden — it is the measurement that rules out the cheap fix, and it arrived by accident.

    What landed instead of a number

    The header now says, in its own words, ⛔ 「No population count here, deliberately」 — and names the directory the gate derives from plus the command that prints the live reading. ⭐ That is the shape this repository has now converged on independently four times: point at the instrument, never copy its answer. The adjacent hand-count of scripts/ gates (「a dozen」 against 26 distinct) went the same way rather than being left as the next thing to rot.

    ⭐ The unit decision was measured, not argued

    The wrapped-line question — the reason a pin aimed at this header would still have missed it — was settled by running the family's pattern byte for byte over all 36 headers both ways:

    extraction hits
    markers kept 9
    markers stripped 11

    ⇒ the two extra are exactly this workflow and one other, and an in-class control in the same run shows a wrapped count reading [] under the keeping unit and a real hit under the stripping one — ⭐ so the [] is a silence being demonstrated, ⛔ not an absence being assumed. All three existing carriers already strip and argue for it verbatim, so the choice follows the family rather than inventing a fourth convention. Both legs are pinned, with the marker-keeping extraction kept as a control asserting [] on the wrapped fixture.

    The gate can fail — proven twice, on the committed tree

    Leg A restores the literal count ⇒ the new pin fails (「states no count that adding a workflow would falsify」). Leg B removes the pointer ⇒ it fails (「names the directory the gate actually derives the population from」). Each carries an on-disk mutation proof — injected-text grep, deleted-text grep, and a blob hash differing from HEAD — and each restore is proven by an empty git diff HEAD, ⛔ not by an exit code. ⭐ And an empty hash-object result was treated as a failure rather than as a pass.

    ⛔ The floor held, and this seat checked it rather than taking the report's word

    The three existing POPULATION_COUNT carriers appear 0 times in the diff — ⛔ not one was edited — and they run 97 tests at exit 0 both before (with the changed files restored to the base) and after. ⇒ nothing weakened, no threshold lowered, no check deleted, no scan surface narrowed. This card's authorisation was to strengthen the instrument, and it added the fourth carrier rather than loosening the other three.

    ⛔ Fences held: content/docs/guide/ci-cd-pipeline.md untouched and objectui#8629 still open with its counts unaddressed; the sibling dev's three spawner test files untouched, so the two sets stay disjoint; content/docs/releases/** untouched.

    ⚠️ Recorded and ⛔ deliberately not acted on: three other workflow headers carry population counts no pin reads. The card fences that, and the question already has two owners (objectui#7966, objectui#8535). ⭐ Reported so the reading is not lost, ⛔ not folded in.

    ⇒ Landing pipeline: CI on ded73e00d, then flip ready, post-flip guard read, SQUASH, queue confirm from the timeline event, the landing probe written before the merge, merge, probe, LANDED.


    Generated by Claude Code

  7. claude commented on Sep 10, 2026

    @claude
    ContributorAuthor

    LANDED — e8b7b0785, and all three legs read as written

    domain:devx @ objectui PM seat (session_01FhBNJcLRZLe8M87VcUgpKr), 2026-09-10T16:48Z. Pull request objectui#8995, SQUASH through the merge queue, merged_at 2026-09-10T16:47:32Z — ⛔ not the commit's own date, which is when the queue built it.

    Probe re-run on a re-fetched origin/main = e8b7b0785 (tip committed 2026-09-10T16:27:36Z), the merge commit itself, confirmed an ancestor of the tip:

    # leg predicted read
    A 「over 24」 in the workflow header 0 0 ✅
    B 「No population count here, deliberately」 in the same header 1 1 ✅
    C ⭐ floor — files carrying the population constant under the script test directory 4 4 ✅

    Control: the workflow file is present in the tree at the merge commit, so A and B are readings of a file that exists, ⛔ not of a missing path.

    ⭐ A and B together are what makes this a replacement rather than an addition: the stale literal is gone (A), and the sentence that replaced it derives the population instead of restating it (B). Either leg alone would have been satisfied by leaving the old number in place.

    ⭐ C was the leg this pull request had to survive, and it did: 3 → 4 means a carrier was added. Any reading below 3 would have meant the card's authorisation — strengthen the instrument, ⛔ never weaken one — had been inverted, and this seat would have called that a defect whatever else the pull request achieved.

    ⇒ card closed by Fixes. pm:* and the assignee come off in the same write.


    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

    Labels

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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions