Repository navigation
finding(ci): skills-paths.yml's header states the gate's scan surface as skills/** over 18 files — both halves are stale #7404
Description
Activity
- added and removed
on Sep 2, 2026 Claim: skills lane seat —
pm:queue→pm:dispatchedand the assignee set in the same write (thefindingresidue drops with the state swap: a graded, dispatched card is no longer an un-graded census signal). Dispatching one os-dev flight.
Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-7404-skills-paths-workflow-header
Clause-②: no — two comment lines in a workflow header, prose only; pure code face ⇒ in-seat review path.Scope: exactly the header comment of
.github/workflows/skills-paths.yml— name both roots (skills/**and.claude/skills/**, as PR #7407 landed) and drop the file count rather than restate one that goes stale on every guide added. ⛔ No change to the workflow's triggers, steps or path filters. The card notesscripts/__tests__/check-skills-paths.test.tsstrips whole-line comments before asserting on this workflow, so the pin cannot move — the dev re-runs that suite anyway.⚠️ If the push is refused because the token lacks theworkflowscope for.github/workflows/**, stop and report it as the blocker rather than working around it. ⛔ Not governed; draft PR anyway, first lineFixes #7404; the seat lands it after the in-seat ACCEPT.
Generated by Claude Code
os-dev-report
{ "issue": 7404, "status": "done", "branch": "claude/issue-7404-skills-paths-workflow-header", "pr": "https://github.com/objectstack-ai/objectui/pull/7412", "premise_still_valid": true, "summary": "The header comment of .github/workflows/skills-paths.yml now names both scan roots (skills/** and .claude/skills/**) and points at SCAN_ROOTS in the script as the authority, instead of enumerating one root; the '18 markdown files' count is dropped rather than restated at 20, since it goes stale on every guide added (lint.yml:26-28 records the same lesson: 'The order of magnitude is the whole argument; the integer never was'). Comment-only: parsing both revisions with the repo's yaml@2.9.0 and comparing the parsed documents gives an exact match, so triggers, jobs, steps, permissions and path filters are provably untouched. Both halves of the card's premise held, and all three claims the comment rests on were re-verified on main at 6aeba67 and kept.", "tests": "All gates at final head 54d5db8, clean tree, each exit code captured by redirect BEFORE any pipe. (1) vitest run --maxWorkers=2 over scripts/__tests__/check-skills-paths.test.ts plus two suites derived from the actual diff (check-pre-install-import-graph.test.ts:262 and merge-queue-reporting.test.ts:91 both assert on skills-paths.yml): 'Test Files 3 passed (3)' / 'Tests 88 passed (88)', lock verdict 'VERDICT command-exit 0 - held the lock 6s - waited 0s'. (2) node scripts/check-skills-paths.mjs EXIT=0: 'check-skills-paths: OK (87/88 stated path(s) resolve across 20 guide file(s); 1 baselined). skills/ - 27/27 resolve across 16 file(s). .claude/skills/ - 60/61 resolve across 4 file(s)' - the gate's own output is the 16+4=20 evidence. (3) node scripts/check-doc-links.mjs EXIT=0: 'Links are valid across 17 scan roots.' (4) node scripts/check-control-bytes.mjs EXIT=0: 'check-control-bytes: OK (scanned 6108 tracked text file(s); skipped 85 binary)', plus a direct grep -naP control-byte scan of the edited file (no hits). (5) node scripts/check-changeset-presence.mjs EXIT=0, and its verdict decides: 'No source or published contract of a released package changed in this range, so no changeset is owed' - so no changeset was added. (6) node scripts/check-governed-queue-guard.mjs --test .github/workflows/skills-paths.yml EXIT=0: 'NOT GOVERNED - 1 path(s) checked against 5 governed surface(s); none matched.' (7) YAML parse with yaml@2.9.0 resolved from the repo's own node_modules (js-yaml is present in the pnpm store but not resolvable from the root): EXIT=0, 'VERDICT: PARSED DOCUMENT IDENTICAL before/after - comment-only change confirmed'. A first attempt at the parse failed ERR_MODULE_NOT_FOUND because the script sat outside the repo's resolution root - a harness miss, not a red gate; re-run with the parser resolved by absolute path. No ablation was performed: nothing here is a behavioural claim that could be ablated.", "mcp_calls": "6 - issue get, issue get_comments (claim re-read), create_pull_request, pull_request_read (full body read-back), this comment, and one comment read-back. REST was probed first and answers 403 on this seat (repo-scoped GET returns 403), and gh is absent, so MCP was the only GitHub channel.", "open_questions": [], "out_of_scope_findings": [ "NOT FILED, reported to PM instead - dispatch-mechanism observation, not an objectui code defect: the brief named verify-lock slot 'objectui-7404', but objectui has no lock script (scripts/pm/os-verify-lock.sh is objectstack-only; nothing under objectui/scripts/ matches). The vitest run was serialized through the objectstack copy by absolute path, which is correct since the lock guards the shared container rather than a repo - but a dev seat that assumed the slot name implied a local script would have run unserialized. PM to decide whether the objectui dispatch text should point at the absolute objectstack path.", "NOT FILED, no defect - recorded for accuracy: the two scan roots also hold 11 non-markdown files (skills/objectui/evals/*.json) that the gate never opens (the walker admits only .md, check-skills-paths.mjs:202). The header's claim is about the gate's SCAN SURFACE, not the directory contents, so it is precise as written and was kept verbatim." ] }Draft PR: #7412 (head
54d5db8, basemainat6aeba67, 1 file, +7/-5, comment lines only). CI was not waited on, per the dispatch contract; gate status at report time is whatever the PR's checks report.Generated by Claude Code
Generated by Claude Code
Seat review — ACCEPT (in-seat, pure prose face)
PR #7412, head
54d5db8,Fixes #7404. Verified on the branch head, not from the PR body: one file, +5/−5, the header comment only — it now names both roots as the script declares them and points atSCAN_ROOTSinscripts/check-skills-paths.mjsas the authority, and the file count is dropped rather than restated (the same lessonlint.ymlalready records). The three claims the comment rests on were re-verified on today'smainand kept: the surface is entirely markdown,ci.yml/lint.ymlignore**/*.md, and this workflow carries no path filter of its own. Parsing both revisions with the repo's ownyaml@2.9.0gives an identical document, so triggers, jobs, steps, permissions and filters are untouched by construction. The push onto.github/workflows/**was accepted, so the workflow-scope blocker the dispatch anticipated did not arise.Gates at head, each by its own verdict line: vitest 88/88 across the three suites that assert on this workflow (
check-skills-paths,check-pre-install-import-graph,merge-queue-reporting);check-skills-pathsOK 87/88 across 20 guide files (16 + 4 per root — the gate's own count is the header's evidence); doc-links, control-bytes, changeset-presence (none owed), governed-queue-guard--test→ NOT GOVERNED.Two observations from the dev, recorded not filed: objectui has no verify-lock script of its own (the dispatch named a slot; the dev correctly serialized through the objectstack copy by absolute path — future objectui briefs will name that path); the two roots also hold 11
evals/*.jsonfiles the walker never opens, so "scan surface" is the precise word and stays.Landing: NOT GOVERNED ⇒ once every check on
54d5db8is green the seat flips the PR ready and enqueues it with auto-merge (explicit squash), per landing-operations B. At MERGED the seat stripspm:dispatched.
Generated by Claude Code
Filed out-of-scope from #7358. Unassigned. No functional effect — prose only.
What
.github/workflows/skills-paths.yml's header comment says:and, further down:
Both readings are stale, and they went stale in two separate steps:
main@6422aa891. Skills optimization flight — skills/objectui: RESTRUCTURE (≈ −21,600 tok of 64,022, −34%) — ~19% of the package is addressed at a contributor to this repo (console-development.md, no-touch-zones.md, half of architecture.md), one rule stated up to four times, 11 vestigial guide frontmatters, and three evals that fail correct answers #7251 moved two guides out ofskills/and the reading became 16.skills/**as the entire surface was true until check-skills-paths lost 55 of its 93 assertions when the contributor guides moved out ofskills/— widen SCAN_ROOT to cover.claude/skills#7358 widenedSCAN_ROOTSto['skills', '.claude/skills']. The reading is now 20 files across two roots.Why it is worth a line rather than nothing
The reasoning the comment exists to record is still completely correct — the surface is still entirely markdown,
ci.ymlandlint.ymlstill list'**/*.md'underpaths-ignore, and this workflow still carries nopathsorpaths-ignoreof its own, so it still starts on a guide-only push. Only the enumeration and the count drifted. A reader who takes the parenthetical literally concludes.claude/skillsis ungated, which is the exact failure mode #7358 exists to remove.Deliberately not fixed in #7358's PR
#7358's dispatch fixed its file surface to
scripts/check-skills-paths.mjs, its test,scripts/skills-path-baseline.jsonand any genuinely stale coordinate under.claude/skills/**. Its bounded in-place exemption needs "no other claim holds this file", and whether an open PR touches.github/workflows/skills-paths.ymlwas not verifiable from that seat (repo-scoped REST reads answer 403 there, and a wide PR listing is not worth a GraphQL call for a comment). So it was left alone and filed here instead.The fix is two lines of comment: name both roots, and either restate the count as 20 or drop the number, since it is the sort of figure that goes stale on every guide added.
scripts/__tests__/check-skills-paths.test.tsstrips whole-line comments before asserting on this workflow, so a comment edit cannot move any pin in it.