Lefthook Commit Gate for Catalogue Consumers
Spec: Lefthook Commit Gate for Catalogue Consumers
Context
HI Catalogue consumers with a supported JavaScript package manager and lockfile need a default local Git Commit Gate. Lefthook is the project-local manager. The gate receives a complete Quality Command Contract from compiled catalogue context and requires lint plus a read-only format-check for staged, applicable owner scope before a normal commit.
The CLI owns desired state, policy, and evidence. The $hi-cli agent owns post-command lifecycle follow-through and verification.
Non-Goals
- Supporting Python-only or other consumers without a supported JavaScript package-manager and lockfile path.
- Replacing consumer-owned Lefthook entries or silently migrating another hook manager.
- Formatting or restaging files in the Commit Gate.
- Preventing deliberate
LEFTHOOK=0,--no-verify, or equivalent bypasses, or reporting historical bypass telemetry. - Making the local gate the merge authority; CI remains the merge authority.
- Extending the existing AI-agent lifecycle-hook projection to represent Git commits.
- Defining implementation files, workers, task graphs, execution order, or unaccepted design.
User Stories
US-001: Protect the normal commit path
As a Commit Gate Consumer, I want staged work in each applicable owner workspace to pass lint and a read-only format-check before Git creates my commit.
US-002: Control policy durably
As a project operator, I want hi init and hi ensure to persist enabled or disabled Commit Gate policy so later scaffold operations cannot silently reactivate an opt-out.
US-003: Materialize safely with existing tooling
As a consumer, I want HI to preserve my Lefthook configuration and existing hook-manager state unless I authorize migration.
US-004: Verify operational state
As an operator, I want hi check and the Post-Command Handoff to distinguish desired scaffold state from live Commit Gate health.
Acceptance Criteria
- AC-001: An applicable Commit Gate Consumer has a complete Quality Command Contract with one lint command and one read-only format-check command, backed by the project-local Lefthook dependency pinned to the reviewed version.
- Covers: US-001
- AC-002: A normal pre-commit runs each applicable owner contract exactly once, runs independent lint and format-check work in parallel, aggregates all failures, and succeeds without starting quality tools when the applicable staged scope is empty.
- Covers: US-001
- AC-003: The HI-owned Lefthook pre-commit command is named exactly
lint, and it runs only against staged, applicable owner scope.- Covers: US-001, US-003
- AC-004:
commitGatepersistsenabledordisabled, and an absent value is treated as enabled.hi initandhi ensurepersist only the policy; they do not materialize the gate.- Covers: US-002
- AC-005: While Commit Gate Opt-Out is selected, scaffold and update do not restore the HI-owned dependency, command, configuration, or installation action. A later scaffold-capable command can materialize a re-enable.
- Covers: US-002
- AC-006: When HI is the sole Lefthook owner, ownership-aware agent follow-through removes the project-local dependency and runs plain
lefthook uninstall. When ownership is shared, it preserves the dependency and disables only the HI command.- Covers: US-002, US-003
- AC-007: Another hook manager or unsafe existing configuration causes scaffold to defer dependency, configuration, and installation, then return migration evidence. An authorized migration must precede a rerun.
- Covers: US-003
- AC-008: Existing Lefthook commands and configuration entries remain unchanged. HI adds
lint; an existinglintthat cannot be merged safely is returned for user decision without overwrite.- Covers: US-003
- AC-009: Scaffold emits a Post-Command Handoff. It is complete only after an agent verifies the exact pinned dependency, active
lintconfiguration, and installed Git hook; missing or failed follow-through remains unresolved.- Covers: US-004
- AC-010: The managed scaffold receipt proves HI-owned desired state, while a separate Commit Gate Lifecycle Receipt proves live operational state. Any relevant desired or observed state change makes the lifecycle receipt stale.
- Covers: US-004
- AC-011:
hi checkreports policy and exact current health states, including disabled, healthy, unresolved handoff, dependency drift, changed or missinglint, missing or wrong hook, and conflicting manager, without repair.- Covers: US-004
- AC-012: Deliberate local bypass remains possible, historical bypass is not claimed, and CI remains the merge authority.
- Covers: US-001, US-004
Constraints
- Default-on applies only to Commit Gate Consumers.
- Lefthook is the Evil Martians
lefthookpackage and executable, version2.1.10. - Commit Gate policy is durable, typed project state in
.devpunks/settings.json. - HI owns only the
lintentry in shared Lefthook configuration and preserves consumer-owned entries. - Format-check is read-only; the gate does not format or restage files.
- Unsupported package-manager consumers are non-applicable for this integration.
Dependency Readiness
Ready: npm lefthook@2.1.10, integrity sha512-K7mM4WoqMwqfXYK11EHy+lSH1uW8XHni3Yn/bSqyerPkUPygGdf3xn18JoV5HyA06xuQL3ofGAOjG01QX9oJ4w==, npm gitHead 8d9cfec5f52367af6374a5430b4e9568844856e5, tarball https://registry.npmjs.org/lefthook/-/lefthook-2.1.10.tgz.
Branch/Base Intent
Implement on child branch feat/pre-commit-hooks, explicitly requested by the user, from immutable base/start commit b0c53c2552e3c0a1ab34519e7486a9bfe11d1fbb. Verified origin/main descends from that base.
Accepted Technical Decisions
- Commit Gate is a first-class catalogue contribution separate from AI-agent lifecycle hooks.
- Context compilation produces the Quality Command Contract and rejects applicable consumers missing either command.
- Existing staged workspace-selection semantics are reused; owner contracts run once and independent checks run in parallel.
- Project-local Lefthook is the sole dependency and version authority, pinned to
2.1.10. - Existing hook-manager detection blocks materialization. A Hook Migration Proposal is evidence, not authorization;
$hi-cliowns safe migration guidance and the agent performs the authorized migration. $hi-cliprovides ownership-aware guidance for disabling the current pre-commit hook after an opt-out; policy persistence alone never mutates hook state.- Scaffold, update, and check consume persisted policy;
hi checkis read-only. - Structured configuration merge preserves consumer entries and gives HI exactly
lint. - Opt-out disable behavior is ownership-aware because Lefthook npm postinstall can reinstall hooks.
Accepted Testing Decisions
- Verify policy persistence and the absent-field default through
hi initandhi ensurebehavior. - Verify context compilation rejects incomplete contracts and produces staged owner routing.
- Verify scaffold Post-Command Handoff output, ownership-safe disable, migration deferral, conflict preservation, and lifecycle receipt invalidation.
- Verify Git pre-commit behavior for lint and format success, aggregated failures, parallel independent checks, each-owner-once dispatch, and empty scope.
- Verify
hi checkemits each exact health state without repair and does not claim historical bypass detection.
Verification Seams
- Settings persistence and context compilation outputs.
- Managed scaffold receipt and Post-Command Handoff.
- Lefthook
lintcommand and Git.git/hooks/pre-commitinstallation. - Commit Gate Lifecycle Receipt.
hi checkread-only health output.
Decision Log
| Decision | Evidence | Rationale |
|---|---|---|
| Use Lefthook as the project-local manager | Grill Q1; research report; reviewed npm metadata | Establishes package and executable identity. |
| Default-on only for Commit Gate Consumers | Grill Q2, Q29 | Excludes unsupported Python-only and package-manager paths. |
| Persist two-state policy and durable opt-out | Grill Q3, Q6-Q8, Q12, Q16, Q18 | Makes reruns and disable behavior deterministic. |
| Keep Commit Gate separate from agent lifecycle hooks | Grill Q4; research report | Preserves distinct ownership and verification seams. |
| Preserve existing managers and Lefthook entries | Grill Q9, Q13, Q17, Q19 | Prevents unreviewed migration and consumer-state loss. |
Own exactly lint and compile the Quality Command Contract | Grill Q2, Q10, Q15, Q21-Q23 | Gives one clear HI boundary and deterministic staged routing. |
| Prove live state with a separate lifecycle receipt | Grill Q20, Q25-Q28 | Distinguishes desired scaffold state from operational hook health. |
| Allow deliberate bypass while retaining CI authority | Grill Q5, Q24 | Improves normal-path feedback without claiming enforcement the gate cannot provide. |