Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ ehthumbs.db
*.swp
*.swo
*.lock
!pre-commit/hooks/uv.lock

# Generated repo-root markdown and tool config files are intentionally versioned.
# Do not ignore:
Expand Down
14 changes: 9 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ GOFMT ?= gofmt
CARGO ?= cargo
GO_BUILD_FLAGS ?= -trimpath -buildvcs=false
GO_BUILD_CACHE_DIR ?= $(LOCAL_REPO_ROOT)/.coding-ethos/cache/go-build
GO_PATH_DIR ?= $(LOCAL_REPO_ROOT)/.coding-ethos/cache/go-path
GO_MODULE_CACHE_DIR ?= $(GO_PATH_DIR)/pkg/mod
UV_CACHE_DIR ?= $(LOCAL_REPO_ROOT)/.coding-ethos/cache/uv
export GOCACHE := $(GO_BUILD_CACHE_DIR)
export GOPATH := $(GO_PATH_DIR)
export GOMODCACHE := $(GO_MODULE_CACHE_DIR)
export UV_CACHE_DIR

empty :=
Expand Down Expand Up @@ -71,7 +75,7 @@ fi
endef

define install_git_hooks
$(call print_info,hooks: $(1)); "$(GO_TOOLS_BIN_DIR)/coding-ethos-toolchain" install-git-hooks --hooks-dir "$(1)" --runner "$(GO_HOOK)"
$(call print_info,hooks: $(1)); "$(GO_TOOLS_BIN_DIR)/coding-ethos-toolchain" install-git-hooks --hooks-dir "$(1)" --runner "$(2)"
endef

HOOK_CONSUMER_ROOT := $(shell $(resolve_hook_consumer_root))
Expand Down Expand Up @@ -648,11 +652,11 @@ go-hook-runner-install: ensure-go ## Build the bundled Go hook runner into the c
@cd "$(GO_TOOLS_DIR)" && "$(GO)" build $(GO_BUILD_FLAGS) -o "$(LOCAL_BIN_DIR)/coding-ethos-hook-runner" ./cmd/coding-ethos-hook-runner
@$(call print_info,installed: $(LOCAL_BIN_DIR)/coding-ethos-hook-runner)

_sync-git-hooks: ensure-go go-tools-install
_sync-git-hooks: ensure-go go-tools-install _sync-parent-hook-runtime
@$(call print_step,Syncing Git hook entrypoints)
@$(call install_git_hooks,$(LOCAL_HOOKS_DIR))
@$(call install_git_hooks,$(LOCAL_HOOKS_DIR),$(GO_HOOK))
@if [ "$(HOOKS_DIR)" != "$(LOCAL_HOOKS_DIR)" ]; then \
$(call install_git_hooks,$(HOOKS_DIR)); \
$(call install_git_hooks,$(HOOKS_DIR),$(PARENT_HOOK_BIN_DIR)/coding-ethos-run); \
fi

_sync-parent-hook-runtime: ensure-go go-tools-install policy-bundle-install
Expand All @@ -678,7 +682,7 @@ _sync-parent-hook-runtime: ensure-go go-tools-install policy-bundle-install
@"$(GO_TOOLS_BIN_DIR)/coding-ethos-toolchain" install-git-shim \
--dest-dir "$(PARENT_HOOK_BIN_DIR)" \
--real-git "$(GIT)" \
--runner "$(GO_HOOK)"
--runner "$(PARENT_HOOK_BIN_DIR)/coding-ethos-run"
@"$(GO_TOOLS_BIN_DIR)/coding-ethos-lint" \
--install-shims \
--tools-bin-dir "$(PARENT_HOOK_BIN_DIR)" \
Expand Down
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,38 @@ install/check emit only status plus artifact-step rows, while parent lint emits
the normal coding-ethos TOON lint report. See `TO_MY_PARENT.md` for the parent
artifact contract.

`parent-install` rebuilds the checkout-authoritative Go tools and atomically
projects byte-identical executables into the parent repository's stable common
Git runtime. `parent-check` hashes both sides and fails if that projection is
missing, non-executable, symlinked back to a retiring checkout, or stale.

Parent install and check are artifact workflows and do not perform a full
repository code-intel refresh. Lint and Git-hook workflows refresh code intel
when source analysis is actually part of the requested gate, so deploying or
checking the runtime cannot be delayed by an unrelated whole-repository scan.
Failed or policy-blocked hooks retain their trace evidence but do not perform a
whole-repository refresh, because no accepted source transition occurred.

Consumer commits may include generated tool and provider configuration only
when the staged Git-index bytes exactly match output rendered by the active
Coding Ethos authority and the path is present in the staged diff. That narrow
trust record exempts the generated surface from path-write guards and the
forbidden-string scan that would otherwise reject the authority's own generated
runtime commands; every other content policy still runs. Restoring a clean
working-tree copy cannot conceal divergent staged bytes.

