Skip to content

Add provider-neutral supervisor hook integration - #264

Merged
paudley merged 13 commits into
mainfrom
agent/nyarlathotep-hooks
Jul 27, 2026
Merged

Add provider-neutral supervisor hook integration#264
paudley merged 13 commits into
mainfrom
agent/nyarlathotep-hooks

Conversation

@paudley

@paudley paudley commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • add the versioned provider-neutral hook v1 request/response contract and machine-readable capability discovery
  • support private settings overlays with distinct repository roots, external supervisor hook commands, and independently owned Coding Ethos MCP commands
  • add consumer-scoped runtime-policy sync/check commands without rewriting tracked consumer configuration
  • add native Kimi hook/MCP generation, provider output semantics, verification probes, aliases, and generated capability documentation
  • split hook probe construction and validation into focused modules to keep hook settings code within repository limits
  • address review findings for root precedence, Kimi timeout rendering, neutral-v1 provider validation, generated ignores, state artifact clarity, stdout capture stability, and dependency security scan findings

Why

Local agent supervisors need a stable policy boundary that does not depend on Claude, Codex, Gemini, or Kimi response schemas. They also need to keep provider credentials/settings private while Coding Ethos continues to own policy, MCP, runtime policy, and code-intelligence behavior.

Capability Surface

  • Hook contract: neutral-v1 request validation, response encoding, correlation IDs, and provider-neutral effects.
  • Provider settings: Claude, Codex, Gemini, and Kimi hook/MCP generation with configurable hook deadlines where the provider supports them.
  • Overlay routing: separate settings root, source repository root, and durable Coding Ethos state root.
  • Runtime policy: consumer-scoped runtime-policy sync/check artifacts under private state.
  • Documentation: provider capability matrix, hook contract guidance, Kimi behavior, and supervisor setup examples.

Impact

Existing provider-native output and repo-local settings remain the default. Supervisors can opt into neutral-v1, separate --root from --repo-root, and pass a validated external hook command plus an explicit Coding Ethos MCP command. Static command validation rejects shell operators, substitutions, redirections, relative external executables, and invalid MCP commands.

Checklist

  • Provider-neutral contract and capability discovery implemented.
  • Split-root settings, repository, and state routing implemented.
  • Kimi hook/MCP generation, output semantics, and verification probes implemented.
  • Review feedback addressed on current branch head.
  • Local build and check gates passed.
  • GitHub checks passed on current branch head.

Validation

  • go test -buildvcs=false -timeout=90s -short ./go/internal/codeintelcli -covermode=atomic -coverprofile=/tmp/codeintelcli.out -count=10
  • make build
  • make check
  • protected pre-commit hook chain
  • protected pre-push hook chain
  • GitHub checks on 4dc915711aa9e3461a5be45d62e1e0ae22f3ffd0: Build distribution, CodeQL, Coding Ethos SARIF Gate, Go coverage, Go fuzz smoke, OSV dependency scan, OpenSSF Scorecard, Python 3.11/3.13 tests, Unified lint, Validate GitHub workflows, Zizmor, CLA

Notes

The local and GitHub gates pass on the current branch head. The protected hook chains still emit the repository-wide non-blocking Go coverage goal warning; the blocking 80% coverage floor passes locally and in GitHub Actions.

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a752993b-3f79-4efb-9321-d7afa7bd8fa9

📥 Commits

Reviewing files that changed from the base of the PR and between 317c6b0 and 4dc9157.

📒 Files selected for processing (3)
  • README.md
  • docs/HOOK_CONTRACT_V1.md
  • go/internal/codeintelcli/main_internal_test.go
📜 Recent review details
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-06-23T12:26:47.373Z
Learnt from: paudley
Repo: paudley/coding-ethos PR: 258
File: go/internal/geminiprompts/render.go:125-132
Timestamp: 2026-06-23T12:26:47.373Z
Learning: In the paudley/coding-ethos repo, the documented guideline “Gemini prompt pack should be generated in go/internal/geminiprompts/” refers to the generator implementation location (Go source), not the location of the generated prompt-pack artifact. Always treat PromptPackPath as the enforced output artifact path `.coding-ethos/gemini/prompt-pack.json` (e.g., render_test.go asserts PromptPackPath, and compiler_policies.go / hookrunner lookup / README document the expected path). Do not flag a code review issue just because PromptPackPath points to `.coding-ethos/gemini/prompt-pack.json`; only flag violations if the artifact output path logic breaks that enforced contract.

Applied to files:

  • go/internal/codeintelcli/main_internal_test.go
🔇 Additional comments (3)
docs/HOOK_CONTRACT_V1.md (1)

192-197: 🎯 Functional Correctness

Keep a provider-wide timeout contract here.

The text already documents that Coding Ethos validates --hook-timeout-seconds within the 1–3600 range and calls out Kimi’s 1–600 second native limit separately. This does not state that invalid Kimi TOML is generated for values beyond Kimi’s native range.

			> Likely an incorrect or invalid review comment.
README.md (1)

494-505: LGTM!

Also applies to: 1581-1581, 1590-1661, 1673-1677, 1688-1705, 1764-1786

go/internal/codeintelcli/main_internal_test.go (1)

27-27: LGTM!

