Skip to content

test(scripts): guard that dispatcher entrypoints are tracked executable#409

Merged
aleskalfas merged 1 commit into
mainfrom
test/405-ci-guard-assert-dispatcher-entrypoint
Jul 1, 2026
Merged

test(scripts): guard that dispatcher entrypoints are tracked executable#409
aleskalfas merged 1 commit into
mainfrom
test/405-ci-guard-assert-dispatcher-entrypoint

Conversation

@aleskalfas

Copy link
Copy Markdown
Owner

What

A repo-wide CI guard (tests/test_entrypoint_exec_bit.py) that asserts every dispatcher entrypoint script is git-tracked executable (100755), so the #402 defect class can't recur: a 100644 entrypoint raises PermissionError through the dispatcher's subprocess.run([script_path, ...]) and the verb silently can't run.

  • Core guard — enumerates every git-tracked .pkit/**/scripts/*.py carrying the #!/usr/bin/env -S uv run --script shebang, reads its git-tracked mode via git ls-files -s, and asserts 100755. On failure it names every offender with the remedy chmod +x <path> && git add <path>.
  • Enumeration-drift guard — asserts known entrypoints (check-doc-mapping.py, adopt-existing.py, set-field.py, create-issue.py) are discovered, so the exec-bit check can't pass vacuously on a broken scan.
  • Unit coverage — the mode parser against 100755 / synthetic 100644 inputs and the shebang discriminant, exercising the failure path without mutating any real file.

Design notes

  • Discriminator = the shebang, verified against the tree: no scripts/_lib/ module (nor any non-entrypoint scripts/*.py) carries the uv-script shebang, so libs are excluded naturally and a new entrypoint anywhere under .pkit/**/scripts/ is covered automatically.
  • Git-tracked mode, not filesystem stat — asserts what ships to a fresh clone (the mode that actually caused [Bug] Restore executable bit on check-doc-mapping and adopt-existing dispatcher scripts #402), which a local chmod can't mask.

Verification

  • New test in isolation: 7 pass. Full suite: 4144 pass.
  • Enumeration sanity: 60 entrypoints found, all 100755; 30 non-entrypoint scripts/*.py correctly excluded.
  • Negative check: flipping an entrypoint's index mode to 100644 (working tree untouched) makes the guard fail, name the offender, and print the remedy; restored, tree clean.
  • ruff / pyright clean; pkit migrations check-diff --include-working-tree --base main — no trigger (pure addition).

Version / migration

Test-only addition — not a surface change per PRJ-002 (no new CLI command/flag/principle/schema/adopter-facing convention; tests project-kit's own tree). No version bump, no migration.

Doc impact

  • None — the asserted invariant ("dispatcher entrypoints are tracked 100755") is internal to project-kit's own scripts; the test module docstring documents the rule and rationale. Not an adopter-facing convention, so no COR/PRJ record.

Test plan

Closes #405

🤖 Generated with Claude Code

Repo-wide CI guard: enumerates every git-tracked .pkit/**/scripts/*.py carrying
the uv-script shebang and asserts each is tracked 100755, so a dispatcher
entrypoint can never ship unrunnable again (the #402 defect class — a 100644
entrypoint raises PermissionError through subprocess.run). Keys on the shebang
so _lib modules and other non-entrypoints are excluded; asserts the git-tracked
mode (what ships to a fresh clone), not the local filesystem stat. Includes an
enumeration-drift guard so the exec-bit check can't pass vacuously, plus unit
coverage of the mode parser's failure path against synthetic input.

Test-only addition; no surface change, no version bump, no migration.

Closes #405

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@aleskalfas

Copy link
Copy Markdown
Owner Author

Reviewer agent (local, reviewer): APPROVED

  • Branch shapetest/405-ci-guard-assert-dispatcher-entrypoint matches <conv-type>/<issue-number>-<slug> ([project-management:DEC-013-branch-and-pr-conventions], git-conventions.yaml branch-name). pass.
  • Branch-type / issue-type alignment — closing issue [Test] CI guard: assert dispatcher entrypoint scripts are tracked executable #405 is type:test, which maps to conv-type test (classification.yaml pr_type_mapping); the branch's test/ segment agrees. pass.
  • PR title Conventional Commitstest(scripts): … parses as <type>(<scope>): <description> with test in the accepted list ([COR-008] + git-conventions.yaml). pass.
  • PR title type matches issue typetest derives from type:test per pr_type_mapping. pass.
  • Issue classification complete[Test] CI guard: assert dispatcher entrypoint scripts are tracked executable #405 carries type:test, priority:Medium, workstream:tests ([project-management:DEC-012-classification-axes]). pass.
  • PR body links a closing issueCloses #405 present and closes field populated (git-conventions.yaml pr-body). pass.
  • Doc-impact section present — body has a ## Doc impact section, the hard-reject pr-body rule (git-conventions.yaml). pass.
  • Surface-change discipline — diff adds a single test file (tests/test_entrypoint_exec_bit.py); no kit-owned-tree rename/removal, no schema_version bump, no capability-subtree restructure, so no migration is required ([COR-010]). Pure addition. pass. Note: the new test blob is tracked 100644, which is correct — it is a pytest module under tests/, not a .pkit/**/scripts/ dispatcher entrypoint, and carries no uv-script shebang, so it is outside the very invariant it guards.
  • No-shared-files invariant — no edits to core-owned files; the change is confined to the project's tests/ tree ([COR-001]). pass.

No warnings. No bypassable-with-audit findings, so no audit comment is required for approval.

@aleskalfas aleskalfas changed the title test(scripts): ci guard: assert dispatcher entrypoint scripts are tracked executable test(scripts): guard that dispatcher entrypoints are tracked executable Jul 1, 2026
@aleskalfas aleskalfas merged commit 6f411d7 into main Jul 1, 2026
1 check passed
@aleskalfas aleskalfas deleted the test/405-ci-guard-assert-dispatcher-entrypoint branch July 1, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Test] CI guard: assert dispatcher entrypoint scripts are tracked executable

1 participant