When `parent-install` or `parent-lint` receives an external `--state-root`, it
leaves the consumer checkout's tracked `.gitignore` unchanged. Other generated
parent artifacts remain normal consumer surfaces; repo-local state retains the
runtime-ignore repair.

Git hooks installed for a parent repository route through its stable common
Git runtime at `.git/coding-ethos-hooks/bin/coding-ethos-run`. They never point
at a worktree-local build path, so one worktree cannot strand every sibling's
hooks when its own checkout is retired or hidden by a lane sandbox. Running the
supported parent workflow refreshes and verifies that shared executable
projection as part of the same install/check contract.

Parent repos can opt into profile defaults in `repo_config.yaml`:

```yaml
Expand Down Expand Up @@ -1845,6 +1877,18 @@ bin/coding-ethos-run policy-git --admin-approved commit -F /tmp/msg
The flag only changes `git.staged_admin_files` from block to record. It does
not disable other policy and is invalid outside this repository.

In consumer repositories, an admin-classified file that is also a generated
tool-config surface may be committed by an agent only when its staged bytes
exactly match the output rendered from the active Coding Ethos policy. The
comparison is against the Git index, so restoring only the working-tree copy
cannot conceal a divergent staged config. Any hand-edited or stale config
remains admin-blocked.

The optional shell common-helper convention is enforced only when the consumer
actually tracks a `common.sh` helper. A repository without that convention is
still checked for shebangs, strict mode, syntax, and unsafe shell constructs,
but is not told to source a nonexistent file.

Agents must not use `/usr/bin/git` or any other raw Git path for this workflow.

## Development
Expand Down
6 changes: 6 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ 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-hooks` runtime. See
> `docs/HOOK_RUNTIME_BOOTSTRAP.md` for the superseding architecture.

### Phase 1 - Runtime Layout

- [x] Replace the consumer `.git/coding-ethos-hooks` runtime cache with
Expand Down
9 changes: 6 additions & 3 deletions TO_MY_PARENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ profiles:

Explicit `repo_config.yaml` settings override these profile defaults.

`parent-install` syncs generated parent artifacts. `parent-check` verifies those
artifacts without rewriting them. `parent-lint` syncs the parent artifacts, then
runs the full parent lint scope through the compiled policy bundle.
`parent-install` syncs generated parent artifacts and atomically refreshes the
compiled executables in the parent repository's common
`.git/coding-ethos-hooks/bin/` runtime. `parent-check` verifies those artifacts
without rewriting them, including byte identity and executable independence
from any retiring worktree. `parent-lint` syncs the parent artifacts, then runs
the full parent lint scope through the compiled policy bundle.

## Output Contract

Expand Down
2 changes: 2 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,8 @@ filesystem:
- 'lbox-worktrees/[A-Za-z0-9._-]+'
- '/tmp/tmp\.[A-Za-z0-9._-]+'
literals: []
allowed_patterns:
- '/home/agent/'
exempt_prefixes:
- .git/
license_header:
Expand Down
13 changes: 12 additions & 1 deletion docs/CODE_INTEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Use explicit storage layers with separate logical responsibilities:
content-addressed base manifest is shared through the Git common directory;
each worktree owns its delta manifest, tombstones, and current-generation
receipt. No shared writable DuckDB is used for these source facts.
- **DuckDB remains the v1-compatible analytical and telemetry store.** It owns
- **DuckDB is a schema-v2 analytical and telemetry store with v1 upgrade
compatibility.** It owns
traces, policy decisions, remediations, outcomes, derived AST graph edges,
file metadata, and full-text search. Existing v1 stores are retained during
the v2 migration and can be rebuilt explicitly as derived state.
Expand Down Expand Up @@ -156,6 +157,16 @@ remediation text.
duckdb-vss is active for derived vector rows, but DuckDB facts remain the
auditable source of truth.

Writable stores use schema v2. Search identities are enforced by unique
constraints on `code_intel_fts.fts_id` and on `(term, fts_id)` in
`code_intel_search_terms`. Upgrading or replaying a v1 store collapses exact
duplicate rows, fails closed when one identity carries conflicting content,
and reports row and duplicate counts through store statistics. Migration
manifests use kind v2, record `deduplicated_rows`, and exclude the schema
metadata row from migrated-data accounting. File, chunk, and graph-edge
replays use conflict-aware updates so rebuilding search state does not discard
retained AST or foreign-key evidence.

Graph facts expose provenance classes wherever repo maps, graph reports, and
MCP graph surfaces show those facts. `EXTRACTED` marks parser/static-analysis
facts, while `GIT_DERIVED`, `POLICY_DERIVED`, `TRACE_DERIVED`, and
Expand Down
Loading
Loading