Also applies to: 39-43, 138-138, 465-465, 523-527, 577-581, 627-686, 795-804, 818-818, 827-851, 899-927, 1350-1369, 1423-1429


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added Kimi Code CLI integration, including native hooks, MCP configuration, memory handling, and capability reporting.
    • Added provider-neutral Hook Contract v1 with structured responses, validation, and capability discovery.
    • Added separate repository, settings, and durable state locations for agent hooks, memory, and code intelligence.
    • Added configurable hook timeouts and runtime-policy synchronization/check commands.
  • Bug Fixes

    • Improved sandbox evidence preservation and handling when cgroup attachment is unavailable.
    • Prevented inherited runtime context from leaking into subprocesses.
  • Documentation

    • Expanded operational guidance for overlays, state management, Kimi setup, hook verification, and runtime policies.

Walkthrough

This PR adds Kimi provider support, a provider-neutral hook contract, capability discovery, split repository/state-root routing, private durable storage for code intelligence and memory, runtime-policy commands, configurable hook timeouts, and related sandbox, subprocess, CLI, documentation, and test coverage.

Changes

Runtime and hook behavior

Layer / File(s) Summary
Neutral hook contract and provider output
go/internal/hooks/*, go/internal/hookcli/*, docs/HOOK_CONTRACT_V1.md
Adds neutral-v1 request validation and response encoding, correlation IDs, Kimi provider output semantics, provider-specific exit codes, and CLI contract selection.
Kimi settings and capability discovery
go/internal/agenthooks/*, go/internal/agenthookscli/*
Adds Kimi settings/MCP generation, capability reporting, timeout-aware hooks, split-root synchronization, provider probes, Codex trust options, state artifacts, and verification coverage.
Split-root runtime routing and policy
go/cmd/coding-ethos-run/*, go/internal/agenthookscli/*
Routes repository, settings, and state roots separately; adds runtime-policy sync/check commands and forwards validated external hook/MCP commands.
Code intelligence and memory state separation
go/internal/mcp/*, go/internal/memories/*, go/internal/syncstate/state.go
Stores code-intelligence databases, workspace metadata, and central memory under explicit state roots while reading source settings from repository roots.
Sandbox, subprocess, and fixture isolation
go/internal/sandbox/*, go/internal/e2e/*, go/internal/managedcapture/*, tests/*
Adds cgroup start probes, managed __pycache__ paths, runtime-context environment cleanup, sandbox helper linking, and conditional isolation evidence checks.
Repository configuration and documentation
.coding-ethos/*, .gitignore, .gitattributes, Makefile, README.md, docs/*, pyproject.toml
Updates generated-artifact ignores, local cache settings, workflow documentation, Kimi capability documentation, and package metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: erinaudley

Poem

A rabbit hops through roots unseen,
With Kimi hooks in overlays green.
State sleeps safe beyond the tree,
Neutral JSON flows free.
“Sync and verify!” the bunny sings,
While private caches grow tiny wings.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: provider-neutral supervisor hook integration.
Description check ✅ Passed The description covers the required summary, validation, capability surface, checklist, and notes, with only minor checklist detail gaps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/nyarlathotep-hooks

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linter] gci: create analyzer: finding local modules for localModule configuration: reading go.mod: open go.mod: no such file or directory"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@paudley
paudley marked this pull request as ready for review July 27, 2026 19:51
@paudley
paudley requested a review from ErinAudley as a code owner July 27, 2026 19:51
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

Upgrade vulnerable Go modules reported by the PR OSV scan: github.com/google/cel-go, github.com/klauspost/compress, and golang.org/x/text. Keep transitive x/* module versions consistent with go get and go mod tidy.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.coding-ethos/.gitignore:
- Around line 3-10: Fix the ignore patterns in .coding-ethos/.gitignore by
making them relative to that directory: remove the repeated .coding-ethos/
prefix so cache, code-intel.duckdb and its WAL, events, hook-runs, lint-runs,
prune-runs, and state paths match the repository-root .coding-ethos contents.

In `@go/cmd/coding-ethos-run/dispatch.go`:
- Around line 983-1001: Update runAgentHooksCommand so CODE_ETHOS_CONSUMER_ROOT
uses the same root precedence as withCommandRoots: resolve --repo-root first,
then --root, then the existing paths.Root value. Do not fall back to
settingsRoot when exporting CODE_ETHOS_CONSUMER_ROOT; preserve the separate
settings-root fallback for envStateRoot.

In `@go/cmd/coding-ethos-run/parent_workflow.go`:
- Around line 213-224: Update cleanOptionalRoot to avoid embedding the
state-root-specific error text: include the rejected root value in the
absolute-path validation error and make the message generic enough for any
caller. Preserve the existing empty-root behavior and cleaned absolute-path
return path.

In `@go/internal/agenthooks/settings_test.go`:
- Around line 903-1050: Extract the shared expected verification-check count
into a single test constant near the related tests, then replace the hardcoded
17 values in all three report assertions and their failure messages with that
constant. Keep the existing validation behavior and test names unchanged.

In `@go/internal/agenthooks/settings.go`:
- Around line 1543-1588: Add a TimeoutSeconds field to kimiHook and update
buildKimiSettings to accept or access SettingsOptions.HookTimeoutSeconds,
assigning that configured value to every generated hook, including spec hooks,
provider alias hooks, and observation event hooks. Preserve the existing
command, event, matcher, and filtering behavior.

In `@go/internal/agenthooks/state_artifacts.go`:
- Around line 178-185: Update agentHookStateArtifactInputs to accept a
providerStateContent struct with named fields instead of multiple positional
string parameters. Define fields for claude, claudeMCP, codex, gemini,
kimiConfig, and kimiMCP, then update callers and internal references to use the
struct fields while preserving the existing hashing behavior.

In `@go/internal/agenthookscli/main.go`:
- Around line 114-138: Remove the unused `--json` flag registration from
`capabilities`, since this subcommand already always writes JSON through
`feedback.WriteJSON`. Keep the existing flag parsing and capability output
behavior unchanged.

In `@go/internal/hooks/contract_v1.go`:
- Around line 186-207: Update validateHookContractProvider to validate the
resolved value from event.Provider(), not only event.ProviderHint. Explicitly
reject an empty unresolved provider fallback, and ensure the resolved provider
is contained in hookContractV1Providers() while preserving the existing contract
error behavior.

In `@tests/test_lint_capture_lifecycle.py`:
- Around line 25-27: Add a concise Google-style docstring to the public test
function test_subprocess_environment_drops_inherited_runtime_roots describing
that it verifies subprocess environments remove inherited runtime roots.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: aca8577c-de1a-4fda-b32a-1939451556aa

📥 Commits

Reviewing files that changed from the base of the PR and between 5259447 and 9317c1e.

⛔ Files ignored due to path filters (2)
  • pre-commit/hooks/npm-locks/eslint-10.3.0/package-lock.json is excluded by !**/package-lock.json
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (62)
  • .coding-ethos/.gitignore
  • .gitattributes
  • .gitignore
  • Makefile
  • README.md
  • docs/HOOK_CONTRACT_V1.md
  • docs/PROVIDER_CAPABILITY_MATRIX.md
  • go/cmd/coding-ethos-run/args.go
  • go/cmd/coding-ethos-run/dispatch.go
  • go/cmd/coding-ethos-run/hook_policy_paths.go
  • go/cmd/coding-ethos-run/main.go
  • go/cmd/coding-ethos-run/main_test.go
  • go/cmd/coding-ethos-run/parent_workflow.go
  • go/internal/agenthooks/codex_trust.go
  • go/internal/agenthooks/doctor_contract_test.go
  • go/internal/agenthooks/provider_capabilities.go
  • go/internal/agenthooks/settings.go
  • go/internal/agenthooks/settings_probe.go
  • go/internal/agenthooks/settings_test.go
  • go/internal/agenthooks/spec.go
  • go/internal/agenthooks/state_artifacts.go
  • go/internal/agenthookscli/main.go
  • go/internal/agenthookscli/main_internal_test.go
  • go/internal/e2e/mcp_test.go
  • go/internal/e2e/sandbox_workflow_test.go
  • go/internal/e2e/scenario.go
  • go/internal/e2e/scenario_internal_test.go
  • go/internal/hookcli/main.go
  • go/internal/hookcli/main_internal_test.go
  • go/internal/hookrunnercli/main.go
  • go/internal/hookrunnercli/main_internal_test.go
  • go/internal/hookrunnercli/toolchain_groups.go
  • go/internal/hookrunnercli/toolchain_groups_internal_test.go
  • go/internal/hooks/contract_v1.go
  • go/internal/hooks/contract_v1_test.go
  • go/internal/hooks/event.go
  • go/internal/hooks/inspection.go
  • go/internal/hooks/json.go
  • go/internal/hooks/provider_output.go
  • go/internal/hooks/provider_output_test.go
  • go/internal/hooks/result.go
  • go/internal/hooks/runner.go
  • go/internal/hooks/testdata/neutral_v1_allowed.json
  • go/internal/hooks/testdata/neutral_v1_blocked.json
  • go/internal/managedcapture/capture.go
  • go/internal/managedcapture/capture_test.go
  • go/internal/managedcapture/writable_paths.go
  • go/internal/mcp/code_intel.go
  • go/internal/mcp/code_intel_workspace.go
  • go/internal/mcp/server.go
  • go/internal/mcp/server_test.go
  • go/internal/mcpcli/main.go
  • go/internal/memories/memory.go
  • go/internal/memories/memory_test.go
  • go/internal/sandbox/cgroup_linux.go
  • go/internal/sandbox/cgroup_linux_test.go
  • go/internal/syncstate/state.go
  • go/internal/toolaliases/aliases.go
  • go/internal/toolaliases/aliases_test.go
  • pyproject.toml
  • tests/lint_capture_support.py
  • tests/test_lint_capture_lifecycle.py
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
  • GitHub Check: Coding Ethos SARIF Gate / Coding Ethos SARIF Gate
  • GitHub Check: Validate GitHub workflows
  • GitHub Check: Test (Python 3.11)
  • GitHub Check: Go coverage
  • GitHub Check: Unified lint
  • GitHub Check: Test (Python 3.13)
  • GitHub Check: OSV dependency scan
  • GitHub Check: CodeQL (go)
  • GitHub Check: Go fuzz smoke
