Skip to content

chore(governance): adopt praetor HISS-16 standards before rc1 (ADR-1249) - #1454

Merged
lusoris merged 9 commits into
masterfrom
chore/praetor-governance-adoption
Sep 18, 2026
Merged

lusoris merged 9 commits into
masterfrom
chore/praetor-governance-adoption

Conversation

@lusoris

@lusoris lusoris commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Brings the repository under the praetor / HISS-16 governance system ahead of
1.0.0-rc.1, as scaffolding and a ratchet only. Declarations, the compiled
agent contexts, the generated policy artefacts and one required CI gate land
here; the five pre-migration epic tasks (#1444–#1448) are post-1.0.0 and no
product code is refactored for them.

Refreshed 2026-09-18 onto current master and praetor e4b35cb, with
the history restructured so that every commit passes the hooks that run
from the commit introducing lefthook.yml onward. The adoption was
regenerated by a real adopt --force in a clean clone. praetorctl audit
passes every gate on 1,627 baselined infractions (was 1,687), and the CI
gate pins the same engine (PRAETOR_REF = e4b35cb3c7fe…).

AGENTS.md becomes a single canonical source compiled into six vendor files, so
CLAUDE.md, .cursor/rules/, .github/copilot-instructions.md,
.windsurfrules, .gemini/GEMINI.md and .codex/rules.md may no longer be
edited by hand. It is now 253 lines in the internal (caveman) register, which
the engine lints; the largest compiled target is 263 of 300 lines. Its hard
rules and rebase-sensitive invariants move to docs/development/ pages. Rules
that only the hand-written CLAUDE.md carried move with them, so compiling
CLAUDE.md loses nothing: source layout, the banned-function list, the
golden test files, the benchmark-output rule and the docs/state.md rule.

Commits:

  1. docs(agents): split the hard rules and rebase invariants out of AGENTS.md.
  2. docs(adr): ADR-1249, lefthook owning the hooks and delegating to the
    pre-commit framework (ADR-1241 dispatchers kept).
  3. docs(agents): AGENTS.md in the internal register, plus the rules only
    CLAUDE.md carried.
  4. chore(agents): one canonical copy of the ten reviewer personas under
    .agents/agents, projected to Codex, Copilot and Gemini.
  5. chore(governance): the generated adoption.
  6. ci(standards): the required gate, pinned to e4b35cb.
  7. docs(research): digest renumbered to 2064 (2041 is taken on master).
  8. build(security): .gosec.json, which the gate refuses to run without.
  9. ci(hooks): drop the gate stage from pre-push; its race stage cannot build
    the cgo packages.

Type

  • feat — new feature
  • fix — bug fix
  • perf — performance improvement
  • refactor — no behavior change
  • docs — documentation only
  • test — test-only
  • build / ci — tooling / infra
  • port — cherry-pick from upstream Netflix/vmaf
  • sycl / cuda / simd — backend-specific

Checklist

  • Commits follow Conventional Commits (the commit-msg hook enforces this).
  • make format && make lint is green locally.
  • Unit tests pass: meson test -C build.
  • If I touched any SIMD/GPU code path, I ran /cross-backend-diff and the worst ULP is ≤ 2.
  • If I touched a feature extractor with SIMD/GPU twins, I either updated every twin or listed the gap under "Known follow-ups" below.
  • If I added a new .c / .cpp / .cu / .h / .hpp, it has the appropriate license header (see CONTRIBUTING.md).
  • If this is a breaking change, the commit message uses ! or BREAKING CHANGE: and the migration path is documented below.
  • If this PR adds an ADR, the ADR row lives in docs/adr/_index_fragments/<NNNN-slug>.md and the slug is appended to docs/adr/_index_fragments/_order.txt — do not edit docs/adr/README.md directly.

Bug-status hygiene (ADR-0165)

  • no state delta: governance scaffolding and CI wiring only; no tracked bug is opened, closed or re-scoped by this change.

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.
  • If I believe a golden value must change, I have explained why below AND pinged @lusoris for a CODEOWNERS exception.

Deep-dive deliverables (ADR-0108)

  • Research digest — docs/research/2064-praetor-adoption-measurements.md, including the 2026-09-18 refresh section.
  • Decision matrix — four alternatives scored in docs/adr/1249-praetor-governance-adoption.md.
  • AGENTS.md invariant note — docs/rebase-notes.md gains the compiled-source contract: vendor context files are generated and must never be resolved by hand, the harness has ~30 lines of budget headroom, and the project-wide invariant index moved out of §13.
  • Reproducer / smoke-test command — pasted below under "Reproducer".
  • CHANGELOG fragment — changelog.d/added/1249-praetor-governance-adoption.md added.
  • Rebase note — docs/rebase-notes.md, top entry.

Reproducer

# context integrity: six vendor targets, all within the 300-line budget
praetorctl compile-context --verify

# the ratchet, as CI runs it
praetorctl audit -base origin/master

# the repository's own gates over this branch
.venv/bin/pre-commit run --files $(git diff --name-only origin/master...HEAD)
.venv/bin/python -m mkdocs build --strict
bash scripts/ci/check-aggregator-names.sh

Verified locally

At tip 0f9701c49:

Gate Result
compile-context --verify pass; 6 targets, 48 persona copies in sync
praetorctl audit (CI=true) every gate passes, 1,627 of 1,627 baselined
flavor audit 100%
CI install path (go install …@e4b35cb, then verify and audit) pass
mkdocs build --strict exit 0
pre-commit over all 140 changed files pass
pre-push (mypy, MkDocs, PR-body) over origin/master..HEAD pass

Known follow-ups

  • make install-hooks refuses to run once lefthook owns pre-commit
    and pre-push; recorded in ADR-1249. The e4b35cb audit only checks that
    some pre-commit hook exists, so ADR-1249's reason for lefthook owning the
    hooks is weaker than it was, which is worth a second look.
  • Master-based checkouts currently run no git hooks. The shared
    .git/hooks have been lefthook's since 2026-09-15, and lefthook exits
    quietly where there is no lefthook.yml. Merging this PR ends that.
  • Overlap with the caveman-register branch, which rewrites 8 of the 10
    personas: whichever merges second copies the text into .agents/agents/ and
    recompiles. The gate flags it if not.
  • sync --remote must not be run against this repository: the engine
    hardcodes main while this fork's default branch is master (ADR-0002).
  • Praetor engine issues found in the refresh, for upstream:
    • adopt stops on "editor language scan exceeds file bound" because the
      scan is capped at 4,096 files with no flag (the editors step was declined
      for the generation run only).
    • It writes an empty ruff.toml that shadows pyproject.toml's
      [tool.ruff] (not committed).
    • Its generated personas and .paperclip/rules.md still fail markdownlint.
    • rulesets/main.json has no trailing newline.
    • The caveman lint flags "please" inside release-please.
    • A go install @<sha> build reports version unknown.

…S.md

The canonical agent harness is compiled into six vendor context files
(CLAUDE.md, .cursor, .windsurfrules, copilot, GEMINI.md, .codex) under a
300-line budget per target. At 558 lines AGENTS.md could not be projected at
all, so the three heaviest sections move to their own pages and the harness
keeps a pointer section with import lines for agents that expand them:

- §12 Hard rules (141 lines) -> docs/development/agent-hard-rules.md
- §13 Rebase-sensitive invariants (131 lines) ->
  docs/development/rebase-sensitive-invariants.md
- §12a Worktree discipline (40 lines) -> dropped in favour of the existing
  docs/development/agent-worktree-discipline.md, verified to cover every
  specific the section carried, down to the memory citation and the
  every-20-tool-uses cadence.

AGENTS.md is now 265 lines and every projection lands at 268-274. Root-relative
links in the moved bodies were rewritten for their new depth: docs/adr/X ->
../adr/X, docs/development/Y -> Y, and source-tree pointers -> ../../X, which
is the convention the existing development pages already use and which
mkdocs.yml records as INFO-level rather than a strict-build failure. Both pages
are added to the nav, because nav.omitted_files is warn and therefore fatal
under --strict.

Also corrects a stale absolute path in the pelorus interop research digest
after the local checkout moved to ~/dev/vmafx/vmafx.
… owning the hooks

The repository is being adopted into the praetor / HISS-16 standards system
as scaffolding and a ratchet only, ahead of 1.0.0-rc.1. The decision lands
before the commits that implement it, so the ADR, its index fragment and the
regenerated ADR index, tag pages and navigation come first.

The record states the four forces that shape the adoption: the transpiler's
300-line budget per compiled context file, the engine's lint of AGENTS.md in
its internal register (praetor e4b35cb, no opt-out), the hook managers
already in play (ADR-0924 and the ADR-1241 dispatchers), and the rc1
schedule. It decides that lefthook owns pre-commit and pre-push and hands
both stages to the pre-commit framework, while the ADR-1241 dispatchers keep
commit-msg and pre-rebase.

The consequences keep the two deliberate exclusions (`sync --remote`, because
the engine hardcodes `main`, and REUSE), note that the SPDX and licence-text
findings were since resolved on master by ADR-1250 and ADR-1255, and list the
open follow-up that `make install-hooks` refuses to run once lefthook owns
those two hooks.
…DE.md's own rules

AGENTS.md is read by agents only, and the governance engine this branch adopts
(praetor e4b35cb) lints it in its internal "caveman" register: compile-context
--verify and audit fail on prose, with no opt-out. The repository's part of
the file, below the praetor harness, is rewritten in that register. Every rule,
ADR id, command, code span and link survives:
`praetorctl caveman floor` passes from the prose version to this one, and
markdownlint is clean. The harness above the end marker is left for the
adoption commit to regenerate.

The adoption also turns CLAUDE.md into a compiled copy of AGENTS.md, so
anything only the hand-written CLAUDE.md said would disappear from Claude's
context. That content moves here first:

- AGENTS.md gains the full source layout, the IDE / compile_commands note,
  `make preflight` (ADR-1234), the banned-function list, the golden-data test
  files, the release dry-run skill, and the licence split from ADR-1250
  (fork-authored code is EUPL-1.2, inherited code keeps its terms). The old
  "BSD-2-Clause-Patent for everything" line predates the relicensing.
- The hard-rules page gains the rules only CLAUDE.md carried: never commit
  benchmark output, re-read the ADR index each session, update docs/state.md
  with every bug (ADR-0165), the host-enforced branch protection notes
  (ADR-0037), the container-canonical publishing rule (ADR-1102), and the
  current NOLINT closeout wording (ADR-0278) in place of a stale T7-5 backlog
  pointer.
….agents/agents

The governance engine adopted in the next commit (praetor e4b35cb) treats
.claude/agents, .codex/agents, .github/agents and .gemini/agents as
projection directories. It verifies them in both directions: every persona in
.agents/agents must appear, byte-identical, in all four, and a file in any of
them without a source in .agents/agents fails `compile-context --verify` and
`audit` ("projects no canonical persona").

The ten reviewer personas this repository keeps in .claude/agents had no such
source. Each gains a byte-identical copy in .agents/agents, projected to the
Codex, Copilot and Gemini agent directories exactly as `praetorctl
compile-context` writes them. The .claude/agents files are not modified. From
here on a persona is edited in .agents/agents and recompiled; editing a
projection fails the gate.

The .codex/agents/*.toml definitions are a separate, Codex-native format and
are left alone.
…ding

Brings the repository under the praetor governance system (workstation
contract DEV-05) ahead of 1.0.0-rc.1, as scaffolding and a ratchet only
(ADR-1249): the five pre-migration epic tasks (#1444-#1448) are post-rc1
work and nothing here refactors product code. Every generated artefact comes
from a real `praetorctl adopt --force` run at praetor e4b35cb in a clean
clone, because this working tree's build directories inflate the scan.

Declarations and policy:

- .standards.yaml selects the native-gpu-systems archetype with the
  security:high, api:public-contract, docs:seo-portal and agent:sandboxed
  facets. .standards.lock pins them by content digest and .config/archetypes/
  holds the pinned policy locally, so the audit resolves it instead of a
  fallback.
- .standards-baseline.json records the existing debt, 1,627 infractions
  (HISS-04 889, HISS-01 538, HISS-07 74, HISS-02 65, HISS-09 48, HISS-08 13),
  so legacy code builds while new debt fails the audit.
- AGENTS.md gets the refreshed praetor harness, in the internal register
  with its text-register block, and is compiled into CLAUDE.md,
  .cursor/rules, .windsurfrules, the Copilot, Gemini and Codex files and
  the persona projections. CLAUDE.md is now generated: edit AGENTS.md, never
  a target. The largest target is 263 lines against the 300-line budget.
- Makefile gains verify-all, audit and compile-context; README documents the
  gates.

Local enforcement: lefthook owns pre-commit and pre-push and hands both
stages to the pre-commit framework. Pre-commit runs `pre-commit run`, and
pre-push runs `pre-commit hook-impl --hook-type=pre-push` with the remote
arguments and the push-ref stdin, so the ADR-1241 push checks (MkDocs strict,
PR-body deliverables, push-range mypy) keep running. Both fail closed when
pre-commit is missing, as the ADR-1241 dispatchers do. commit-msg and
pre-rebase stay with those dispatchers.

Also: .config/ (labels, agent checkpoint and evaluator, anti-evasion
interceptor), the .paperclip harness, .github/rulesets/main.json (a local
declaration only, since `sync --remote` hardcodes `main`), the two praetor
personas, editor configurations for eight editors, and a devcontainer built
by `praetorctl devcontainer --base-image` on this repository's published dev
image (ghcr.io/vmafx/vmafx-dev-mcp, digest-pinned, still the current
`latest`), so meson, CUDA, oneAPI and ROCm stay in the container.

Deliberate departures from the generated output, each for a measured reason:

- The personas and .paperclip/rules.md keep their markdownlint-clean
  layout; only the engine's content changes (standardsctl renamed to
  praetorctl, one text-register rule) were applied.
- `adopt` wrote a ruff.toml holding one comment. Ruff prefers ruff.toml to
  pyproject.toml, so it would have discarded this repository's [tool.ruff]
  settings; it is not committed, and `praetorctl flavor audit .` passes
  without it.
- The editor step was declined for the generation run only, because
  `adopt` stops at "editor language scan exceeds file bound" (a fixed
  4,096-file cap). The editor configurations are the ones generated at the
  first adoption; the decline is not part of .standards.yaml.
- .pre-commit-config.yaml keeps the whitespace and end-of-file hooks away
  from the base64 source bundle and the pinned catalog, which the audit
  compares byte for byte against recorded digests.

.gitignore excludes local agent scratch, the vendor skill mirror
(.claude/skills/ is the tracked canonical copy), the private .workingdir/ and
the gate worktrees under .standards/.
Adds the required context `Standards & Invariant Verification Gate`, which
runs `standardsctl compile-context --verify` and the baseline-only
`standardsctl audit`, and registers it in required-aggregator.yml. The
generated ruleset picks the new context up from the workflow.

The engine is installed by pinned commit, praetor e4b35cb, the build the
baseline was recorded with. praetor publishes no semver releases, only moving
tags, and the HISS count depends on the engine build, so an unpinned engine
could flip the ratchet on its own. Bumping the pin is a deliberate PR: e4b35cb
itself added the AGENTS.md register lint and the two-way persona check.

The audit runs without `-base`. That mode adds a touched-file clean rule on
top of the ratchet, and HISS-04 flags every function over 60 lines in any
file a PR opens, which would fail routine fixes to legacy C for reasons
unrelated to the fix. Recorded debt still may only shrink. ADR-1249 records
the trade and when to revisit it.

The job installs no git hook toolchain: under CI the engine's hook gate only
checks that lefthook.yml exists. It carries no `paths:` filter on purpose,
because the scan reads source and a required context that never starts would
leave the aggregator waiting.

The changelog fragment describes the whole adoption; CHANGELOG.md is
re-rendered from changelog.d.
…se contract

ADR-0108 deliverables for the governance adoption. The digest records what
the tool did rather than what its documentation claims: the three defects the
first adoption hit in order (the 4,096-entry discovery cap, the retired
placeholder lockfile, the 300-line context budget against a 558-line
AGENTS.md), the three different `max_func_loc` values `audit`, `plan` and the
archetype report, and the licence measurements behind leaving REUSE out of
rc1.

Its refresh section covers the move to praetor e4b35cb over 170 new master
commits: the AGENTS.md register lint and the rewrite's gate results, the
two-way persona check, the baseline falling from 1,687 to 1,627 by rule, the
hook gate that no longer asks who installed the hooks, and the adoption
defects the refresh hit (a fixed 4,096-file editor scan, a placeholder
ruff.toml that would shadow pyproject.toml, generated markdown that fails
markdownlint again). The SPDX and licence-text findings are marked as since
resolved on master by ADR-1250 and ADR-1255.

The digest takes number 2064: 2041 now belongs to the thread-pool research
on master, and 2062 and 2063 are held by in-flight branches.

The rebase note is the part that matters on an upstream sync: the vendor
context files and persona projections are generated and must never be
resolved by hand, AGENTS.md is linted as agent text, the largest target has
37 lines of headroom, and the invariant index an upstream-sync agent reads has
moved out of AGENTS.md §13.
…ires

`praetorctl gate run` refuses to execute gosec without a pinned configuration
file (".gosec.json is missing: the security gate refuses to run gosec without
its pinned configuration").

The gate runs `gosec -conf .gosec.json <packages>` with no
`-exclude-generated`, which surfaced 24 findings that live entirely in
generated code: G103 in gen/go/*.pb.go and G115 in the cgo intermediates
under the build cache. Those two rules are excluded here, and only for the
gate. The repository's own gosec lane (`make` and the Go workflow) passes
`-exclude-generated` and no `-conf`, so it still runs every rule on first-party
code. The proper fix is upstream: the gate should skip generated files.

The model-card read in pkg/predictor/ortsession.go that tripped G304 on
master is no longer part of this change; master replaced it with an
os.OpenRoot-confined read.
The praetor gating pipeline's race-detector stage runs `go test -race ./...`
in a bare isolated worktree (still so at praetor e4b35cb). Every Go package
here is cgo over libvmaf (`-L core/build-cpu/src -lvmaf`), and the worktree
has no built library, so the binaries fail to build before a single test runs
and the pipeline can never be admitted. With the stage in place the
repository could not be pushed at all.

Its other stages already run pre-push as `audit`, `flavor-audit` and
`security`, and anti-direct-merge is enforced by branch protection and the
required aggregator, so nothing is lost but the stage that cannot work. Filed
upstream (praetor#81) asking the stage to honour the repository's declared
test command, which the engine already writes into the harness.
@lusoris
lusoris force-pushed the chore/praetor-governance-adoption branch from 6bcd044 to 0f9701c Compare September 18, 2026 19:14
@github-actions github-actions Bot added the type:chore Maintenance, no user-visible change label Sep 18, 2026
@lusoris
lusoris marked this pull request as ready for review September 18, 2026 19:15
@lusoris
lusoris merged commit 5730fca into master Sep 18, 2026
135 of 137 checks passed
@lusoris
lusoris deleted the chore/praetor-governance-adoption branch September 18, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:chore Maintenance, no user-visible change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant