Research
Lefthook Commit Gate Delivery Planning Research
Lefthook Commit Gate Delivery Planning Research
Scope
Read-only planning discovery for Linear Story IP-425 and Task IP-426. The accepted spec, grill status, and glossary remain requirements authority.
Research lanes
| Lane | Coverage | Primary evidence |
|---|---|---|
| Policy and context | Project Settings, repository analysis, catalogue compilation, Quality Command Contract gap | apps/cli/src/features/project-settings/{model,service}.ts; apps/cli/src/features/repository-analysis/model.ts; apps/cli/src/features/context-planning/compiler.ts; packages/scaffold/src/{catalog,context-plan}.ts |
| Scaffold and receipts | Desired state, structured merge, managed receipt, handoff and live-proof gap | apps/cli/src/features/scaffold-state/{reconcile,receipt}.ts; apps/cli/src/scaffold/output.ts; apps/cli/src/update/run.ts; apps/cli/src/content/scaffold-copy.ts |
| Hook runtime | Staged owner selection and Lefthook install/config/run/uninstall behavior | apps/cli/scripts/staged-verification-selector.mjs; .githooks/pre-commit; exact Lefthook 2.1.10 source |
| Check and docs | Read-only check, JSON/facts/rendering, health vocabulary, docs/release gates | apps/cli/src/features/repository-check/*; apps/cli/src/platform/repository-check-capabilities.ts; apps/cli/src/presentation/operation-result/repository-check-facts.ts; docs/runbooks/hi-cli-scaffolding.md |
Trusted facts
Durable policy and compilation
ProjectSettingsDocumenthas nocommitGate. Writes start from the raw decoded object, so known-field changes preserve unrelated keys. Initialization and reconfiguration need typed policy support (apps/cli/src/features/project-settings/model.ts:12-31;service.ts:292-400).hi ensureis settings-only today, matching the accepted policy-only command boundary (apps/cli/src/cli/ensure-command.ts:17-75).ContributionKindhas no Commit Gate family, and catalogue hooks are AI-agent lifecycle hooks only (packages/scaffold/src/context-plan.ts:8-15;apps/cli/src/data/catalog/hooks.ts:1-26). Reusinglifecycle-hookwould violate the accepted boundary.- Repository manifest evidence lacks package-manager, lockfile, and quality-command fields (
apps/cli/src/features/repository-analysis/model.ts:20-31). Context compilation cannot yet prove applicability or compile a complete Quality Command Contract. - Lint catalogue entries contain configuration/dependency metadata, not executable lint and read-only format-check commands (
apps/cli/src/data/catalog/lint.ts:25-43). Runtime package-script discovery would create a second authority.
Desired state, coexistence, and proof
packages/scaffoldowns behavior-free shared contracts. CLI materialization belongs toapps/cli/src/scaffold/output.ts; reconciliation belongs toapps/cli/src/update/run.ts.- Reconciliation already preserves consumer-owned structured entries and removes only receipt-proven HI entries. This is the correct pattern for the one owned Lefthook
lintcommand (apps/cli/src/update/run.ts:1910-1963;apps/cli/src/features/scaffold-state/reconcile.ts:185-256). - Managed scaffold and AI projection receipts do not prove an installed Git hook or completed agent follow-through (
apps/cli/src/features/scaffold-state/receipt.ts:55-104;apps/cli/src/scaffold/output.ts:2367-2385). The Commit Gate Lifecycle Receipt must remain separate. .devpunks/AGENT-HANDOFF.mdalready carries post-scaffold work but has no Commit Gate verification section (apps/cli/src/content/scaffold-copy.ts:243-381).
Staged execution and Lefthook 2.1.10
staged-verification-selector.mjsis NUL-safe, accounts for both rename paths, mapsapps/*andpackages/*owners, falls back for global paths, and spawns nothing for empty staged scope (apps/cli/scripts/staged-verification-selector.mjs:19-113). It is Harness-specific, sequential, and fail-fast, so it is not the consumer runner required by the spec.- Lefthook npm
2.1.10runsnode postinstall.js, which runslefthook install -ffromINIT_CWDor the current directory. Dependency installation can reactivate hooks unless policy and migration preflight prevent materialization. - Lefthook rejects custom local/global
core.hooksPathby default. Force/reset can replace consumer behavior, so automatic force/reset is forbidden. - Plain
lefthook uninstallremoves Lefthook-owned hooks and keeps config. It is safe only when evidence proves HI is sole owner. - Hook-level
parallel: truecompletes and collects all jobs; empty staged lists skip jobs.piped: trueis fail-fast and unsuitable.
Read-only health and evidence
hi checkusescheck: true,write: false,yes: false(apps/cli/src/cli/check-command.ts:24-99;apps/cli/src/platform/feature-application-operations.ts:193-205). Commit Gate health must preserve this.RepositoryCheckResulthas no Commit Gate health. Facts, JSON, terminal rendering, and remediation guidance must change together (apps/cli/src/features/repository-check/application.ts:34-52;apps/cli/src/presentation/operation-result/repository-check-facts.ts;apps/cli/src/ui/renderer.ts).- Accepted states are disabled, healthy, unresolved handoff, dependency drift, missing/changed
lint, missing/wrong hook, and conflicting manager. Current health must not claim historical bypass detection. - CLI workflow/setup changes require
docs/README.mdanddocs/runbooks/hi-cli-scaffolding.md. Changelog changes select the release path and require classifier readback.
Design alternatives
- Extend broad existing modules directly. This minimizes new files but spreads policy, desired state, observed health, proof, and recovery across callers; it also risks overloading managed receipts.
- Add one deep
features/commit-gateboundary. Keep shared schemas inpackages/scaffold, policy inproject-settings, compilation in repository analysis/context planning, and raw filesystem/Git/package-manager/process mechanics in adapters. Existing scaffold/update/check callers consume one typed feature result.
Select option 2. It keeps one semantic owner, supports deterministic failure-path tests, and preserves desired-state versus live-proof boundaries.
Uncertainty and conclusion
- The connected Linear tool exposes only Collective Intelligence, not Devpunks
IP-*. The same-day handoff retains the exact IP-425/IP-426 hierarchy and V4.1 membership, but live provider readback remains required before mutation/closeout. - No implementation, PR, CI run, lifecycle receipt, or real consumer Git evidence exists.
- The change is architecture-bearing. IP-426 is one provider Task, so one worker must deliver vertical RED/GREEN cycles inside one behavior-complete architecture wave, with no temporary seam.