🧰 Additional context used
📓 Path-based instructions (5)
{.python-version,pyproject.toml,mypy.ini,pyrightconfig.json,ruff.toml,.golangci.yml}

📄 CodeRabbit inference engine (AGENTS.md)

Python version is the single authority across generated tool configs, pyupgrade autofix pass, and repo-root consistency checks for .python-version, pyproject.toml, mypy.ini, pyrightconfig.json, ruff.toml, and .golangci.yml's lll line-length setting

Files:

  • pyproject.toml
Makefile

📄 CodeRabbit inference engine (AGENTS.md)

Makefile: Use make install to install dependencies
Use make check as the canonical automated verification gate; use make test or uv run pytest only as focused Python-test helpers

Files:

  • Makefile
**/{hooks,policies,lint-capture,runtime}/**/*.{go,sh,py}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer compiled Go for hook, policy, lint-capture, and runtime glue; treat shell and Python as transitional unless they are clearly the right interface

Files:

  • go/internal/hooks/inspection.go
  • go/internal/hooks/provider_output_test.go
  • go/internal/hooks/event.go
  • go/internal/hooks/runner.go
  • go/internal/hooks/contract_v1_test.go
  • go/internal/hooks/json.go
  • go/internal/hooks/provider_output.go
  • go/internal/hooks/result.go
  • go/internal/hooks/contract_v1.go
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Crash early on ambiguous startup and configuration states instead of degrading silently
Treat required imports as hard dependencies and fail immediately if they are missing (no soft dependency pattern)
Make ruff and mypy blocking quality gates rather than advisory tools
Model required dependencies as non-optional and default to full-strength behavior (no Optional types for required dependencies)
Run required validation unconditionally; a missing component is itself a failure
Validate required capabilities at startup instead of probing for them at runtime
Validate configuration, schema, and extensions during bootstrap rather than on first use
Route configuration through validated bootstrap paths instead of inline shell environment variables
Log important decisions with context and instrument the system with metrics (Radical Visibility)
Define and verify interfaces before writing or referencing implementations (Protocol-First Design)
Resolve lint findings with structural fixes; suppress only with documented necessity
Use Python's functional tools (itertools, functools) when they make code clearer and more local
Keep public behavior documented as part of the interface contract; every public function must have a Google-style docstring
Use precise exception types and actionable, context-rich error messages; all application exceptions should inherit from a base exception with structured context

