- Remove the internal
coding-ethos-run agent-hook -> coding-ethos-hookruntime self-delegation path.coding-ethos-run agent-hookinvokes the hook CLI path in-process with the same compiled bundle and provider output contract, without spawning the separatecoding-ethos-hookbinary. This ban applies to Go runtime paths delegating back out to another generated Go executable; user-facing entrypoint shims such asgitand managed-tool wrappers remain intentional integration surfaces.
Goal: make coding-ethos easy to find, understand, trust, and try from GitHub,
search engines, and AI-agent policy/security searches.
- Configure GitHub repository topics for the core search surface:
ai-agents,mcp-server,git-hooks,static-analysis,devsecops,policy-as-code, andcel. - Update the GitHub repository description so it names the core product surface: AI-agent policy-as-code, MCP, CEL, Git hooks, SARIF, and static analysis.
- Improve the README first screen with badges, a direct value statement, AI-agent search terms, and a 30-second start path.
- Expand the source docs index so MCP, CEL, SARIF, runtime sandboxing, red-team, and roadmap documents are discoverable from one page.
- Add a GitHub social-preview image sized for repository cards and shared links.
- Add an OpenSSF Scorecard workflow and badge; the public score appears
after the first successful
mainrun publishes results. - Track OpenSSF Scorecard gaps after the first release: fuzzing depth, Best Practices registration, tag/release detection, branch-protection ruleset visibility, sustained SAST history, and token-permission drift.
- Register the OpenSSF Best Practices Badge project and add the badge once the public checklist has an issued project URL.
- Document progress toward the OpenSSF Best Practices badge.
- Use OpenSSF Best Practices Gold as an active project checklist:
- Add checked-in
.bestpractices.jsonrepo-hosted evidence. - Drive all generated
Unmetand?criteria to either repo-side remediation or an explicit external blocker. - Raise coverage evidence from the current 80% gate toward Gold-level statement and branch coverage expectations.
- Add assertion-enabled dynamic analysis for critical runtime invariants.
- Require assertion mode in release test/fuzz jobs.
- Resolve review-capacity criteria such as two-person review and unassociated significant contributors when project governance supports them honestly.
- Add checked-in
- Add a small demo walkthrough showing an agent using MCP instead of invoking lint directly.
- Add a short docs landing page optimized for "policy as code for AI agents", "MCP server for static analysis", and "CEL Git hook policy" search terms.
- Add comparison and integration docs for adoption-oriented searches.
- Draft external launch-post copy outside the repo.
- Add a threat model for security-focused project evaluation.
- Add release process docs for public release readiness.
- Add GitHub Discussions setup guidance.
- Improve package metadata keywords, classifiers, and project URLs.
- Add CEL, SARIF CI, command-block, and runtime-sandbox examples.
- Add GitHub Pages Jekyll theme config for the
/docssite. - Add a verified text demo for MCP command checks, managed lint checks, and SARIF output.
- Add an asciinema recording and rendered GIF demo for MCP command checks, managed lint checks, and SARIF output.
- Add docs asset regeneration instructions.
- Cross-link examples to relevant MCP, CEL, SARIF, sandbox, and threat docs.
- Update changelog for discoverability, Pages, examples, and demo assets.
- Document PyPI metadata checks, Trusted Publishing, artifact attestations, SBOM generation, checksums, and verification as release prerequisites.
- Add a local release dry-run target for package metadata, checksums, and GitHub workflow lint.
- Add a package smoke target proving the wheel works outside the source checkout with packaged defaults.
- Decide the correct Go hook runtime publication model for PyPI users: wheel data, companion platform wheels, GitHub release assets, or source checkout bootstrap. Do not bundle binaries into the wheel without a designed upgrade, checksum, and platform strategy.
- Flesh out fuzzing beyond CI smoke coverage: add durable corpus seeds, parser and formatter invariants, crash artifact retention, and a long-running scheduled target for shell parsing, SARIF generation, CEL input construction, and hook event decoding.
Acceptance criteria:
- A first-time visitor can identify the project purpose, supported agents, core enforcement surfaces, and first command within the first README screen.
- GitHub shared links have a clear project visual.
- Security-focused visitors can find trust signals and roadmap status without reading implementation docs first.
Goal: prove the actual coding-ethos workflows users and agents depend on by creating real temporary git checkouts, installing the real hook/runtime path, running real commands, and inspecting real output and repository state.
- Priority: enforce the
No Self-Promotionbranding ban in hooks and CI instead of relying on agent memory or plugin templates.- Add CEL-backed policy expressions to the
no-self-promotionprinciple incoding_ethos.ymlso the source ethos explicitly rejects agent/tool branding in commits, pull request titles/bodies, documentation, and generated artifacts. - Gate agent
PreToolUsecommand payloads that create or edit pull requests, includinggh pr create,gh pr edit, and connector-backed PR creation, when title/body arguments contain prefixes or attribution such as[codex],codex/,Generated with,Co-authored-by: Codex, or equivalent tool branding. - Gate
commit-msgand staged-file scopes for self-promotion text in commit subjects, generated markdown, release notes, PR templates, and agent-authored docs while allowing legitimate references to product paths such as.codex/configuration files. - Add real hook workflow regressions proving the plugin-suggested
[codex]PR title is blocked before GitHub mutation and that a repo-native unbranded title is allowed. - Regenerate
AGENTS.md,ETHOS.md, provider skills, and prompt packs from the source ethos after adding the CEL policy.
- Add CEL-backed policy expressions to the
- Build a Go-based end-to-end test harness that creates isolated git checkouts with known sample files, initializes commits, installs coding-ethos hook/runtime artifacts, and runs ordinary git commands through the same path a user or agent uses.
- Add a successful commit regression: stage a compliant file, run real
git commit, assert the command succeeds, HEAD advances, hook traces are written, and no internal bookkeeping policy is surfaced as a user failure. - Add a failed commit regression: stage a known policy violation, run real
git commit, assert the command fails with the original lint/policy finding, and assertgit.commit_head_advanceddoes not replace or mask that failure. - Add managed lint capture workflow tests that run real managed tools
against reference-repo source files for clean output, warning output with exit
code 0, parseable diagnostics, and unparseable failures; assert
TOON/JSON/SARIF and trace outputs preserve the evidence.
- Add real Ruff scenarios for clean output with exit code 0, parseable Ruff diagnostics, retained lint traces, and SARIF evidence.
- Treat empty machine-readable success payloads such as
[]as silent clean output instead of user-visible linter warnings. - Add JSON-output assertions for the same real managed-tool scenarios.
- Add a real managed-tool failure scenario that proves raw output remains visible and policy/CEL/SARIF evidence is retained.
- Route every pre-commit gate through the normalized
diagnostics/SARIF/CEL path. Gates such as
go-test,go-vet, formatting, manifest checks, generated-config checks, and tool bootstrap checks must produce structured diagnostics that can become SARIF results and CEL inputs; they must not fall back to generic exit-code-only failures except for runner failures where no tool output exists.- Emit file-specific diagnostics for generated-config freshness drift so stale repo-root tool configs appear as SARIF/CEL-addressable findings instead of pathless external-command failures.
- Emit file-specific diagnostics for generated Gemini prompt pack drift.
- Emit provider/skill-path diagnostics for generated agent skill surface drift.
- Convert tool bootstrap and managed-toolchain manifest failures into structured diagnostics with manifest paths, tool names, and repair commands.
- Verify
go-vetfailures produce parser-backed diagnostics in TOON/JSON/SARIF and retain bounded raw output only as supporting evidence. - Verify formatter/checker gates (
go-format,format,shfmt) report changed files as structured diagnostics rather than generic group failures. - Add an end-to-end scenario that runs the real generated-config drift path and asserts trace plus SARIF evidence contains each stale file.
- Restore or replace the temporary GitHub ruleset drift from PR #64: code-owner review, Copilot review, and Scorecard code-scanning requirements need durable policy decisions before the next release.
- Add Go test coverage tracking to the full diagnostics pipeline. Coverage
output should be captured as structured evidence, flow through normalized
diagnostics when thresholds fail, be eligible for SARIF output, and expose
CEL facts so policy can distinguish missing coverage data, below-threshold
packages, and ordinary test failures.
- Parse
go test -json -coverpackage coverage output into non-blocking record diagnostics. - Parse
go tool cover -funcfile/function rows and totals into coverage diagnostics with file, line, package, and percent metadata. - Expose Go coverage diagnostics through the shared CEL
coveragecollection and verify CEL can promote below-floor coverage into a blocking SARIF finding.
- Parse
- Add policy-yaml coverage threshold bands and enforcement modes. Coverage
policy should support high/medium/low thresholds in
coding_ethos.yml, with configurable floors for project, module/package, and file/function coverage. The default policy should require at least 80% coverage where coverage is enforced, expose warning bands below preferred thresholds, and allow CEL to promote below-threshold coverage records into blocking findings. - Suppress routine pass/noise lines in pre-commit gate output while
preserving actionable failure context. For example, passing Go package
lines such as
ok ...should not appear in user-facing hook reports, but failing package names, test names, file/line locations, panic text, and unparseable failure excerpts must remain visible. - Add a shell-parser-backed hook rewrite that detects naked
pythonorpython3invocations and rewrites them touv run pythonwhen the target repo is a uv-managed project. The policy must use parsed command structure, preserve arguments and quoting, avoid string matching, and only rewrite when repo evidence shows uv is the active Python environment contract. - Add hook workflow tests for PreToolUse and PostToolUse payloads from Codex, Claude, and Gemini shapes using real command text, file edits, apply-patch payloads, and provider-specific output fields.
- Add MCP workflow tests that exercise the real stdio framing and request handling path for policy explanation, command checks, code-intel queries, and managed lint advice.
- Add sandbox workflow tests that verify generated tool capabilities, filesystem write allowances, blocked capability requests, and trace/SARIF evidence using the real sandbox planner and available backend behavior. Covered by #129.
- Evaluate whether Go's standard
testingpackage remains sufficient or whether this needs a small internal scenario harness for fixture setup, command execution, output assertions, and trace inspection.
Acceptance criteria:
- The suite fails if a real
git commitpath is broken, even when unit tests for individual evaluators pass. - The suite distinguishes product failures from internal telemetry; internal bookkeeping checks must not become user-facing policy blocks.
- The suite runs in CI on pull requests and has clear local invocation instructions.
- The Go E2E harness applies per-command timeouts and Unix process-group cleanup so a timed-out scenario does not leave child processes running.
- End-to-end tests use real commands, real managed tools, real filesystem state, real Git repositories, real MCP framing, and real trace/SARIF output. AI calls are the default allowed exception because live LLM behavior is nondeterministic and externally controlled.
- No pre-commit gate may bypass normalized diagnostics, SARIF evidence, or CEL policy evaluation. A failing gate must be represented as structured, actionable findings first, with bounded raw output only as supporting evidence for genuinely unparseable failures.
- The end-to-end fake/mock admission policy is documented: every mock, fake executable, fake service, or synthetic fixture requires explicit admin approval before it is added.
- The end-to-end fake/mock documentation requirement is documented: every approved exception must explain why no real alternative was safe or practical, what exact behavior is being replaced, and what risk remains uncovered.
- The end-to-end fake/mock defect ledger is documented: every approved
exception must be listed in
KNOWN_DEFECTS.mdwith an owner, replacement plan, and removal condition.
- Track explicit
rmandgit rmintent in code-intel traces instead of relying only on refresh-time missing-file detection. - Define and implement code-intel database cleanup policy: retention windows, compaction triggers, stale diff-pattern pruning, and whether raw symbol text survives after source deletion.
Goal: make the checked-out coding-ethos repository the single build and
runtime source of truth. Consumer repository hooks should only discover,
repair, and dispatch.
Historical plan: the completed phases below describe the earlier checkout-local runtime. The current worktree-safe contract keeps the selected checkout as source/build authority and installs a byte-verified executable projection in the Git-common
.git/coding-ethos-hooksruntime. Seedocs/HOOK_RUNTIME_BOOTSTRAP.mdfor the superseding architecture.
- Replace the consumer
.git/coding-ethos-hooksruntime cache with checkout-localcoding-ethos/bin/andcoding-ethos/build/artifacts. - Change
make buildso it writes all required hook binaries and compiled runtime files into thecoding-ethoscheckout. - Add
.gitignoreentries for checkout-local runtime outputs:bin/,build/, and any transient bootstrap lock/log files. - Decide the final artifact paths and document them in
docs/HOOK_RUNTIME_BOOTSTRAP.md. - Ensure
make cleanremoves checkout-local runtime artifacts without touching source configuration.
Acceptance criteria:
-
make buildfrom thecoding-ethoscheckout produces every artifact needed for hook execution. - No normal hook path requires
.git/coding-ethos-hooks. - Runtime artifacts are ignored and never staged by default.
- Rewrite installed consumer hook shims so they only discover the repo,
locate
coding-ethos, repair missing artifacts withmake -C ... build, and dispatch to the checkout-local hook binary. - Prefer
$consumer_root/coding-ethosfor checkout discovery and avoid broad filesystem search. - If the checkout is missing, print a direct submodule repair command:
git submodule update --init coding-ethos. - Move versioned bootstrap logic into the
coding-ethoscheckout so the installed parent shim stays small and stable. - Ensure hook dispatch passes the consumer repo root explicitly so submodule and worktree path resolution cannot drift.
Acceptance criteria:
- Installed parent hook files contain no policy selection or policy validation logic.
- Hook dispatch uses binaries from the checked-out
coding-ethostree. - Running hooks from the consumer root and from inside
coding-ethosresolves the same consumer repository.
- Remove lifecycle-hook fatal checks based on policy/source mtimes.
- Bootstrap repair only when required artifacts are missing, unreadable, or non-executable.
- Add a bootstrap recursion guard for repair builds.
- Add an interprocess lock around hook-triggered repair builds.
- Preserve build output when bootstrap repair fails and print the exact command that failed.
- Make Stop/agent lifecycle hooks warn, not fail, for freshness concerns that are not runtime-corrupting.
Acceptance criteria:
- Missing artifacts self-repair by running
make -C "$coding_ethos_root" build. - Two concurrent hooks do not corrupt the runtime output directory.
- Failed repair exits with a precise error and no stale-cache language.
- Runtime mtime drift cannot block an agent Stop hook.
- Keep strict policy freshness checks only in explicit verification paths
such as
make validate,make cutover-verify, and CI. - Add a hash manifest for policy bundle inputs before reintroducing any strict freshness gate.
- Record policy input paths, hashes, and consumer repo config path in the manifest.
- Make
make validatecompare hash manifests instead of mtimes. - Remove or downgrade all runtime messages that say the bundle is stale solely because a source file has a newer mtime.
Acceptance criteria:
- Touching
coding_ethos.ymlwithout changing contents does not make runtime validation fail. - Changing policy input contents is detected by
make validate. - CI and maintainer verification remain strict without blocking lifecycle hooks.
- Add tests for missing binary, missing policy bundle, missing submodule, failed build repair, concurrent bootstrap, and normal dispatch.
- Add a regression test for consumer-root resolution in a Git worktree with
coding-ethosas a submodule. - Add a regression test proving
CODE_ETHOS_CONSUMER_ROOTis not required for normal installed hooks. - Add a test proving the installed shim contains no policy-specific logic.
- Add a test proving mtime drift does not fail Stop/agent hook execution.
Acceptance criteria:
- Tests fail against the legacy
.git/coding-ethos-hooksruntime-cache model and pass against checkout-local runtime artifacts. - Worktree/submodule path resolution is covered.
- Hook-triggered repair behavior is covered without relying on real global machine state.
- Update
pre-commit/PRE-COMMIT.md,pre-commit/hooks/HOOKS.md, and README install guidance once the implementation changes land. - Add a migration note explaining that
.git/coding-ethos-hooksis legacy and can be deleted after checkout-local runtime is installed. - Update
make helpdescriptions to distinguish build, install, validate, and cutover responsibilities. - Update hook failure messages so they point to
make -C <coding-ethos> buildorgit submodule update --init coding-ethos, not generic stale runtime repair.
Acceptance criteria:
- A new contributor can recover from missing runtime artifacts by following the hook error text alone.
- Documentation no longer describes
.git/coding-ethos-hooksas the target runtime model. - The migration path is explicit and does not require manual edits inside
.git.
- Add a checkout-local Go bin directory for third-party Go tools.
- Add a source-install wrapper that installs into managed checkout-local prefixes instead of host-global paths.
- Add a GitHub-release binary installer as the starting point for pinned binary tool installs.
- Install
shfmtthrough the managed Go bin path and treat it as a required runtime artifact. - Prepend managed toolchain directories to hook runtime
PATHbefore dispatching to Go hook code. - Migrate ShellCheck, actionlint, hadolint, and golangci-lint to pinned managed installers.
- Record managed tool versions and checksums in a toolchain manifest.
Acceptance criteria:
- Hook execution does not require host
shfmtonPATH. - Missing managed
shfmtself-repairs throughmake -C <coding-ethos> build. - All binary linters used by hook groups resolve from the managed
toolchain before host
PATH.
These items came from an adversarial SOLID review of the hook runtime. They are not blockers for the package-relative path fix, but they should be handled before the next broad hook expansion.
- Consolidate tool/runtime policy metadata currently split across
go/toolcatalog/catalog.go,go/internal/hooks/lint_tool_capture.go,go/cmd/coding-ethos-hook-runner/hook_groups.go, andgo/cmd/coding-ethos-hook-runner/toolchain_groups.go. - Move duplicated evidence-map policy out of hook group execution and the compiled policy path into one shared policy source.
- Split
hooks.RunWithRegistryso event parsing, policy evaluation, tool rewriting, output rendering, and trace logging have narrower ownership. - Keep lint and policy semantics out of generic hook-output formatting; output packages should render normalized results, not decide enforcement behavior.
- Slim
toolcatalog.Toolinto smaller capability interfaces so adding a captured tool does not require unrelated fields and switch expansion. - Replace hook-group switch dispatch with registry-driven evaluators that can be extended from compiled config data.
- Separate capture execution IO, parser selection, lint-log persistence, and user-facing rendering into testable components.
- Replace the remaining shell-owned lint capture entrypoint with Go so capture, target resolution, config enforcement, and output normalization all live in compiled hook code instead of shell glue.
- Parallelize hook execution: inter-group concurrency for analysis groups,
intra-group concurrency via
ParallelAfterfor thegogroup, per-language parallel formatter lanes, AI groups gated on prior success. - Add incremental linting:
golangci-lint --new-from-rev=HEADfor pre-commit, full lint for pre-push.
Do these before replacing the remaining shell-owned lint capture entrypoint.
- Move lint target resolution into Go, including package-relative roots, invocation subdirectories, globs, missing paths, and repo-escape rejection.
- Expose merged consumer config and policy-root data through one Go helper instead of rediscovering config paths in each command.
- Define a Go capture request model containing tool name, original argv, invocation cwd, consumer root, ethos root, managed tool path, output format, and trace root.
- Move managed tool executable and wrapper path resolution behind
toolcatalogcapability APIs. - Generate lint tool shims from
toolcatalog.CapturedLintTools()rather than maintaining a shell-owned tool array. - Make generated-tool-config integrity checking callable as Go code before any captured linter executes.
- Add behavior-preserving tests for rewritten commands,
ruff,mypy, one managed binary linter, malicious absolute paths, globs, package-relative paths, and drifted generated configs. - Slim
toolcatalog.Toolor add focused capability views such asCaptureSpec,RuntimeSpec, andFileMatchSpec. - Document the intended Go lint capture flow: shim -> Go dispatcher -> capture request -> managed tool -> normalized lint result.
Goal: make every managed tool, formatter, test gate, and quality gate flow through one catalog-backed diagnostics contract. The tool catalog, parser registry, managed-capture allow list, formatter handling, and SARIF/CEL evidence must not drift.
- Merge the tool catalog, parser registry, and managed-capture tool list into one source of truth. There should be one catalog, period: each tool entry declares execution, capabilities, parser/producer type, output contract, formatter behavior, SARIF/CEL support, and any explicit exception rationale.
- Add a catalog invariant test requiring every hook-owned tool to declare
one of:
- a registered central diagnostics parser;
- a first-class formatter changed-file producer;
- a first-class internal structured diagnostic producer;
- an explicitly justified generic fallback exception.
- Add real-output parser fixtures for every managed tool. Each fixture must
prove parse status is
parsed,empty, orchanged_files;parse_errorshould only appear for genuine runner/tool failures and must remain visible.- Split diagnostics parser implementations into focused files for core registry/shared parsing, Go tools, Python tools, test-output tools, and static/config tools instead of growing one large parser file.
- Parse stdout and stderr according to a tool-specific stream policy instead of using the first non-empty stream. Tools that emit actionable diagnostics on both streams must preserve both streams as structured diagnostics or bounded evidence.
- Replace formatter fallback handling with first-class changed-file
diagnostics. Mutating formatters should report which files changed, what tool
changed them, and how that maps to SARIF/CEL evidence instead of relying on
ad hoc stdout parsing.
- Preserve formatter argument context in changed-file diagnostic metadata so traces can explain the rewrite scope.
- Move
radon-complexity,radon-maintainability,vulture,gofmt-check,pytest-gate, andgemini-checkinto the central diagnostics path or a formal diagnostic-producer interface. Bespoke hookrunner parsing must not remain a parallel reporting path.- Add central
radon-complexityandradon-maintainabilityparsers. - Add a central
vultureparser. - Route
gofmt-checkhook findings through the central diagnostics parser. - Add a central
pytest-gateparser for file/line pytest failures. - Route pytest gate failures through the central diagnostics parser when parseable file/line output is available.
- Add a central
geminiparser for Gemini JSON violations.
- Add central
- Add a dedicated
go-vetparser or diagnostic producer instead of relying on generic fallback parsing. - Verify
go-testcommand construction and parser alignment end to end: the executed command must emit JSON, the parser must suppress routine passing package noise, and failures must become SARIF/CEL-addressable diagnostics. - Normalize internal quality gates that already construct findings directly
so they are treated as first-class diagnostic producers with the same trace,
SARIF, CEL, policy, skill, and remediation metadata as external tools.
- Route Radon complexity and maintainability commands through managed capture instead of bespoke hook-report output.
- Route Vulture through managed capture while preserving whitelist, confidence, and exclude arguments.
- Add a
hookReporttolint.Resultbridge so remaining internal reports can render SARIF from normalized diagnostics instead of bespoke text-only structures. - Add shared trace IDs to
hookReportoutput so internal gate denials expose a correlation ID in TOON, JSON, human, and SARIF formats. - Add shared policy/code/skill defaults for
hookReportdiagnostics so older internal gates do not emit anonymous SARIF/CEL findings when callers omit per-finding metadata. - Add a shared
emitHookReportpath that logs normalized internal reports as lint traces before rendering them. - Migrate manifest validation, module documentation, comment suppression, and Python version consistency reports to the trace-logging emitter.
- Migrate Python policy, SQL/direct import, pytest-gate, plan-completion, gofmt-check, and external quality reports to the trace-logging emitter.
- Migrate runtime ignore checks to the trace-logging emitter with structured policy, skill, file, and remediation metadata.
- Add docstring coverage SARIF output backed by normalized hook findings for missing public symbol docstrings.
- Assess
shfmtfor uplift from medium quality to high quality. Prefer exact changed-file or hunk diagnostics over file-only diff-header parsing.- Parse unified-diff hunk locations so shfmt findings identify the changed region instead of defaulting every file to line 1.
- Assess
yamllintfor uplift from medium quality to high quality. Confirm parser behavior for paths containing colons and add fixtures for multiline or unusual YAML diagnostics.- Add a parser fixture for YAML file paths containing colons.
- Add parser coverage for multiple diagnostics in one parsable output.
- Assess
tombifor uplift from medium quality to high quality. Prefer structured output if available; otherwise harden ANSI stripping, multiline locations, and schema-error fixtures.- Add parser coverage for ANSI-colored diagnostics, schema-style warning
output, intervening help lines, and delayed
at file:line:columnlocations.
- Add parser coverage for ANSI-colored diagnostics, schema-style warning
output, intervening help lines, and delayed
- Assess
dotenv-linterfor uplift from medium quality to high quality. Confirm stable plain output across versions and add fixtures for empty files, missing files, and multi-file output.- Add parser coverage for routine/no-problem lines, multi-file output, diagnostics with and without line numbers, and missing-file diagnostics.
- Assess
go-vetfor normalization and uplift to high quality. Capture package context, file/line diagnostics, and runner errors without raw-output leakage.- Preserve Go package headers as diagnostic metadata while suppressing them as standalone user-facing noise.
- Assess
gofmt-check/gofmtfor normalization and uplift to high quality. Treat filename-list output and formatter rewrites as structured changed-file diagnostics.- Add a central filename-list parser for
gofmtandgofmt-check. - Use catalog-backed diagnostic contracts for both check and formatter modes so Go formatting results no longer need hookrunner-specific parsing.
- Add a central filename-list parser for
- Assess
python-complexityfor normalization and uplift to high quality. Move Radon JSON parsing into the central diagnostics layer and preserve symbol names, complexity values, thresholds, and AST identity where available.- Add a central Radon complexity JSON parser with complexity metadata.
- Route the hook command through managed capture so complexity findings produce trace, SARIF, CEL, skill, and remediation metadata.
- Assess
python-maintainabilityfor normalization and uplift to high quality. Remove tool-name drift, preserve maintainability index values, and decide whether advisory results are recorded as SARIF evidence.- Add a central Radon maintainability JSON parser with MI metadata.
- Route the hook command through managed capture so advisory MI findings are recorded as normalized diagnostics instead of side-effect-only parsing.
- Assess
python-vulturefor normalization and uplift to high quality. Preserve confidence, symbol kind, whitelist evidence, and file/line locations in structured diagnostics.- Route the hook command through managed capture so unused-code findings produce trace, SARIF, CEL, skill, and remediation metadata.
- Assess
gemini-checkfor normalization and uplift to high quality. Preserve model/check/batch metadata while routing violations and API/parser failures into the same diagnostics/SARIF/CEL evidence model.- Add a central Gemini JSON violation parser.
- Assess
pyupgradefor normalization and uplift to high quality. Treat syntax rewrites as changed-file diagnostics and preserve the configured Python target version as evidence.- Add generic formatter changed-file diagnostics for successful rewrites.
- Preserve formatter invocation arguments in trace metadata, including the
configured
--pyNN-plustarget flag used by pyupgrade.
- Assess
ruff-formatfor normalization and uplift to high quality. Use Ruff parser support or changed-file diagnostics rather than generic fallback. - Assess
golangci-lint-formatfor normalization and uplift to high quality. Detect formatter rewrites and route any tool warnings through the centralgolangci-lintparser where possible.- Add generic formatter changed-file diagnostics for successful rewrites.
- Preserve formatter invocation arguments in trace metadata.
- Assess
golinesfor normalization and uplift to high quality. Treat line wrapping rewrites as changed-file diagnostics and preserve configured width as evidence.- Add generic formatter changed-file diagnostics for successful rewrites.
- Preserve formatter invocation arguments in trace metadata.
- Assess
pytest-gatefor normalization and uplift to high quality. Prefer machine-readable pytest output where practical, preserve failing tests, file/line context, coverage facts, and traceback excerpts as bounded evidence.- Add a central pytest text parser for file/line failures.
- Parse pytest
FAILED ... - ...andERROR ... - ...summary lines into structured diagnostics with test-name metadata where available. - Parse pytest coverage
TOTALrows into diagnostics with coverage percentage metadata. - Add dedicated CEL policy inputs for pytest coverage totals and per-package coverage rows.
Acceptance criteria:
- Adding a managed tool requires changing one catalog entry and fixtures,
not parallel parser, capture, hookrunner, and SARIF lists.
- Catalog tests now fail when a registered parser lacks a catalog declaration or when a hook-owned tool lacks a diagnostic contract.
- Finish removing direct hookrunner quality-gate emitters so no new tool needs a hookrunner-specific reporting branch.
- Every non-empty tool output is either parsed, intentionally represented as
changed-file evidence, or reported as an unparseable tool failure with bounded
evidence.
- Managed capture tests cover parsed output, stdout/stderr preservation, formatter changed-file evidence, empty machine-readable success output, and unparseable tool failures.
- Formatter, linter, test, AI-review, and internal policy outputs all reach
SARIF and CEL through the same normalized diagnostics contract.
- Formatter changed-file evidence, linter parser diagnostics, Radon, Vulture, go-test, pytest-gate, and Gemini violations now use central diagnostics.
- Finish first-class diagnostic producer interfaces for generated-config, manifest, docstring coverage, and other internal policy-only reports.
- Add SARIF rendering support for existing
hookReport-based internal reports while the remaining producers are migrated. - Add SARIF diagnostics for docstring coverage threshold failures.
- No hook-owned tool can silently bypass parser quality checks because it is
absent from a secondary registry or allow list.
-
CapturedLintTools()is derived from catalog metadata, and tests assert parser registry/catalog consistency.
-
These are larger roadmap items for moving coding-ethos from a local hook and
generated-context system into a broader policy platform for AI-assisted
engineering. The common goal is defense in depth: prevent bad actions early,
explain violations in agent-native formats, and keep organization-specific
policy editable without weakening the compiled enforcement core.
Open issues #52 through #62 describe one coherent Agent Proxy program. The feature work should not start as one-off wrappers around individual tools; it needs a shared proxy substrate that routes agent/API/tool traffic through the same AST/CEL/SARIF, code-intel, sandbox, and remediation architecture already used by hooks.
- Define the Agent Proxy threat model and trust boundary for outbound provider API inspection, inbound tool-call inspection, local tool output transforms, and file-edit mediation. Include explicit CA/TLS interception risks, provider-protocol maintenance risks, and operator opt-in requirements. Foundation for #52.
- Define a provider-agnostic proxy event envelope for outbound prompts, inbound model responses, tool-call requests, tool-call outputs, file reads, directory listings, file edits, search requests, and remediation actions. The envelope must carry provider, model, session ID, tool name, target paths, payload hashes, token estimates, trace IDs, and policy evidence. Foundation for #52-#62.
- Add provider protocol adapters for OpenAI, Anthropic, and Gemini payload
schemas behind a narrow interface. Adapters should extract messages,
attachments, tool calls, tool results, and streaming chunks without exposing
raw provider JSON to policy code. Foundation for #52, #56, and #57.
- Pure
agentproxy/adapterpackage (OpenAI/Anthropic/Gemini + registry) normalizing request messages, tool definitions, response assistant text, and tool calls into hashes-onlyProviderEvents. See #223. - SSE (
text/event-stream) responses are reconstructed: the proxy tees a bounded copy of the verbatim stream and the matched adapter parses the accumulated events into the same structural facts as a non-streamed body (streaming_reconstructed). Oversized streams still forward verbatim but are markedpayload_too_large_for_normalization;streaming_not_normalizednow only appears as a graceful fallback for an unparseable stream.
- Pure
- Add a proxy session ledger in the repo-local code-intel store for read events, directory-listing events, prompt/tool payload hashes, token counts, cache hits, truncation decisions, policy injections, and edit attempts. Foundation for #53, #55, #56, #57, #58, and #62.
- Add tokenizer abstraction and calibrated token-estimate tests. The first implementation may use a conservative local estimator, but the interface must support provider/model-specific tokenizers without making enforcement depend on network access. Foundation for #55, #57, #58, and #59.
- Build a content-transform pipeline for proxy outputs with ordered stages: DLP/policy inspection, exact diagnostic extraction, stack-trace preservation, token budgeting, semantic pagination, compression, and final trace/SARIF evidence. Foundation for #55, #57, and #58.
- Add code-intel query APIs for compact AST anatomy maps, repo maps, semantic chunk pagination, exported symbol summaries, approximate token sizes, and nearby related symbols. Reuse DuckDB/FTS/duckdb-vss storage rather than reparsing in the proxy. Foundation for #54, #58, #59, and #61.
- Add semantic-search and grep-augmentation contracts that combine exact search, AST filters, FTS, vector search, path constraints, and result expansion. Results must cite file, symbol, line range, content hash, and index freshness. Foundation for #61.
- Add a SEARCH/REPLACE patch engine with exact-one-match validation,
content-hash preconditions, AST-aware affected-symbol reporting, rollback on
failure, and normalized diagnostics when a search block is missing,
non-unique, or stale. Foundation for #62.
- First enforced slice: reusable exact-one-match patch validation plus
PreToolUse blocking for existing-file
Writerewrites and concreteEdit/MultiEditsearch blocks that are empty, missing, or non-unique. - Extend patch outcomes with AST affected-symbol evidence and durable proxy trace/code-intel storage.
- First enforced slice: reusable exact-one-match patch validation plus
PreToolUse blocking for existing-file
- Add a transactional edit/remediation workspace for lint shielding: apply proposed edit, run managed autofixers and syntax checks, classify autofix-only changes versus semantic changes, emit a diff, and require policy approval before returning a modified result to the agent. Foundation for #60.
- Add just-in-time policy injection selection that maps proxy events to exact ETHOS principles, skills, and MCP policy explanations. Injection must be deterministic and evidence-backed, not generic vector-RAG over policy prose. Foundation for #56.
- Add DLP facts and CEL scopes for outbound provider payloads and local tool outputs: secret-like values, protected paths, large binary payloads, credential filenames, ignored directories, and policy-sensitive source snippets. Foundation for #52 and #57.
- Extend trace, SARIF, and code-intel schemas for proxy denials,
transformations, cache hits, token truncation, policy injections, semantic
search results, and patch outcomes. Foundation for #52-#62.
- Add the first code-intel proxy session/event ledger for provider calls, file reads/listings, payload hashes, token counts, cache hits, injections, truncations, edits, and transform records.
- Add proxy event correlation, DLP facts, policy evidence, payload kind, direction, cache key, and transform metadata to the code-intel ledger.
- Add proxy result properties and ingestion fields for SARIF.
- Enforce outbound DLP via principle-owned
scope: proxyCEL policies on intercepted provider requests: scan body-free DLP facts, evaluate the seedproxy.outbound_exfiltrationpolicy, deny exfiltrating requests with a 403 coding-ethos body before they reach the provider, and record aDecision="deny"proxy event with the policy id, DLP facts, andproxy_*SARIF metadata. Enforcement is non-optional and fail-closed; the secret value is never retained. E2E coverage ingo/internal/e2eproves the block, the not-received provider, the deny ledger event, and retention. (#224) - Add inbound tool-call enforcement and a proxy-denial MCP tool so denials are explainable through the MCP policy tools. (#235)
- Add first-class proxy trace files and trace ingestion for proxy decisions and transformations.
- Add an Agent Proxy E2E harness with fake provider endpoints and real local tools/files. The harness must test API inspection, file-read caching, anatomy map injection, output compression, token hard stops, semantic pagination, semantic search, search/replace patching, and lint shielding. Fake provider behavior must be documented under the existing E2E mock/fake exception policy. Foundation for #52-#62.
- Document the Agent Proxy operator model: opt-in installation, CA lifecycle, supported providers, sandbox routing, privacy boundaries, failure modes, and how proxy decisions relate to existing hooks and MCP. Foundation for #52-#62.
Acceptance criteria:
- Agent Proxy feature work has one event model, one session ledger, one policy-evaluation path, one trace/SARIF evidence path, and one code-intel retrieval path.
- Proxy decisions can be explained through the same MCP policy tools and ETHOS/skill mappings as hook decisions.
- No proxy feature silently edits, truncates, injects, or suppresses data without a traceable policy decision and replayable evidence.
- TLS/API interception remains an explicit, documented operator choice and never becomes an invisible default.
- Branch plan: deliver MCP over stdio first, backed by the compiled policy bundle and generated skill data already used by hooks.
- Branch plan: expose
coding-ethos-mcpas a repo-local Go binary and routebin/coding-ethos-run mcpthrough it. - Implement a Model Context Protocol server for
coding-ethos. - Expose policy and skill queries for command checks, proposed edit checks, managed lint capture, compiled lint checks, lint advice, policy explanations, remediation lookup, task-based skill recommendation, and capability metadata.
- Keep static generated docs and skills as durable fallback context while allowing Claude, Codex, Gemini, Cursor, and compatible clients to request focused context on demand.
- Add tests proving MCP responses come from the same compiled policy bundle and ETHOS skill data used by hooks.
- Go-ify branch task: replace the
start_hook_logshell wrapper inbin/coding-ethos-runwith a Go-owned logging dispatcher so metadata, stdout/stderr capture, repo-ignore validation, and sanitized event traces share one compiled implementation.
Acceptance criteria:
- Agents can query whether a proposed file path, command, or edit violates policy before attempting the action.
- MCP responses are compact, auditable, and linked to ETHOS principles and skill IDs.
- The server does not create a bypass path around hook enforcement.
Decision: use CEL as the first policy-language backend. CEL is the better
initial fit because coding-ethos needs fast, embedded, deterministic,
typed expressions over already-normalized hook/lint inputs. Keep OPA/Rego as a
future optional backend for larger set/query policies only if CEL expressions
become too limited.
- Add
docs/POLICY_LANGUAGE_STRATEGY.mdas the design record for the CEL-first decision and Rego deferral. - Add a
policy.expressionssection toconfig.yamlandrepo_config.yamloverlays with explicit fields forid,description,scope,severity,principle_ids,skill_id,when,message, andadvice. - Compile CEL expressions into the policy bundle during
coding-ethos-policy compile; syntax, type, and unknown-variable failures must fail bundle compilation. - Define stable typed CEL input objects for the first supported command
policy slice:
command,argv,files,cwd,scope, andmetadata. - Extend typed CEL input objects to diagnostic, finding, repo, and path scopes.
- Keep all host access out of CEL. CEL policy may inspect only the input object and static bundle data; file IO, Git calls, network access, time, and environment access remain first-party Go responsibilities.
- Add an expression evaluator to the existing compiled evaluator registry
so CEL-backed policies emit normal
policy.Decisionanddiagnostics.Diagnosticvalues. - Support deterministic reusable helpers only through reviewed Go-provided CEL functions, starting with path classification, glob matching, suffix/prefix helpers, and collection checks.
- Require every expression-backed policy to map to ETHOS principles and, where possible, a generated skill ID so output remains explanatory rather than bare rule text.
- Add a CLI explain mode that shows CEL source, compiled input schema, matched evidence fields, and the ETHOS/skill mapping for an expression policy.
- Add golden tests for TOON, JSON, and human output for CEL-backed command, file, diagnostic, and lint-finding policies.
- Add negative tests for unsafe functions, unknown variables, type errors,
non-boolean
whenexpressions, missing ETHOS mappings, and invalid override merges. - Add migration guidance for moving small hardcoded evaluators into CEL only when doing so reduces Go code without weakening diagnostics or safety.
- Revisit OPA/Rego only after CEL ships and real policies demonstrate a need for package-level rules, partial evaluation, large static data sets, or complex set joins.
Acceptance criteria:
- A consuming repo can define a non-trivial custom policy without changing Go source.
- CEL expressions are compiled and type checked before hook runtime.
- Expression policies emit the same normalized diagnostics, ETHOS links, skill hints, traces, and TOON/human output as compiled evaluators.
- Unsafe, non-deterministic, networked, or host-dependent policy execution is impossible from expression policy.
- Direct hook, agent-hook, lint-capture, and future MCP paths all evaluate the same compiled expression policies.
- Rego is not introduced unless a written design record identifies a concrete CEL limitation and a bounded integration surface.
The current CEL work is a typed custom-policy extension point. These items define what is required before CEL can be treated as a complete generic policy engine rather than a companion to first-class Go evaluators.
- Define and version a stable policy object model for CEL inputs covering command, argv, tool, event, provider, cwd, repo, path, paths, file, files, file changes, diagnostic, finding, diff, Git facts, config facts, and safe metadata.
- Remove aspirational CEL fields: every exposed field must be populated reliably for its scope, or removed until the runtime can provide it.
- Populate real typed inputs for hook command scope, file/path scope, lint finding scope, Git scope, config scope, and diff scope.
- Add typed
git_commandCEL facts for normalized Git argv, subcommand, global options, subcommand args, flags, targets, andgit -Cdetection. - Add typed
file_changesCEL facts for staged file status, byte size, line count, generated/test/protected classification, and original line count when Git can provide it. - Migrate the first tiny Git evaluators to CEL-backed policies:
git.change_dir_flag,git.destructive_worktree, andgit.stash_blocked. - Move the large-file and line-limit policies out of config-owned Go
evaluators and into principle-local CEL expressions in
coding_ethos.yml. - Treat
coding_ethos.ymlas the policy backbone: new shared policy should live with the ETHOS principle it enforces; config remains an artifact and overlay surface for policy not yet expressed properly in ETHOS. - Replace hand-rolled shell command tokenization in agent hook paths with a
proper shell AST parser (
mvdan.cc/sh/v3/syntax), deny malformed shell text at the hook boundary, and feed normalizedshell_commandsfacts into Go and CEL policy. Keep Git wrapper execution on argv-based Git option parsing because wrapper commands have already been parsed by the shell. - Migrate more brittle command-string CEL examples and hook predicates to
shell_commandsfacts instead of rawcommand.contains(...)matching. - Use parser-backed shell facts to distinguish direct
git,command git,env git,bash -c 'git ...', pipelines, grouped commands, and background commands before deciding whether to rewrite or block agent hook input. - Use parser-backed shell facts to route lint tools consistently through
capture for direct invocations,
uv run,python -m, leading assignments, chained commands, redirects, and pipelines. - Add higher-level CEL shell command facts such as
is_git,is_lint_tool,is_shell_exec,uses_path_override,has_command_substitution,has_process_substitution, andhas_dynamic_expansionso CEL policies stay readable. - Block or constrain ambiguous shell constructs around protected tools:
eval, shell functions/aliases masking protected commands, command substitution, process substitution, here-doc command execution, andbash -c/sh -cunless recursively parsed and approved. - Improve agent remediation messages for shell policies so they identify the exact command node, argument, redirect, assignment, or pipeline segment that triggered the decision.
- Reuse the shell AST parser for
.shpolicy: reject parse errors, detect raw protected-tool invocations, unsafeeval, risky redirects, and shell-script bypass patterns structurally instead of regex-only checks. - Use shell AST positions in SARIF where possible so shell-script and hook-command findings can point to exact command spans rather than only the whole command or whole file.
- Replace first-file
pathsemantics with explicit multi-file collection semantics such aspaths.exists(...),paths.all(...),files.changed_matching(...), andfindings.exists(...). - Make dispatch policy-driven so expression config declares hook events, tools, lint tools, modes, defense layers, principle IDs, and skill IDs without hardcoded evaluator registration.
- Compile and cache CEL programs during bundle compilation or bundle load rather than recompiling expressions at evaluation time.
- Add controlled policy inheritance and override rules for expression policies, including forbidden shadowing of protected built-ins and explicit rules for severity weakening.
- Ensure every CEL policy emits the same normalized result shape as Go evaluators: policy ID, severity, decision, message, suggestion, principle IDs, skill ID, evidence, diagnostic location, remediation hint, and explanation metadata.
- Expand the reviewed helper library with pure typed helpers for glob matching, path classification, test/generated/protected detection, lint code matching, command-tool detection, inline-env detection, repo config presence, and protected-branch facts.
- Add first-class explain output for CEL decisions showing the expression, available input schema, helper functions, matched evidence, ETHOS grounding, and skill/remediation path.
- Keep the CEL boundary pure by design: Go prepares facts; CEL decides over facts. CEL must not read files, execute shell/Git, inspect environment, access the network, or depend on wall-clock time.
- Add operator documentation for supported scopes, input schemas, helper functions, dispatch, severity, examples, anti-patterns, and migration rules.
- Add a trust-building test matrix for unknown fields, type failures, unknown helpers, multi-file semantics, hook/lint dispatch, inheritance, shadowing, explain-output golden files, trace output, malicious config, and performance with many expression policies.
Acceptance criteria:
- Repo policy authors can express most simple and medium-complexity rules in checked-in ethos/config YAML without changing Go source.
- Policy authors get compile-time failures for unknown fields, invalid types, invalid helpers, unsafe host access, and invalid dispatch.
- Direct hook, agent-hook, lint-capture, explain, trace, CI, and future MCP paths cannot distinguish CEL-backed and Go-backed policies except by implementation metadata.
- Multi-file and multi-finding policies are explicit and deterministic; no policy depends on implicit "first file" ordering.
- Protected core policies remain non-shadowable and non-weakenable unless a protected source explicitly permits it.
- Go evaluators remain only for complex parsing, expensive analysis, Git state modeling, managed toolchain behavior, path normalization, and other reviewed security-sensitive operations.
- Add richer diff hunk and line-range facts once the runtime has a reviewed Go diff parser shared by hook, lint, CI/SARIF, and MCP paths.
- Add provider-native event fields beyond provider/event/tool/scope only after all supported agents can populate the field consistently.
- Build a VS Code/Cursor extension that invokes
coding-ethos-policyandcoding-ethos-lintin the background. - Surface policy and lint diagnostics at edit time instead of waiting for Git hooks.
- Provide quick access to relevant ETHOS principles and generated skills from diagnostics.
- Detect protected-path edits, hook tampering attempts, bare exception patterns, suppressions, and other high-value failures before a diff is applied.
Acceptance criteria:
- The extension uses the same compiled bundle and managed toolchain as CLI and hook execution.
- Diagnostics are low-noise, actionable, and grouped by file and policy.
- The extension is advisory by default but can enforce blocking behavior in managed workspaces.
- Add SARIF output for normalized policy and lint diagnostics.
- Provide native GitHub Actions and GitLab CI examples.
- Package reusable GitHub Actions and GitLab CI components.
- Ensure CI runs the same compiled policy bundle and managed toolchain versions as local hooks.
- Publish violations as PR annotations and, where supported, security/code scanning findings.
- Document expanded SARIF product uses in
docs/SARIF_USES.md.
- Keep code-scanning SARIF actionable: record-only policy context remains in TOON/JSON traces and must not upload as root-level warning results.
- Omit pathless policy results from code-scanning SARIF so GitHub does not
reject uploads and coding-ethos does not invent noisy alerts at
.line 0. - Add MCP remediation endpoints that accept a SARIF run or trace ID and
return focused ETHOS-grounded repair advice.
- Add
sarif_remediation_advicefor SARIF JSON payloads, selected results, CEL provenance, skill context, and MCPlint_checkrerun guidance. - Add retained lint trace ID lookup through the configured consumer
root's
.coding-ethos/lint-runs/directory.
- Add
- Add cross-tool finding grouping using SARIF fingerprints, policy IDs, skill IDs, and source locations.
- Emit policy coverage summaries that show which ETHOS principles,
policies, skills, and tool families ran for a commit or PR.
- Start the coverage ledger by emitting SARIF
runs[].properties.policy_coveragefor normalized decisions and diagnostics, including CEL provenance when available.
- Start the coverage ledger by emitting SARIF
- Add SARIF trend analysis for newly introduced, reopened, fixed, and
worsening findings across commits.
- Add first
sarif_trend_analysisMCP compare path for introduced, fixed, and persisting findings across SARIF payloads or retained lint traces. - Add baseline-history semantics for reopened and worsening findings.
- Add first
- Produce compact PR risk summaries from SARIF and
.coding-ethostraces for agents and reviewers.- Add first SARIF-only
sarif_risk_summaryMCP tool for result counts, blocking/security counts, policy/skill/tool/file hotspots, finding groups, and next remediation calls. - Fold retained lint trace evidence into the summary through the same safe trace ID lookup.
- Add first SARIF-only
- Retain SARIF plus trace artifacts as an audit evidence bundle in CI.
- Define an IDE/editor diagnostic integration path that consumes the same SARIF output used by hooks and CI.
- Report unmapped diagnostics, noisy rules, missing skill IDs, and weak severity mappings as policy-authoring feedback.
Acceptance criteria:
- A repo can gate PRs in CI even if local hooks are bypassed.
- SARIF includes policy IDs, ETHOS principle IDs, skill IDs, file/line locations, remediation advice, and stable rule metadata.
- CI output remains compact for agents while preserving full artifacts for audit.
- SARIF can act as a shared evidence ledger for hooks, CI, MCP, agent remediation, audit review, and editor diagnostics without creating a second policy interpretation path.
Goal: complement CEL and Go policy evaluation with an OS-level data-plane boundary for managed hook, lint, and agent-invoked tool execution. CEL remains the control plane that decides which action and capabilities are allowed; the sandbox enforces filesystem, network, process, syscall, timeout, and resource limits at runtime.
- Write a design record for runtime sandboxing that explicitly rejects
LD_PRELOADas a security boundary because it is bypassed by static binaries, direct syscalls, environment scrubbing, and modern Go/Rust toolchains. - Define a tool capability model in
toolcatalogand compiled policy data: read paths, write paths, network access, process visibility, Git access, environment access, timeout, memory, CPU, and sandbox profile. - Add CEL-visible capability facts so policies can require explicit ETHOS approval for risky capabilities such as network, broad write access, raw Git, process inspection, or privileged filesystem paths.
- Add the first CEL deny-by-default network capability policy: managed
tools must declare
requires_network, and agent-invoked network-capable tools require explicit approval before execution. - Prototype a Linux sandbox runner using Bubblewrap (
bwrap) before writing raw namespace code, with a Go-owned request model and no shell glue.- Add
go/internal/sandboxwith Bubblewrap command construction, platform-derived sandbox requirements, backend-unavailable denials, and unit tests. - Wire managed lint capture to sandbox profile execution from the tool catalog without an operator sandbox mode switch.
- Add
- Add mount namespace support for read-only root, read-only
.git, hidden credential directories, and minimal read/write bind mounts for declared repo paths.- Build Bubblewrap args with read-only
/, tmpfs/homeand/root, read-only repo binding, read-only.git, and declared writable paths only. - Filter attempted
.gitwrite bind paths from both Bubblewrap args and sandbox evidence.
- Build Bubblewrap args with read-only
- Add PID and network namespace profiles for managed tools so ordinary linters cannot inspect host processes or exfiltrate data.
- Add seccomp-bpf profile support for managed hooks and lint tools,
starting with a conservative profile that blocks privilege escalation,
ptrace, mount/unshare, and other abnormal syscalls. - Add cgroup-backed resource quotas for sandboxed tool execution, including hard timeouts and memory limits to prevent local denial-of-service failures.
- Record sandbox profiles, declared capabilities, and runtime denials in
.coding-ethostraces and SARIF properties so failures are auditable and agent-remediation friendly.- Record sandbox evidence in lint traces under
result.capture.sandbox. - Record sandbox evidence in SARIF run properties under
runs[].properties.sandbox. - Normalize required-mode backend failures as
runtime.sandbox_denialfindings.
- Record sandbox evidence in lint traces under
- Require Bubblewrap for sandboxed execution and fail closed with clear denial evidence when Linux namespace/seccomp support is unavailable.
- Remove sandbox
automode so sandbox-declared tools have only explicitoffor fail-closedrequiredexecution paths. - Evaluate future high-isolation backends such as gVisor, eBPF-based telemetry/enforcement, and Wasm/WASI execution for untrusted extension code, but keep the first implementation focused on rootless local hook execution.
Acceptance criteria:
- A managed linter can run in a rootless sandbox with no network, read-only
.git, hidden credential directories, bounded resources, and declared writable paths only. - Sandbox capability requests are visible in policy explanations, traces, SARIF, and MCP responses.
- A tool cannot gain broader filesystem, network, process, or syscall access by bypassing shell wrappers, using static binaries, or spawning child processes.
- Sandbox denials are normalized into policy-linked diagnostics with ETHOS principle IDs and remediation guidance.
- CI can require sandbox enforcement for high-risk tool classes while local developer workflows remain recoverable and explicit about unsupported platforms.
- Build an automated red-team harness for attempts to bypass or tamper with
coding-ethosprotections. - Cover protected paths, raw Git bypasses, absolute binaries, nested shell execution, symlink replacement, path traversal, config drift, hook deletion, and managed toolchain evasion.
- Cover protected paths, raw Git bypasses, absolute binaries, nested shell execution, symlink replacement, path traversal, generated config drift, hook deletion, and managed toolchain evasion in deterministic Go red-team scenarios.
- Capture both successful blocks and any missed bypass attempts as reproducible fixtures.
- Add regression tests for the initial deterministic bypass classes.
- Add live Claude, Codex, and Gemini prompt-based red-team runs where practical.
Acceptance criteria:
- Red-team scenarios can run in isolated sample repositories without touching the parent repo.
- Each bypass attempt produces either a clear block or a filed gap with a failing regression test.
- The suite validates Claude, Codex, Gemini, and generic shell workflows where practical.
- Support policy and ethos inheritance, such as extending a local preset, GitHub-hosted preset, or enterprise registry preset.
- Define merge rules for inherited principles, skills, evidence maps, generated tool config, and repo-specific overrides.
- Validate inherited sources with pins, hashes, and provenance metadata.
- Provide curated presets such as strict Python, strict Go, agent-safe Git, and security-first repositories.
Acceptance criteria:
- A repo can inherit a baseline ETHOS and override only the local context.
- Inheritance is deterministic, auditable, and visible in policy trace output.
- Unpinned remote policy inputs are rejected unless explicitly allowed.
- Define a standardized machine-readable violation payload for agents.
- Emit XML, JSON, or TOON remediation blocks that include policy ID, ETHOS principle ID, skill ID, file/line, failed action, and concrete next steps.
- Feed hook failures back into Claude, Codex, Gemini, and future MCP clients in the strongest native format each provider supports.
- Add stable remediation IDs, skill-loading instructions, MCP
remediation_explain, provider-output golden fixtures, and exact remediation examples. - Add normalized source spans, stable finding IDs, evidence envelopes, SARIF result evidence properties, trace schema versions, and remediation lifecycle events as the substrate for code intelligence storage.
- Add CEL-facing source/finding fields and backend-neutral evidence store, code fact store, vector index, and trace ingestor interfaces.
- Add per-run remediation summaries to hook and lint traces so later storage can measure repeated policy failures without parsing provider text.
- Add an initial DuckDB code-intelligence store under
.coding-ethos/code-intel.duckdbthat ingests retained hook/lint traces, normalized findings, remediation payloads, and remediation events. - Add repeated-failure and FTS search commands over imported trace data.
- Add hook-usage intelligence storage for allow/block/rewrite events: tracking ID, session/provider/tool, operation kind, target kind, risk category, command shape fingerprint, target-set fingerprint, runtime, decision rows, message/suggestion variant hashes, and target paths.
- Expose hook-usage summaries through
code-intel hook-usageandcode_intel_hook_usageso agents and maintainers can identify recurring friction, bypass attempts, rewrite patterns, and policy hotspots. - Add hook review storage and CLI surfaces so admin/operator review can mark correct blocks, false positives, unclear messages, over-broad policies, and missing allow-list cases.
- Track whether remediation hints reduce repeated failures in
.coding-ethostraces by linking follow-up attempts to outcomes. - Extend local-first remediation storage to SARIF trace references with full-text plus embedding search over remediation IDs, policy IDs, skills, command/file context, outcomes, and follow-up attempts.
- Complete the
remediation_outcomes_1storage foundation: normalized DuckDB tables for SARIF runs/results, remediation outcomes, CEL/evaluator provenance, embedding metadata, and vector-backend row references. - Add code-intelligence CLI/query surfaces for SARIF result references, remediation outcomes, remediation effectiveness, and vector metadata status.
- Add embedding candidate, duckdb-vss upsert, hybrid search, and index status surfaces so agents can retrieve prior fixes before broad file reads.
- Implement duckdb-vss as the active DuckDB vector backend fed from canonical DuckDB records; do not let vector rows become the only copy of policy, SARIF, CEL, or remediation evidence.
- Add Tree-sitter AST indexing for Go, Python, JavaScript/TypeScript,
shell, and YAML into the canonical DuckDB store with stable
code_chunkrecords, FTS rows, and embedding-candidate export. - Refactor Tree-sitter extraction toward a resolver-style AST service
inspired by
~/Active/pyqa_lint: parser reuse, shared traversal helpers, and line-to-nearest-context lookup. - Add JSON and TOML config-entry AST chunks so policy, SARIF, MCP, and code-intel retrieval can target precise config entries.
- Expose AST code intelligence through
code-intel index-code,code-intel code-chunks,code_intel_index_code, andcode_intel_code_chunksso agents can retrieve focused symbol context before broad file reads. - Expose line-based AST code context lookup through
code-intel code-context --path ... --line ...andcode_intel_code_context. - Add Markdown AST chunking after choosing a maintained Go binding or a first-class adapter for the markdown parser layout.
- Add initial AST graph edges for containment, imports, and same-file references.
- Extend AST graph edges to language-specific calls, inheritance, test-to-source links, and documentation links.
- Store parser metadata, index timestamp, and content hashes beside AST-derived code files/chunks.
- Add stale code-chunk embedding invalidation when reindexing changes chunk hashes.
- Add incremental reindex invalidation that compares file hashes even when mtime and size appear unchanged.
- Use Tree-sitter facts to augment CEL source inputs with symbol kind, symbol name, symbol path, enclosing function/class/type/config entry, byte span, line span, content hash, parent symbol, and nearest test/doc chunk.
- Add CEL helper functions over AST facts:
symbol.kind_is(...),symbol.name_matches(...),source.enclosing_symbol(...),source.changed_symbol_count(),source.has_nearby_test(),source.has_doc_chunk(), andsource.symbol_too_large(...). - Move more size/complexity policy into principle-owned CEL by evaluating Tree-sitter chunks instead of whole files: block growing oversized functions, classes/types, shell functions, and YAML config entries while allowing shrinking edits.
- Add AST-aware edit preflight for agents: classify whether an Edit/Write grows, shrinks, adds, deletes, or rewrites an existing symbol before CEL decides whether the action is allowed.
- Extend AST-aware edit preflight to classify symbol renames explicitly instead of representing them as delete/add pairs.
- Add AST-aware diff facts that map changed lines to affected symbols so policy can target the edited function/config entry rather than the entire file.
- Add SARIF locations for Tree-sitter-backed findings using exact symbol start/end lines, byte offsets, and region snippets.
- Include AST node kind and symbol identity in SARIF properties for Tree-sitter-backed CEL findings.
- Document the required AST/CEL/SARIF architecture in
docs/AST_CEL_SARIF_ARCHITECTURE.md: Go collects facts, CEL evaluates configurable decisions, SARIF reports stable remediation-ready findings. - Add a shared Python AST fact surface for policy evaluators and CEL: imports, calls, functions, classes, assignments, lambdas, exception handlers, symbol context, ancestry flags, and initial signature facts.
- Expose Python AST facts to CEL as
python_astso future pyqa_lint ports can move decision logic into principle-owned expressions before adding new Go evaluators. - Extend SARIF AST identity to diagnostics with AST node metadata even when the finding has no named symbol path, and include parent-symbol metadata for source-backed findings.
- Use Tree-sitter-backed Python policy checks to block conditional import
workarounds at write time: nested imports,
TYPE_CHECKINGimport branches, module__getattr__,__import__, andimportlib.import_module. - Add pyqa-inspired Python functional idiom diagnostics for assigned lambdas and closure factories, grounded in the Functional Idioms principle.
- Port pyqa_lint's strict typing AST guidance into principle-owned Python
policy: flag
Any,typing.Any,object, andbuiltins.objectin parameter, return,*args,**kwargs, and annotated-assignment positions; ground it in No Optional Types for Required Dependencies and Static Analysis as the First Line of Defense. - Port pyqa_lint's signature-width AST guidance into a SOLID/SRP policy:
count positional-only, positional, keyword-only, varargs, and kwargs on
function definitions; recommend parameter objects or smaller seams when
signatures exceed the configured threshold or rely on
**kwargs. - Port pyqa_lint's Tree-sitter docstring structure checks into Documentation as Contract: index module/class/function docstrings, require summaries, enforce Args/Returns/Yields sections from actual AST parameters and return/yield behavior, and emit symbol-level SARIF regions.
- Port pyqa_lint's generic value-type Tree-sitter analysis as configurable
class-trait policy: derive dataclass/frozen/slots/enum/iterable/sequence/
mapping/value traits from decorators, bases, methods, and
__slots__, then require or recommend dunder methods such as__eq__,__hash__,__repr__,__str__,__len__,__bool__,__iter__, and__contains__. - Generalize pyqa_lint's interface-first AST rules into configurable architecture policy: detect concrete imports across configured layer/domain boundaries, forbid concrete functions/classes/assignments in configured interface modules except Protocol/ABC/TypedDict/Enum/dataclass-like contracts, and link violations to Protocol-First Design.
- Generalize pyqa_lint's DI composition-root AST rule: detect configured
service-container registration calls such as
container.register(...)and allow them only in configured composition roots or bootstrap modules. - Generalize pyqa_lint's cache-wrapper AST rule: resolve imported aliases
and decorator calls for banned cache decorators such as
functools.lru_cache, then require the repo's configured cache abstraction when a principle says caching must be centralized or observable. - Replace remaining text-only Python hygiene checks with AST-backed policy
facts inspired by pyqa_lint: detect debug breakpoints/tracing, bare except,
broad
except Exceptionwithout justification, debug imports, directSystemExit/sys.exitoutside CLI modules, module__main__blocks, and unsanctionedprintcalls while avoiding strings/comments false positives. - Port pyqa_lint's package module documentation convention as configurable
Documentation as Contract policy: discover package directories from
__init__.py, require configured module docs such asMODULE.mdor package-derived docs, and verify required sections. - Reuse pyqa_lint's AST visitor/reporting pattern conceptually by adding a shared Go policy visitor helper for Python AST evaluators: one parse path, one suppression check path, consistent diagnostic metadata, and no duplicate ad-hoc Tree-sitter traversals per policy.
- Add SARIF partial fingerprints based on path, language, symbol path, node kind, rule/policy ID, and content hash so findings remain stable across unrelated line movement.
- Link SARIF/CEL findings that carry AST identity back to matching
code_chunkrows throughast_finding_links. - Emit SARIF code flows/thread flows for policy findings that involve relationships, such as unsafe call chains, missing tests for changed symbols, imports from forbidden layers, or generated-config edits from source files.
- Add AST-backed SARIF suppression guidance that points agents to the
principle and symbol-level remediation path instead of allowing broad
noqa,nolint, or config weakening. - Use Tree-sitter graph edges to enforce architecture policies in CEL: layer boundaries, forbidden imports, test-to-source coverage proximity, generated-artifact/source ownership, and shell wrapper boundaries.
- Add policy articulation output that explains Tree-sitter-backed decisions in human terms: "this edit grows function X from N to M lines", "this YAML key is enforcement config", or "this import crosses a forbidden layer."
- Extend
policy_explainandremediation_explainto include relevant AST context, including the exact symbol, enclosing parent, related test/doc chunks, and the next MCP calls (code_intel_code_chunks,code_intel_search, orlint_check). - Add AST-aware guidance packets for agents that include focused code chunks, related prior SARIF/remediation history, and symbol-specific rerun instructions before suggesting broad file reads.
- Add CLI context expansion for code chunks with parent, children, graph edges, and linked SARIF/CEL findings.
- Add MCP context expansion for code chunks with parent, children, graph edges, and linked SARIF/CEL findings.
- Extend context expansion with sibling chunks.
- Extend context expansion with language-specific callers/callees, related tests, related docs, recent policy failures, and prior fixes for the same symbol.
- Promote diagnostic signature tokens into a first-class stored column or relation once repeated-failure clustering needs querying beyond FTS search.
- Add query-driven AST capture specs for imports, references, config keys,
headings, and documentation chunks; keep enforcement policy in
coding_ethos.ymland use capture specs only to supply facts. - Add first staleness and trust metadata to indexed AST files: indexed content hash, index timestamp, and parser metadata.
- Add stale-result refusal behavior and current-content validation for
CodeContextlookups. - Add stale-result refusal behavior and current-content validation for compact code context, repo maps, and other AST-derived context lookups.
- Add stale-result refusal behavior and current-content validation for every AST-derived CEL/SARIF result.
- Add regression tests proving Tree-sitter facts are identical across hook, lint, CLI, MCP, and CI/SARIF paths so AST-backed policy cannot drift between enforcement surfaces.
- Build the code intelligence roadmap in
docs/CODE_INTEL.md: Tree-sitter AST chunking, DuckDB canonical storage, duckdb-vss vector search, hybrid retrieval, and MCP code/remediation search tools.
Acceptance criteria:
- Agents can self-correct common hook failures without reading raw terminal noise.
- Remediation output is compact enough for context windows and precise enough to prevent guessing.
- Human output and agent output share the same normalized data model.
- The local code-intelligence database can answer which SARIF/CEL findings repeated, which remediation guidance was issued, and whether later attempts fixed or repeated the finding.
- The local code-intelligence database can answer which hook provider/tool/operation/target/risk groups are blocked, rewritten, or repeatedly advised.