Files
rune/docs/structural-contract.md

3.6 KiB

Structural Contract — henxels Adoption (#138)

The repo's shape is machine-checkable. henxels.yaml (repo root) holds the contract; henxels sync renders it into the AGENTS.md digest agents read; henxels check --all --plain enforces it (exit 0 = green, 1 = red) and runs as a CI lint-job step.

What the contract governs

Henxel Scope Rule
Canaries registered in CI ./src/rune/canary_*.py Custom statement ci_runs_all_canaries (in henxels_checks.py): every canary on disk must appear in .gitea/workflows/ci.yml
No secrets whole repo no_secrets — no credentials in tracked files
Plans ./plans markdown only, kebab-case filenames
Docs ./docs/* .md/.yaml only, except docs/v1/** and docs/wiki/**
File-size debt ./src/rune max_lines: 1200, except the documented debt list below

Warnings (non-blocking): near-duplicate file detection (the shared/ vs src/rune/ copies and backups/ snapshots are pre-existing debt the warning correctly keeps visible).

Debt table

Known violations, explicitly excepted in henxels.yaml instead of silently ignored. Each entry lists the finding that forced the exception.

File / spot Rule Finding Disposition
src/rune/rune_tui.py max_lines 1200 4231 lines (drafted exception) except-listed; split is future work
src/rune/rune_operator.py max_lines 1200 1265 lines (drafted exception) except-listed; split is future work
src/rune/local_tool_runtime.py max_lines 1200 506 lines — drafted as pre-emptive headroom, not currently over budget except-listed (as drafted)
src/rune/memory_store.py max_lines 1200 2171 lines (live finding) except-listed; split is future work
src/rune/curator.py max_lines 1200 1597 lines (live finding) except-listed; split is future work
src/rune/tool_executor.py max_lines 1200 1523 lines (live finding) except-listed; split is future work
src/rune/warm_router.py max_lines 1200 1292 lines (live finding) except-listed; split is future work
tests/test_gitea_provision.py no_secrets flagged as hardcoded credential — actually synthetic fixture tokens (plaintext-transport-test-secret etc.) whose purpose is asserting tokens never leak except-listed (false positive)
src/rune/canary_native.py canary gate tui_validator's import allowlist drifted from rune_tui.py (from __future__ import annotations, bare import rune) — 2 false-failures; validator fix is issue #139, not here canary tolerates exactly those 2 messages (prints ⚠ known false-failure, #139, does not count them); any other TUI error still fails the canary

How to add a rule

  1. Prefer a built-in: henxels catalogue lists every statement (built-ins and this repo's custom ones).
  2. Add a henxel to henxels.yaml. Custom statements live in henxels_checks.py (auto-loaded; a .henxels/ folder of check modules also works). Custom statements REQUIRE an in: scope — without one they never fire.
  3. Run henxels check --all --plain locally; fix findings cheaply or add an explicit except: and a row to the debt table above.
  4. henxels sync to refresh AGENTS.md and commit both together.
  5. The contract must be green at birth: never merge a rule that fails on master.

Why no git hooks

Subagents work in throwaway worktrees (/mnt/workdrive/rune and siblings) and commit there; a pre-commit hook would either miss those commits or block the agent mid-flight. Enforcement is CI-only: the lint job runs henxels check --all --plain on every push/PR, so the gate is the merge, not the commit.