Files:

  • tests/lint_capture_support.py
  • tests/test_lint_capture_lifecycle.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: Treat tests as executable behavioral contracts and update them with code changes (Testing as Specification)
Prove critical behavior with real functional workflows before relying on unit tests or mocks (Functional Testing Is the Proof)

Files:

  • tests/lint_capture_support.py
  • tests/test_lint_capture_lifecycle.py
🧠 Learnings (2)
📚 Learning: 2026-06-23T12:26:47.373Z
Learnt from: paudley
Repo: paudley/coding-ethos PR: 258
File: go/internal/geminiprompts/render.go:125-132
Timestamp: 2026-06-23T12:26:47.373Z
Learning: In the paudley/coding-ethos repo, the documented guideline “Gemini prompt pack should be generated in go/internal/geminiprompts/” refers to the generator implementation location (Go source), not the location of the generated prompt-pack artifact. Always treat PromptPackPath as the enforced output artifact path `.coding-ethos/gemini/prompt-pack.json` (e.g., render_test.go asserts PromptPackPath, and compiler_policies.go / hookrunner lookup / README document the expected path). Do not flag a code review issue just because PromptPackPath points to `.coding-ethos/gemini/prompt-pack.json`; only flag violations if the artifact output path logic breaks that enforced contract.

Applied to files:

  • go/internal/toolaliases/aliases_test.go
  • go/internal/e2e/scenario_internal_test.go
  • go/internal/agenthooks/spec.go
  • go/internal/hookrunnercli/toolchain_groups.go
  • go/internal/managedcapture/writable_paths.go
  • go/internal/hooks/inspection.go
  • go/internal/e2e/mcp_test.go
  • go/internal/mcp/server.go
  • go/internal/mcpcli/main.go
  • go/internal/managedcapture/capture_test.go
  • go/internal/syncstate/state.go
  • go/internal/hooks/provider_output_test.go
  • go/internal/mcp/server_test.go
  • go/internal/hookrunnercli/toolchain_groups_internal_test.go
  • go/internal/hooks/event.go
  • go/internal/memories/memory_test.go
  • go/internal/managedcapture/capture.go
  • go/internal/hookrunnercli/main_internal_test.go
  • go/internal/toolaliases/aliases.go
  • go/internal/agenthooks/doctor_contract_test.go
  • go/internal/hookrunnercli/main.go
  • go/internal/hooks/runner.go
  • go/internal/hooks/contract_v1_test.go
  • go/internal/sandbox/cgroup_linux_test.go
  • go/internal/hooks/json.go
  • go/internal/hookcli/main_internal_test.go
  • go/internal/agenthooks/codex_trust.go
  • go/internal/hooks/provider_output.go
  • go/internal/mcp/code_intel.go
  • go/internal/agenthooks/provider_capabilities.go
  • go/internal/hookcli/main.go
  • go/internal/hooks/result.go
  • go/internal/e2e/scenario.go
  • go/internal/e2e/sandbox_workflow_test.go
  • go/internal/agenthookscli/main_internal_test.go
  • go/internal/hooks/contract_v1.go
  • go/internal/sandbox/cgroup_linux.go
  • go/internal/agenthooks/settings_probe.go
  • go/internal/agenthooks/state_artifacts.go
  • go/internal/memories/memory.go
  • go/internal/mcp/code_intel_workspace.go
  • go/internal/agenthookscli/main.go
  • go/internal/agenthooks/settings_test.go
  • go/internal/agenthooks/settings.go
📚 Learning: 2026-06-07T21:57:34.433Z
Learnt from: paudley
Repo: paudley/coding-ethos PR: 237
File: .gitignore:62-62
Timestamp: 2026-06-07T21:57:34.433Z
Learning: When reviewing this repo’s .gitignore files, do NOT flag the ignore entry that uses a dash form for the DuckDB shm sidecar as incorrect. Specifically, the pattern `.coding-ethos/code-intel.duckdb-shm` (and its recursive equivalent `**/.coding-ethos/code-intel.duckdb-shm`) must remain exactly as-is; the dot form `.coding-ethos/code-intel.duckdb.shm` will trip the repo’s blocking `repo.required_ignores` policy/lint stage.

Applied to files:

  • .gitignore
🪛 LanguageTool
docs/HOOK_CONTRACT_V1.md

