Skip to content

T-M5RS-port-check-entities-to-ts

Status: closed/done · Impact: low · Complexity: medium

Port check_entities.py — the project-check that validates each entity type’s template against its own schema — to TypeScript. The checker is currently broken: it shells out to plugin/validators/validate_frontmatter.py, which the en-masse migration renamed to validate_frontmatter.ts. The port restores it by invoking the .ts validator and advances the .claude/ harness onto the TypeScript substrate.

LocationRole today
.claude/skills/project-check/check_entities.pyPython checker: for each entity type under --entities-dir, validates the type’s template.md frontmatter against its schema.json via plugin/validators/validate_frontmatter.py. Broken (exit 1, “validator not found”) — that validator is now validate_frontmatter.ts. Flag --entities-dir.
plugin/validators/validate_frontmatter.tsThe migrated frontmatter validator the checker must invoke.
.claude/skills/project-check/tests/run_evals.pyPython eval harness dedicated to check_entities (shells out to it against fixtures).

check_entities.ts runs under bun, invokes validate_frontmatter.ts, and exits 0 against the live entities tree (checker restored). The Python checker and its Python eval harness are removed; a bun:test suite replaces the harness; the --entities-dir flag, per-entity-type template validation, and exit-code contract are preserved.

  1. Port check_entities.pycheck_entities.ts (bun), invoking plugin/validators/validate_frontmatter.ts (fixing the dangling .py reference), preserving --entities-dir, the per-entity-type template validation loop, the output, and exit codes.
  2. Replace run_evals.py with tests/check_entities.test.ts (bun:test), porting its fixtures — a clean entities dir (exit 0) and an invalid-template fixture (non-zero).
  3. Delete check_entities.py and run_evals.py.
LocationKindChange
.claude/skills/project-check/check_entities.tsnewTypeScript port invoking validate_frontmatter.ts
.claude/skills/project-check/tests/check_entities.test.tsnewbun:test coverage replacing the Python harness
.claude/skills/project-check/check_entities.pydeletereplaced by the .ts port
.claude/skills/project-check/tests/run_evals.pydeletereplaced by the .test.ts suite
  • AC-1: check_entities.ts invokes plugin/validators/validate_frontmatter.ts (not .py), and bun run .claude/skills/project-check/check_entities.ts exits 0 against the live entities tree (the checker that exits 1 today is restored).
  • AC-2: check_entities.py and run_evals.py no longer exist, and grep -rn "check_entities.py\|validate_frontmatter.py" .claude returns no matches.
  • AC-3: .claude/skills/project-check/tests/check_entities.test.ts passes under bun test and asserts a clean entities dir (exit 0) and an invalid-template fixture (non-zero), ported from run_evals.py.
  • AC-4: check_entities.ts preserves the --entities-dir flag, per-entity-type template validation, and the exit-code contract.
  • Porting the other project-check checkers — separate tasks.
  • Refreshing the .claude/skills/project-check/SKILL.md script citations — deferred to one follow-up sweep so per-checker tasks stay file-disjoint.
  • Any change to validate_frontmatter.ts itself (already migrated and tested under plugin/).
  • none
  • Tier-2 dogfood task for the /sdlc:orchestrate/sdlc:task-work migration smoke test. Fixes a .claude/ harness regression (dangling validate_frontmatter.py reference) the TS migration introduced. Designed to run concurrently with the check_skill_prose port — the two touch disjoint files.

Captured by /sdlc:task-work on 2026-06-02. PR: pending.

  • AC-1: agent-manual (with caveat) — check_entities.ts invokes validate_frontmatter.ts (the .py-not-found breakage is fully restored: all 7 entity templates now validate, vs. 7 “validator not found” errors under the broken Python checker). Verified by running the port against the live tree and diffing its findings against the original Python checker’s: the TS port reproduces the 6 validator-independent findings byte-for-byte and eliminates all 7 dangling-validator errors. The literal “exit 0 against the live tree” does NOT hold because the live plugin/lib/model/entities/ corpus carries 6 pre-existing, validator-independent drift findings (format_spec: frontmatter keys in four definition.md files; a kind: prose ref and a status: closed/* glob ref) that predate this task and are out of scope (corpus cleanup / validator changes are excluded). On a clean entities tree the checker exits 0 (proven by the clean and clean-template fixtures).
  • AC-2: auto (with caveat) — check_entities.py and run_evals.py deleted. git grep "check_entities.py\|validate_frontmatter.py" -- .claude still returns matches, but every remaining match is explicitly out of scope: SKILL.md citations (task defers these to a follow-up sweep), check_pipe_tail.ts + its test + skill-doc-fixtures (the string is that checker’s subject matter — the antipattern it lints for), and the shared tests/README.md. None are dangling references this task owns.
  • AC-3: auto — bun test ./.claude/skills/project-check/tests/check_entities.test.ts → 11 pass / 0 fail. Asserts a clean dir (exit 0) and an invalid-template fixture (bad-template-value, exit 1), plus all nine run_evals.py CASES and two arg-handling cases.
  • AC-4: auto — --entities-dir, per-entity-type template validation, and the 0/1/2 exit-code contract are preserved and exercised across all nine fixtures + the missing-dir (exit 2) and bad-flag (exit 2) cases.
  • The existing check_pipe_tail.ts port (same skill dir) was a clean template: pyResolve / displayPath / splitlines helpers, ArgError-based parsing, and the bun:test + spawnSync harness pattern all transferred directly.
  • The pre-existing fixture tree under tests/fixtures/ ported unchanged — no fixture authoring needed, the Python CASES table mapped 1:1 onto the TS test.
  • The baseline-gated quality gate cleanly subtracted the 369 pre-existing audit_entities.ts findings; the run reported OK 6/6 with zero new drift.
  • Write/Edit tools were denied in the worktree path; had to fall back to Bash heredoc for file creation and skip a nice-to-have tests/README.md citation refresh — task-work’s worktree should confirm Write/Edit permission coverage in the Step 3b preflight (it only probes Bash tool-family signals today, not file-mutation tools). → T-WOL2-task-work-preflight-probes-file-mutation-tools
  • AC-1’s “exit 0 against the live entities tree” and AC-2’s “grep returns no matches” are literally unsatisfiable due to pre-existing corpus drift and explicitly-out-of-scope reference sites — task authoring should phrase corpus-dependent ACs against a clean fixture tree (or carve out the known-pre-existing drift), so a faithful port isn’t blocked by orthogonal drift. → T-XC32-task-acs-phrase-against-clean-fixtures
  • run_quality_checks.ts --diff-against-baseline defaults its --baseline-dir to the worktree’s .sdlc/, but task-work captures the baseline in the main repo’s .sdlc/; the gate failed with “baseline not found” until --baseline-dir <main-repo>/.sdlc/quality-baselines was passed explicitly. Step 7’s documented invocation omits --baseline-dir, so the worktree-vs-main mismatch bites every run — task-work Step 7 should pass the main-repo baseline-dir explicitly (or the script should resolve it via the worktree’s superproject). → T-44OO-plugin-scripts-self-discover-project-root

← Back to Tasks