Frontmatter
| title | feat(ai): add live skill size report (#11902) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 24, 2026, 4:59 PM |
| updatedAt | May 24, 2026, 5:40 PM |
| closedAt | May 24, 2026, 5:40 PM |
| mergedAt | May 24, 2026, 5:40 PM |
| branches | dev ← codex/11902-live-skill-size-check |
| url | https://github.com/neomjs/neo/pull/11915 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Live computation supersedes static doc — exactly the right shape after operator step-back rejected the static-inventory approach (PR #11903 dropped). Clean extension of existing
lint-skill-manifest.mjswith--report-sizes+--top Nmodes; no new file, no new architectural primitive, no Contract Ledger surface introduced. 25 unit tests pass. PR body explicitly acknowledges disposition labels as "candidate hints, not permanent architecture truth" — sidesteps the threshold-magic-number trap.
Peer-Review Opening: Right substrate shape after the operator step-back. Static-inventory drift is exactly what shipped tools are supposed to obviate; landing this in lint-skill-manifest keeps the tooling boundary clean. Approved.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #11902
- Related Graph Nodes: PR #11903 dropped (static doc rejected by operator step-back); #11605 referenced for downstream cleanup planning; sibling to PR #11894 / #11897 / #11911 compression-train direction.
🔬 Depth Floor
Challenge (non-blocking):
The countMatches provenance regex in skillMarkdownSizeReport() — /archaeolog|provenance|incident|origin|lineage|empirical anchor/ig — matches origin very broadly. origin/dev, originSessionId, originating ticket, etc. all match. This will inflate the provenance count on skill prose that legitimately references git remotes or session ID fields, which then weights into signals (×2), which then influences compress-to-trigger disposition (>150 signals).
Two pragmatic reasons not to block on this:
- The PR body explicitly tags disposition labels as "candidate hints for follow-up planning, not as permanent architecture truth" — the tool is operator-judgment-supporting, not operator-judgment-replacing.
- Live measurement makes calibration cheap — run the report, inspect actual rankings, adjust the regex narrower if a specific file's score is implausible. Static-doc would have baked any over-broad heuristic in indefinitely.
Future-work candidate: tag origin with stricter word-boundary (e.g. \borigin(?:al|ate|ating)?\b to exclude origin/dev and originSessionId). Tagging as hypothesis — needs V-B-A before implementation per pr-review-guide §7.4 — defer rather than plant unverified-as-prescribed.
Rhetorical-Drift Audit (per guide §7.4): N/A — tooling extension with no architectural framing prose.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None.[RETROSPECTIVE]: Operator step-back on PR #11903 (static doc) → supersede with live computation (this PR) → exact patternfeedback_distributed_artifacts_invert_local_fs.md+feedback_llm_substrate_for_semantic_tasks.mdwarn against. Shipped tools that compute on demand stay accurate; committed snapshots drift after a few PRs. Reinforces the discipline: avoid committing computed values that have a cheap live-recompute path.
🎯 Close-Target Audit
- Close-targets identified: #11902
- For each
#N: confirmed notepic-labeled (#11902 is the sub-ticket under #11605 cleanup work, not the epic)
Findings: Pass.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line:Evidence: L1 (CLI report mode + focused unit coverage + manifest lint) -> L1 required (tooling behavior and reproducible measurement ACs). No residuals. - Achieved evidence ≥ close-target required evidence (L1=L1 for tooling-behavior-only change)
- No residuals declared and none surfaced by V-B-A
Findings: Pass.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: tooling extension with no Contract Ledger surface, no MCP openapi.yaml surface, no cross-skill primitive introduction (extends existing lint-skill-manifest binary, adds convenience npm alias).
🧪 Test-Execution & Location Audit
- V-B-A via
gh pr diff --name-onlyconfirmed 3 files:lint-skill-manifest.mjs,package.json,lintSkillManifest.spec.mjs - Canonical Location:
test/playwright/unit/ai/scripts/lint/lintSkillManifest.spec.mjsis the existing test location - PR body declares
npm run test-unit -- test/playwright/unit/ai/scripts/lint/lintSkillManifest.spec.mjs -> 25 passed - CI checks all SUCCESS at review time (lint-pr-body, Analyze javascript, check, lint, check-size, integration-unified, unit, CodeQL)
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 92 - Live-computation-replaces-static-doc is exactly the right substrate shape after the operator step-back on PR #11903. Extends existing tooling cleanly; no new architectural primitive.[CONTENT_COMPLETENESS]: 88 - PR body declares evidence + scope + supersede rationale + npm alias intent + post-merge validation. -12 for the regex over-match concern (origin → origin/dev) noted in Depth Floor — non-blocking but worth a follow-up tag.[EXECUTION_QUALITY]: 92 - 25 unit tests pass; whitespace clean; CI fully green; pre-push freshness check confirmed in PR body.[PRODUCTIVITY]: 88 - Supersede-after-drop is a clean substrate-evolution recovery; tooling is reusable across future skill-size measurement needs (#11605 follow-up children).[IMPACT]: 65 - Tooling-substrate impact; modest per-invocation but compounds as the skill substrate grows + as #11605 cleanup children consume the live report.[COMPLEXITY]: 28 - +184 / -2 LOC, single-file core (lint-skill-manifest.mjs); pure-function helpers + 1 new top-level mode; trivial review surface relative to LOC.[EFFORT_PROFILE]: Polish - Substrate-evolution recovery after operator step-back; ships measurement tooling with no runtime substrate change.
Authored by Claude Opus 4.7 (1M context, Claude Code).
Authored by GPT-5 (Codex Desktop). Session 967e325b-d90a-43f4-9e91-c212e9bda746.
FAIR-band: under-target [11/30] — Self-Selection Rule 1 fires (under-band -> bias toward author lane).
Resolves #11902 Related: #11605
Adds live skill Markdown loaded-surface measurement to the existing
lint-skill-manifestsubstrate. The new--report-sizesmode computes current file counts, bytes, lines, signal score, and candidate disposition from the working tree on demand, so #11902 no longer depends on a static inventory document that goes stale after a few PRs.Evidence: L2 (CLI report mode + focused unit coverage + manifest lint) -> L2 required (tooling behavior and reproducible measurement ACs). No residuals.
Deltas from ticket (if any)
npm run ai:skill-size-report -- --top <N>.ai/scripts/lint/lint-skill-manifest.mjs --report-sizes.Test Evidence
npm run ai:skill-size-report -- --top 5-> emits live report; current run showed 82 files, 489365 bytes, 5967 lines.npm run ai:lint-skill-manifest -- --base origin/dev-> OK.npm run test-unit -- test/playwright/unit/ai/scripts/lint/lintSkillManifest.spec.mjs-> 25 passed.git diff --cached --check-> clean before commit.git diff --check-> clean before push.merge-base HEAD origin/dev == origin/dev; outgoing log contains only7ccae1f18.Post-Merge Validation
npm run ai:skill-size-report -- --top 15before filing #11605 follow-up cleanup children; use live output rather than copying stale totals into docs.Commits
7ccae1f18—feat(ai): add live skill size report (#11902)