[style] ~185-~185: Consider an alternative for the overused word “exactly”.
Context: ... are rejected. The explicit MCP form is exactly an absolute coding-ethos-run mcp; omi...

(EXACTLY_PRECISELY)

🔇 Additional comments (83)
.gitattributes (1)

7-7: LGTM!

.gitignore (1)

102-102: LGTM!

Makefile (1)

34-36: LGTM!

README.md (6)

494-505: LGTM!


1581-1581: LGTM!


1590-1661: LGTM!


1673-1677: LGTM!


1688-1705: LGTM!


1764-1786: LGTM!

pyproject.toml (1)

90-90: LGTM!

docs/HOOK_CONTRACT_V1.md (1)

1-200: LGTM!

go/internal/hooks/contract_v1.go (3)

18-56: LGTM!


58-152: LGTM!


209-433: LGTM!

go/internal/hooks/contract_v1_test.go (1)

14-172: LGTM!

go/internal/hooks/json.go (2)

7-69: LGTM!


89-131: LGTM!

go/internal/hookcli/main.go (3)

30-34: LGTM!

Also applies to: 46-56, 70-133


91-94: LGTM!


135-204: LGTM!

go/internal/hookcli/main_internal_test.go (1)

166-340: LGTM!

go/internal/hooks/provider_output_test.go (1)

143-181: LGTM!

go/internal/hooks/event.go (1)

17-17: LGTM!

Also applies to: 32-33, 51-52, 65-66, 86-87

go/internal/hooks/inspection.go (1)

197-201: LGTM!

go/internal/hooks/provider_output.go (1)

20-20: LGTM!

Also applies to: 62-62, 84-110, 213-226

go/internal/hooks/result.go (1)

12-28: LGTM!

Also applies to: 30-33

go/internal/hooks/runner.go (1)

101-105: LGTM!

Also applies to: 118-122, 249-250, 271-277, 1030-1033

go/internal/hooks/testdata/neutral_v1_allowed.json (1)

1-19: LGTM!

go/internal/hooks/testdata/neutral_v1_blocked.json (1)

1-25: 🎯 Functional Correctness

Verify the blocked fixture’s tracking identifier.

Blocked results receive Result.TrackingID, and the neutral encoder serializes it. This fixture omits that field; unless assertJSONMatchesFixture intentionally strips dynamic tracking identifiers, the test will fail or fail to verify part of the response contract. Confirm the helper’s normalization and either include the expected identifier or document the omission.

docs/PROVIDER_CAPABILITY_MATRIX.md (1)

19-19: LGTM!

Also applies to: 209-284

go/internal/agenthooks/provider_capabilities.go (2)

12-13: LGTM!

Also applies to: 30-72


227-299: LGTM!

go/internal/agenthooks/spec.go (1)

16-17: LGTM!

go/internal/agenthooks/codex_trust.go (1)

40-56: LGTM!

Also applies to: 76-92, 185-189

go/internal/agenthooks/settings_test.go (6)

77-129: LGTM!


131-144: LGTM!

Also applies to: 146-150, 182-187, 223-225


349-350: LGTM!

Also applies to: 436-440, 442-499


632-634: LGTM!

Also applies to: 846-847, 887-888


1052-1132: LGTM!


1607-1612: LGTM!

Also applies to: 1645-1691, 1693-1729

go/internal/agenthooks/state_artifacts.go (1)

13-92: LGTM!

Also applies to: 94-99, 137-176, 218-231

go/internal/agenthookscli/main.go (5)

12-12: LGTM!

Also applies to: 29-69


140-175: LGTM!


246-298: LGTM!

Also applies to: 311-339, 354-387


476-515: LGTM!

Also applies to: 541-544


229-243: 🗄️ Data Integrity & Integration

No change needed. Artifact rendering and write rendering use the same post-existence path for Codex/Kimi text settings, so the non-overlay path does not record stale post-apply expected_sha256 values.

			> Likely an incorrect or invalid review comment.
go/cmd/coding-ethos-run/parent_workflow.go (3)

52-52: LGTM!

Also applies to: 118-153


164-168: LGTM!

Also applies to: 183-187, 206-211


383-383: LGTM!

Also applies to: 402-405, 953-962

go/internal/hookrunnercli/main.go (1)

445-451: LGTM!

go/internal/hookrunnercli/main_internal_test.go (1)

116-125: LGTM!

go/internal/toolaliases/aliases.go (1)

19-19: LGTM!

Also applies to: 42-59

go/internal/toolaliases/aliases_test.go (1)

67-73: LGTM!

go/internal/agenthooks/settings.go (1)

186-209: LGTM!

Also applies to: 225-278, 1609-1679

go/internal/agenthooks/settings_probe.go (1)

25-57: LGTM!

Also applies to: 189-211, 240-302, 320-369

go/internal/agenthooks/doctor_contract_test.go (1)

42-45: LGTM!

go/cmd/coding-ethos-run/args.go (1)

13-17: LGTM!

Also applies to: 36-58, 153-164, 176-222, 224-275

go/cmd/coding-ethos-run/dispatch.go (1)

109-109: LGTM!

Also applies to: 161-164, 815-820, 969-981, 1015-1029

go/cmd/coding-ethos-run/hook_policy_paths.go (1)

17-26: LGTM!

go/cmd/coding-ethos-run/main.go (1)

27-27: LGTM!

Also applies to: 39-39, 76-87, 157-157, 185-185, 203-203, 228-236, 396-396, 489-489

go/cmd/coding-ethos-run/main_test.go (1)

64-74: LGTM!

Also applies to: 186-190, 201-363, 543-557

