Skip to content

Replace stale native hook copy with governed cross-harness projection #116

Description

@Sequela02

Problem

Kiln has one canonical hooks configuration for Kiln-run sessions, but the retired native projector did not translate that contract into current harness lifecycle-hook contracts:

  • Claude Code received a legacy hooks.autoformat object rather than lifecycle event arrays.
  • Codex received only .codex/hooks/autoformat.sh, without a discovered .codex/hooks.json or inline [hooks] registration.
  • OpenCode received no projection.
  • Matcher, stdin payload, output, timeout, async, trust, blocking, and Windows semantics were not translated.
  • Capability status nevertheless reported hooks as supported for all three harnesses.

This creates false parity and can leave operators believing enforcement hooks are active when they are not.

Decision

Kiln should own a semantic hook contract and project it through versioned harness adapters. It must not use a lowest-common-denominator copy operation or treat prompt text/post-hoc observation as preventive enforcement.

Required design

Canonical contract

Define hook identity and scope plus:

  • semantic event;
  • intent/effect (observe, enrich, or enforce);
  • canonical selector rather than a harness matcher string;
  • argv-based command handler and platform requirements;
  • timeout and async behavior;
  • failure policy;
  • typed input/output effects;
  • explicitly selected native targets.

Keep global and private-project ownership explicit. Generated native files remain projections, never authority.

Adapter capability model

For every admitted harness version and hook, report one of:

  • exact — event, selection, payload, outcome, ordering, and failure semantics are equivalent;
  • lossy — named semantic loss accepted only for non-enforcement hooks;
  • unsupported — no safe representation exists.

Any enforce hook that is not exact must fail projection and prevent admission of a route that depends on it.

Harness adapters

  • Claude Code: render current lifecycle arrays in .claude/settings.json, including event-specific blocking/output behavior.
  • Codex: render .codex/hooks.json or inline config using the current trust and discovery contract, including commandWindows where required.
  • OpenCode: generate a versioned V2 plugin only for proven equivalent hooks; do not map unlike prompt, context, permission, HTTP, or retry hooks by name alone.
  • Kiln runtime: normalize the same semantic events through one runner instead of maintaining an unrelated environment-variable-only behavior.

Lifecycle and evidence

  • Preview every target path and exact/lossy/unsupported result.
  • Preserve unmanaged native hooks and unrelated fields.
  • Record adapter version, source identity/digest, managed fields/files, and per-target settlement in install-state.
  • Detect drift and require explicit force for reviewed managed drift.
  • Uninstall only recorded managed artifacts.
  • Do not report whole-operation success after a partial target failure.

Acceptance criteria

  • Canonical schema validates intent, effects, selectors, platform commands, and target selection.
  • A shared capability matrix is keyed by admitted executable version and semantic hook feature.
  • Claude, Codex, and OpenCode adapters have contract fixtures derived from current first-party schemas.
  • Projection status exposes exact, lossy, or unsupported with reasons per hook and harness.
  • Unsupported/lossy enforcement hooks fail closed before native execution.
  • Kiln-run and native hook inputs/outputs use a documented normalized envelope.
  • SubagentStart and SubagentStop are either wired in Kiln runtime or rejected by admission.
  • Windows behavior is tested for every command projection that claims support.
  • Dry-run, drift, partial failure, uninstall, and disabled-harness behavior have focused tests.
  • Architecture and operator docs distinguish Kiln-run hooks from native hook projection.
  • Live smoke evidence names the exact Claude Code, Codex, and OpenCode versions tested.

Non-goals

  • Importing unmanaged native hooks implicitly.
  • Claiming enforcement from prompt instructions or post-hoc telemetry.
  • Preserving the removed autoformat-only projection as a compatibility path.
  • Forcing harness-specific features into the portable contract.

Current containment

Remove the unsupported kiln sync --hooks target and setup-time autoformat projection, report native hook projection as unsupported, and retain uninstall recognition only for already-recorded managed artifacts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions