feat: implement native hooks runtime

This commit is contained in:
jb
2026-09-01 16:43:46 -04:00
parent 3a9e61c22d
commit 73fa3299bf
59 changed files with 3392 additions and 8 deletions
@@ -0,0 +1,9 @@
# ADR 0001: standalone runtime and trusted policies
**Status:** accepted, 27 August 2026
`pi-native-hooks` is one Pi package and extension. It loads only direct-child TypeScript policies from the current OS user's `~/.config/pi-native-hooks/policies`, after owner, mode, regular-file, and no-symlink checks. Policies are trusted executable code with Pi's authority; validation is not a sandbox.
Analyzer execution is package-owned and coalesced by effective analyzer key. The MVP adapter is ast-grep. Verification is exact-command, revision-scoped evidence, persisted on the active session branch. Pending armed checks force an `agent_settled` follow-up; a reasoned agent waiver is visible and expires on the next relevant mutation.
Node-native erasable TypeScript is required on Node >=22.19. Unsupported syntax fails that policy with an actionable load error; no implicit transpiler fallback is used.
+5
View File
@@ -0,0 +1,5 @@
# Runtime event and identity contract
The runtime targets Pi 0.84.4. `tool_execution_start` carries `toolCallId`, `toolName`, and `args`; all parallel sibling starts are emitted in source order before execution. A finalized execution either enters `tool_result` (with final `input`, `content`, `details`, `usage`, and `isError`) followed by `tool_execution_end`, or may enter only `tool_execution_end` when blocked/invalid. Handlers are idempotent by tool-call ID. `agent_settled` is the completion candidate used by the gate.
Project identity is SHA-256 of the canonical git root, initial commit object (or `NO_HEAD`), and package name, NUL-delimited. The mutable HEAD and index belong to the workspace fingerprint, not identity. A different canonical root or initial commit is a different project. This avoids remote-URL instability while preventing evidence transfer to an unrelated checkout.
+6 -6
View File
@@ -2,7 +2,7 @@
## Status
**Approved on 27 August 2026 for later execution.** This repository is seeded with the reviewed plan only. Runtime implementation has not started and is intentionally outside the repository-creation task.
**Approved on 27 August 2026 and implemented as the repository baseline.** Activation remains a separate explicit user-authorized step; the package is not installed and live personal configuration is not created by implementation or tests.
## Purpose
@@ -18,7 +18,7 @@ The extension will also establish a small toolkit and authoring skill for adding
- Implement a native TypeScript Pi extension with `pi.on(...)`, not `pi-yaml-hooks`, `pi-steering`, or `pi-workflow`.
- Build one standalone repository and Pi package named `pi-native-hooks`, with one extension of the same name.
- Install the package from `/srv/data/code/pi-native-hooks` as a Pi local-path package during development; do not depend on harness-tools link management.
- Install the package from `/srv/data/code/jb-pi/pi-native-hooks` as a Pi local-path package during development; do not depend on harness-tools link management.
- Load personal hook policies as trusted TypeScript modules from `~/.config/pi-native-hooks/`.
- Use ast-grep rule packs for syntax diagnostics.
- Execute an analyzer once per overlapping mutation wave and analyzer configuration, then fan an immutable normalized result out to every interested policy. Individual policy modules must not spawn AST, lint, or LSP processes through the runtime interface.
@@ -85,11 +85,11 @@ The first release is successful when:
## Repository and runtime boundaries
- **Repository:** `/srv/data/code/pi-native-hooks`
- **Repository:** `/srv/data/code/jb-pi/pi-native-hooks`
- **Package and extension:** `pi-native-hooks`
- **Extension entrypoint:** `extensions/pi-native-hooks/index.ts`
- **Personal policy root:** `~/.config/pi-native-hooks/`
- **Installation:** Pi local-path package during development; registry publication is deferred.
- **Installation:** Pi local-path package from `/srv/data/code/jb-pi/pi-native-hooks` during development; registry publication is deferred.
- **Runtime code:** package-owned lifecycle, analyzer, state, delivery, validation, and UI modules.
- **Personal code:** user-owned policy modules and adjacent ast-grep rule files. Personal policies are not committed to this repository.
- **Repository fixtures:** checked-in example policies and test fixtures that mirror the personal module contract without containing the user's live policy set.
@@ -634,7 +634,7 @@ After approval, implementation should add:
- A throwaway ast-grep 0.45.1 fixture detected both initial TypeScript patterns in one `scan --json=stream` invocation, did not confuse logical negation with a non-null expression, and honored a rule-specific suppression with a trailing rationale.
- The ast-grep fixture confirmed warning findings return exit code zero and JSON source ranges are zero-based, both now reflected in the adapter plan.
- Node 26.7 successfully imported an erasable `.ts` policy containing interfaces, `satisfies`, and a type-only import to an unavailable runtime package. Phase 0 still must repeat the contract on the minimum supported Node 22.19 runtime.
- Planning created only this repository's README and documentation. No runtime extension, live personal policy, Pi package setting, or global installation was changed.
- Planning originally created only this repository's README and documentation. Implementation subsequently added the runtime, tests, examples, and authoring skill. No live personal policy, Pi package setting, or global installation is changed without the separate activation approval.
Independent agent review is deferred because direct subagent launches are currently being repaired. It remains the first execution prerequisite when implementation starts from this repository.
@@ -653,4 +653,4 @@ The user accepted these consequences on 27 August 2026:
9. Pi's settlement gate cannot prevent a user or external client from closing the session.
10. Local-path package installation and creation of `~/.config/pi-native-hooks` are separate external mutations requiring approval after tests and review.
User approval is recorded. Implementation has not started; independent review remains the first execution prerequisite.
User approval is recorded. An independent pre-implementation review was completed before runtime changes; its blockers were addressed by `docs/event-contract.md`, the explicit project identity schema, fail-fast native TypeScript loading, and canonical repository paths.
+13
View File
@@ -0,0 +1,13 @@
# Independent implementation review — 27 August 2026
A separate Pi agent reviewed the implementation after the full test and typecheck run.
## Findings and resolution
- **Tool-result patch flow:** reviewer suspected a wave map was returned to Pi. Reinspection and `tests/runtime.test.ts` confirm `ExecutionWaveCoordinator.result()` selects `.get(toolCallId)` and the runtime returns that per-call patch. No defect remained.
- **typebox packaging:** retained as a peer dependency, as required by Pi's package documentation for bundled core packages; it is also a development dependency for standalone typechecking.
- **Initializer path mapping:** fixed. The shipped template contains a placeholder and `/hooks-init --apply` substitutes the installed package root rather than copying a machine-specific path.
- **Equivalent project-root paths:** normalized with `path.resolve` before exact cwd comparison. Subdirectories remain intentionally invalid.
- **Runtime integration coverage:** added a focused registration and per-call tool-result augmentation test.
The reviewer also confirmed the unfiltered test and typecheck commands passed. No unresolved review blocker remains. Activation and creation of live personal configuration remain separate user-authorized steps.
+4
View File
@@ -0,0 +1,4 @@
# Todos
- Validate the native TypeScript loader contract on Node 22.19 in CI (development host currently uses Node 26).
- Consider a user-configurable read-only custom-tool allowlist after MVP evidence is collected.