go/internal/agenthookscli/main_internal_test.go (1)

14-14: LGTM!

Also applies to: 76-107, 161-162, 202-257, 259-328

go/internal/mcp/code_intel.go (1)

592-600: LGTM!

Also applies to: 1037-1047, 1908-1931

go/internal/mcp/code_intel_workspace.go (1)

303-303: LGTM!

Also applies to: 340-344, 370-372, 392-392

go/internal/mcp/server.go (1)

61-61: LGTM!

go/internal/mcp/server_test.go (1)

2553-2597: LGTM!

go/internal/mcpcli/main.go (1)

29-33: LGTM!

Also applies to: 63-69

go/internal/memories/memory.go (1)

24-25: LGTM!

Also applies to: 60-60, 191-222, 232-267, 325-344, 353-412

go/internal/memories/memory_test.go (1)

7-7: LGTM!

Also applies to: 147-193

go/internal/syncstate/state.go (1)

766-769: LGTM!

go/internal/hookrunnercli/toolchain_groups_internal_test.go (1)

137-151: LGTM!

tests/lint_capture_support.py (1)

21-48: LGTM!

go/internal/managedcapture/capture.go (1)

696-732: LGTM!

go/internal/managedcapture/capture_test.go (1)

37-69: LGTM!

go/internal/managedcapture/writable_paths.go (1)

99-114: LGTM!

go/internal/sandbox/cgroup_linux.go (1)

7-14: LGTM!

Also applies to: 23-24, 34-52, 85-123

go/internal/sandbox/cgroup_linux_test.go (1)

9-13: LGTM!

Also applies to: 43-112

go/internal/e2e/scenario.go (2)

207-213: LGTM!

Also applies to: 299-325


398-398: 🎯 Functional Correctness

No change needed. The inherited-runtime-context strip list covers the Coding Ethos root-/state/routing envs set by the runtime path/export flow.

go/internal/e2e/scenario_internal_test.go (1)

1-33: LGTM!

go/internal/e2e/sandbox_workflow_test.go (1)

95-108: LGTM!

Also applies to: 332-390

go/internal/e2e/mcp_test.go (1)

34-85: LGTM!

go/internal/hookrunnercli/toolchain_groups.go (1)

897-921: LGTM!

Comment thread .coding-ethos/.gitignore Outdated
Comment thread go/cmd/coding-ethos-run/dispatch.go
Comment thread go/cmd/coding-ethos-run/parent_workflow.go Outdated
Comment thread go/internal/agenthooks/settings_test.go
Comment thread go/internal/agenthooks/settings.go Outdated
Comment thread go/internal/agenthooks/state_artifacts.go Outdated
Comment thread go/internal/agenthookscli/main.go
Comment thread go/internal/hooks/contract_v1.go
Comment thread tests/test_lint_capture_lifecycle.py
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
README.md (1)

1696-1705: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Disambiguate Kimi denial exit codes.

The bullet combines exit-2 policy denial with structured-deny Stop continuation, but go/internal/agenthooks/settings_probe.go:664-707 requires the Stop-continuation probe to exit with code 0. Split these behaviors and document both exit codes explicitly so external supervisors do not treat structured continuation as an exit-2 failure.

Proposed documentation fix
-- Kimi exit-2 policy denial with a stderr reason and structured-deny Stop
-  continuation
+- Kimi policy denial exits with code 2 and writes a reason to stderr.
+- Kimi Stop continuation exits with code 0 and returns a structured deny
+  payload.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 1696 - 1705, Update the Kimi probe bullets in the
README description to separate exit-2 policy denial from structured-deny Stop
continuation. Document that policy denial exits with code 2 and the
structured-deny Stop continuation exits with code 0, so their distinct
supervisor behavior is explicit.
go/internal/codeintelcli/main_internal_test.go (1)

639-649: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Drain stdout while the command runs.

captureStdout calls runCommand before reading reader; if the command writes more than the OS pipe buffer, it blocks before returning and can hang the test. Start io.ReadAll in a goroutine before runCommand, close the writer afterward, then await the reader.

Proposed fix
+	var (
+		output  []byte
+		readErr error
+	)
+	readDone := make(chan struct{})
+	go func() {
+		output, readErr = io.ReadAll(reader)
+		close(readDone)
+	}()
+
 	runCommand()
 
 	os.Stdout = original
 	if err := writer.Close(); err != nil {
 		t.Fatalf("close stdout writer: %v", err)
 	}
 	writerClosed = true
 
-	output, err := io.ReadAll(reader)
-	if err != nil {
-		t.Fatalf("read stdout pipe: %v", err)
+	<-readDone
+	if readErr != nil {
+		t.Fatalf("read stdout pipe: %v", readErr)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@go/internal/codeintelcli/main_internal_test.go` around lines 639 - 649,
Update captureStdout around runCommand so io.ReadAll(reader) starts in a
goroutine before the command executes, allowing stdout to drain continuously.
After runCommand returns, restore os.Stdout, close writer, then await the
goroutine’s output and error while preserving the existing failure handling.
docs/HOOK_CONTRACT_V1.md (1)

192-196: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Update the Kimi timeout contract wording.

Kimi [[hooks]] configs support a timeout field and read it from generated TOML, so this doc should not say Kimi lacks per-hook timeouts. Also add that Kimi limits timeout to 1–600 seconds, while --hook-timeout-seconds is still validated to 1–3600 before rendering.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/HOOK_CONTRACT_V1.md` around lines 192 - 196, Update the timeout contract
paragraph to state that generated Kimi TOML includes the per-hook timeout field,
with Kimi enforcing a 1–600 second limit. Clarify that --hook-timeout-seconds
remains validated to 1–3600 seconds before rendering, and remove the claim that
Kimi lacks per-hook timeout support.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@docs/HOOK_CONTRACT_V1.md`:
- Around line 192-196: Update the timeout contract paragraph to state that
generated Kimi TOML includes the per-hook timeout field, with Kimi enforcing a
1–600 second limit. Clarify that --hook-timeout-seconds remains validated to
1–3600 seconds before rendering, and remove the claim that Kimi lacks per-hook
timeout support.

In `@go/internal/codeintelcli/main_internal_test.go`:
- Around line 639-649: Update captureStdout around runCommand so
io.ReadAll(reader) starts in a goroutine before the command executes, allowing
stdout to drain continuously. After runCommand returns, restore os.Stdout, close
writer, then await the goroutine’s output and error while preserving the
existing failure handling.

In `@README.md`:
- Around line 1696-1705: Update the Kimi probe bullets in the README description
to separate exit-2 policy denial from structured-deny Stop continuation.
Document that policy denial exits with code 2 and the structured-deny Stop
continuation exits with code 0, so their distinct supervisor behavior is
explicit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e6613fb3-17b7-4284-b257-e3e1495fd216

📥 Commits

Reviewing files that changed from the base of the PR and between 9317c1e and 317c6b0.

⛔ Files ignored due to path filters (1)
  • go/go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • .coding-ethos/.gitignore
  • README.md
  • docs/HOOK_CONTRACT_V1.md
  • go/cmd/coding-ethos-run/dispatch.go
  • go/cmd/coding-ethos-run/main_test.go
  • go/cmd/coding-ethos-run/parent_workflow.go
  • go/go.mod
  • go/internal/agenthooks/kimi_settings.go
  • go/internal/agenthooks/settings.go
  • go/internal/agenthooks/settings_test.go
  • go/internal/agenthooks/state_artifacts.go
  • go/internal/agenthookscli/main.go
  • go/internal/agenthookscli/main_internal_test.go
  • go/internal/codeintelcli/main_internal_test.go
  • go/internal/hooks/contract_v1.go
  • go/internal/hooks/contract_v1_test.go
  • tests/test_lint_capture_lifecycle.py
💤 Files with no reviewable changes (1)
  • go/internal/agenthookscli/main.go
📜 Review details
⏰ Context from checks skipped due to timeout. (8)
  • GitHub Check: Coding Ethos SARIF Gate / Coding Ethos SARIF Gate
  • GitHub Check: Unified lint
  • GitHub Check: Go coverage
  • GitHub Check: Test (Python 3.13)
  • GitHub Check: Test (Python 3.11)
  • GitHub Check: Validate GitHub workflows
  • GitHub Check: CodeQL (go)
  • GitHub Check: Go fuzz smoke
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Crash early on ambiguous startup and configuration states instead of degrading silently
Treat required imports as hard dependencies and fail immediately if they are missing (no soft dependency pattern)
Make ruff and mypy blocking quality gates rather than advisory tools
Model required dependencies as non-optional and default to full-strength behavior (no Optional types for required dependencies)
Run required validation unconditionally; a missing component is itself a failure
Validate required capabilities at startup instead of probing for them at runtime
Validate configuration, schema, and extensions during bootstrap rather than on first use
Route configuration through validated bootstrap paths instead of inline shell environment variables
Log important decisions with context and instrument the system with metrics (Radical Visibility)
Define and verify interfaces before writing or referencing implementations (Protocol-First Design)
Resolve lint findings with structural fixes; suppress only with documented necessity
Use Python's functional tools (itertools, functools) when they make code clearer and more local
Keep public behavior documented as part of the interface contract; every public function must have a Google-style docstring
Use precise exception types and actionable, context-rich error messages; all application exceptions should inherit from a base exception with structured context

Files:

  • tests/test_lint_capture_lifecycle.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: Treat tests as executable behavioral contracts and update them with code changes (Testing as Specification)
Prove critical behavior with real functional workflows before relying on unit tests or mocks (Functional Testing Is the Proof)

Files:

  • tests/test_lint_capture_lifecycle.py
**/{hooks,policies,lint-capture,runtime}/**/*.{go,sh,py}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer compiled Go for hook, policy, lint-capture, and runtime glue; treat shell and Python as transitional unless they are clearly the right interface

Files:

  • go/internal/hooks/contract_v1_test.go
  • go/internal/hooks/contract_v1.go
🧠 Learnings (1)
📚 Learning: 2026-06-23T12:26:47.373Z
Learnt from: paudley
Repo: paudley/coding-ethos PR: 258
File: go/internal/geminiprompts/render.go:125-132
Timestamp: 2026-06-23T12:26:47.373Z
Learning: In the paudley/coding-ethos repo, the documented guideline “Gemini prompt pack should be generated in go/internal/geminiprompts/” refers to the generator implementation location (Go source), not the location of the generated prompt-pack artifact. Always treat PromptPackPath as the enforced output artifact path `.coding-ethos/gemini/prompt-pack.json` (e.g., render_test.go asserts PromptPackPath, and compiler_policies.go / hookrunner lookup / README document the expected path). Do not flag a code review issue just because PromptPackPath points to `.coding-ethos/gemini/prompt-pack.json`; only flag violations if the artifact output path logic breaks that enforced contract.

Applied to files:

  • go/internal/agenthooks/kimi_settings.go
  • go/internal/hooks/contract_v1_test.go
  • go/internal/agenthookscli/main_internal_test.go
  • go/internal/agenthooks/state_artifacts.go
  • go/internal/codeintelcli/main_internal_test.go
  • go/internal/hooks/contract_v1.go
  • go/internal/agenthooks/settings_test.go
  • go/internal/agenthooks/settings.go
🔇 Additional comments (18)
tests/test_lint_capture_lifecycle.py (1)

13-22: LGTM!

Also applies to: 25-45

.coding-ethos/.gitignore (1)

3-10: LGTM!

go/go.mod (1)

24-24: LGTM!

Also applies to: 39-60

README.md (1)

1581-1581: LGTM!

Also applies to: 1590-1661, 1673-1677, 1688-1694

go/internal/codeintelcli/main_internal_test.go (1)

27-27: LGTM!

Also applies to: 39-43, 138-138, 465-465, 523-527, 577-581, 676-676, 785-789, 808-808, 817-820, 825-828, 833-836, 889-892, 897-900, 905-908, 913-917, 1340-1344, 1349-1353, 1358-1359, 1413-1413, 1418-1419

go/internal/hooks/contract_v1.go (2)

186-230: Past-flagged provider validation gap is fixed.

The new hookContractV1ProviderFromHint resolves strictly from the declared provider hint (no source/environment fallback) and validateHookContractProvider now rejects both an unresolvable hint and one that maps outside hookContractV1Providers(). This correctly addresses the earlier concern about accepting event.ProviderHint as-is.


337-399: LGTM!

go/internal/hooks/contract_v1_test.go (1)

117-126: LGTM!

docs/HOOK_CONTRACT_V1.md (2)

1-123: LGTM!


124-191: LGTM!

Also applies to: 197-199

go/internal/agenthooks/kimi_settings.go (1)

16-174: LGTM!

go/internal/agenthooks/settings.go (1)

88-88: LGTM!

Also applies to: 110-110, 147-147, 275-276, 1493-1534

go/internal/agenthooks/settings_test.go (1)

77-137: LGTM!

Also applies to: 874-875, 897-904, 918-1065

go/internal/agenthooks/state_artifacts.go (1)

94-153: LGTM!

Also applies to: 180-239

go/internal/agenthookscli/main_internal_test.go (1)

76-107: LGTM!

go/cmd/coding-ethos-run/dispatch.go (1)

983-1002: Past root-precedence issue resolved.

CODE_ETHOS_CONSUMER_ROOT is now sourced from --repo-root (falling back to paths.Root), separate from the settings-root-derived envStateRoot, matching the documented --repo-root/--root/--state-root semantics and covered by TestRunAgentHooksCommandExportsRepositoryRootBeforeSettingsRoot.

go/cmd/coding-ethos-run/main_test.go (1)

231-248: LGTM!

Also applies to: 336-345, 364-397

go/cmd/coding-ethos-run/parent_workflow.go (1)

119-225: LGTM!

Also applies to: 402-412, 954-963

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
@paudley

paudley commented Jul 27, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@paudley

paudley commented Jul 27, 2026

Copy link
Copy Markdown
Owner Author

PR #264 squash notes

Summary:

  • Add provider-neutral hook contract v1, capability discovery, and supervisor-safe hook output semantics.
  • Add private settings overlay, source repo root, and Coding Ethos state root routing for agent hooks, MCP, memory, code intelligence, and runtime policy artifacts.
  • Add native Kimi hook/MCP generation, Kimi output semantics, verification probes, provider capability docs, and configurable hook deadlines.
  • Harden sandbox/cgroup behavior, generated ignore coverage, dependency vulnerability posture, and CLI test stdout isolation.

Notable files:

  • go/internal/hooks/, go/internal/hookcli/: neutral-v1 contract, validation, provider-native output.
  • go/internal/agenthooks/, go/internal/agenthookscli/: Kimi settings/MCP, capabilities, overlay roots, timeouts, state artifacts.
  • go/cmd/coding-ethos-run/*: split-root runtime wiring, external hook/MCP command validation, runtime-policy commands.
  • go/internal/mcp/, go/internal/memories/, go/internal/syncstate/state.go: state-root owned durable data.
  • README.md, docs/HOOK_CONTRACT_V1.md, docs/PROVIDER_CAPABILITY_MATRIX.md: supervisor and provider contract docs.
  • tests/test_lint_capture_lifecycle.py, go/internal/codeintelcli/main_internal_test.go: validation coverage and stdout-capture stabilization.

Validation:

  • make build
  • make check
  • go test -buildvcs=false -timeout=90s -short ./go/internal/codeintelcli -covermode=atomic -coverprofile=/tmp/codeintelcli.out -count=10
  • CI on 4dc9157: Build distribution, CodeQL, Coding Ethos SARIF Gate, Go coverage, Go fuzz smoke, OSV dependency scan, OpenSSF Scorecard, Python 3.11/3.13, Unified lint, Validate GitHub workflows, Zizmor, CLA
  • protected pre-commit and pre-push hook chains passed

Review:

  • CodeRabbit review comments addressed on branch.
  • Current GitHub checks passed on branch head.
  • Current-head CodeRabbit review approved 4dc9157.

Deferral gate:

  • Branch diff scan: no actionable marker hits.
  • PR body/comment scan: no actionable marker hits.
  • Review thread scan: no active unresolved review threads.

Merge notes:

  • origin/main merged before finalization; no conflicts at last sync.
  • No linked issue references were reported by GitHub.

@paudley
paudley merged commit c453973 into main Jul 27, 2026
22 checks passed
@paudley
paudley deleted the agent/nyarlathotep-hooks branch July 27, 2026 22:04
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.

1 participant