
Agent Harness
- 23 installs
- 4 repo stars
- Updated August 2, 2026
- netresearch/agent-harness-skill
Helps with ai & agent building tasks.
About
agent-harness is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- agent-harness
- AI & Agent Building
- AI-coding skill
Agent Harness by the numbers
- 23 all-time installs (skills.sh)
- +3 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #10,007 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/netresearch/agent-harness-skill --skill agent-harnessAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 23 |
|---|---|
| repo stars | ★ 4 |
| Last updated | August 2, 2026 |
| Repository | netresearch/agent-harness-skill ↗ |
What it does
Helps with ai & agent building tasks.
Files
Agent Harness
The agent harness makes a repo agent-ready with self-sustaining enforcement. This skill installs it; CI, hooks, and conventions then enforce it.
Modes
1. Verify (primary)
Always start here. From the target repo root, run:
scripts/verify-harness.shAnalyse the output and fix or suggest fixes. Verification checks dead references, line counts, missing artefacts, and command/target alignment.
2. Bootstrap
When artefacts are missing, create them from templates:
| Artefact | Template | Platform |
|---|---|---|
AGENTS.md | templates/AGENTS.md.tmpl | All |
docs/ARCHITECTURE.md | templates/ARCHITECTURE.md.tmpl | All |
docs/exec-plans/{active,completed}/ | Create directories | All |
.github/workflows/harness-verify.yml | templates/harness-verify.yml.tmpl | GitHub |
.gitlab-ci.yml (harness-verify job) | templates/gitlab-ci-harness-verify.yml.tmpl | GitLab |
.forgejo/workflows/harness-verify.yml | templates/forgejo-harness-verify.yml.tmpl | Forgejo/Gitea |
.github/pull_request_template.md | templates/pull_request_template.md.tmpl | GitHub |
.gitlab/merge_request_templates/Default.md | templates/merge_request_template.md.tmpl | GitLab |
.forgejo/pull_request_template.md | templates/pull_request_template.md.tmpl | Forgejo/Gitea |
.envrc | templates/envrc.tmpl | All |
| Makefile harness targets | templates/Makefile.harness.tmpl | All |
scripts/verify-harness.sh | scripts/verify-harness.sh (copy directly) | All |
Populate with repo-specific values; never overwrite existing files without confirmation.
3. Audit
Report the repo's maturity level (1, 2, or 3) and show what is needed to reach the next level. See references/maturity-levels.md for detailed criteria.
Key Principles
- AGENTS.md is an index, not an encyclopedia. Keep it under 150 lines. Put detail in
docs/. - Enforcement is project-level. CI workflows, git hooks, and branch protection enforce the harness -- not this skill at runtime.
- Verify first, bootstrap second. Always run verification before creating artefacts. The skill checks artefacts, not tools.
- Delegate specialist work. See
references/skill-integration-map.mdfor skill routing (@agent-rules,@github-project,@enterprise-readiness,@retro). - Does not own learning. Session retrospection, outcome review, and constitutional audits are delegated to
retro-skill. The harness verifies integration points exist (AH-22, AH-23) but does not invoke retro at runtime.
Maturity Levels
Level 1 -- Basic: AGENTS.md exists, is an index, documents commands.
Level 2 -- Verified: CI enforces harness integrity, AGENTS.md references resolve, commands match Makefile/scripts, ARCHITECTURE.md exists.
Level 3 -- Enforced: Branch protection requires harness CI, git hooks auto-activate, PR template includes checklist, drift detection on push.
See references/maturity-levels.md for the full breakdown.
References
references/maturity-levels.md-- Maturity criteria and progressionreferences/agents-md-rules.md-- AGENTS.md authoring rulesreferences/artefact-inventory.md-- Harness artefacts listreferences/harness-engineering-overview.md-- Theory: four functions, patternsreferences/agent-first-architecture.md-- Legibility, layered deps, agent-first techreferences/enforcement-mechanisms.md-- 10-mechanism table (CI, hooks, protection, drift)references/skill-integration-map.md-- Skill routing map + integration contracts with companion skills
version: 1
skill_id: agent-harness
preconditions:
- type: command
pattern: "git rev-parse --git-dir"
desc: "Must be a git repository"
mechanical:
# Level 1 — Basic
- id: AH-01
type: file_exists
target: AGENTS.md
severity: error
desc: "AGENTS.md exists at repo root"
- id: AH-02
type: command
pattern: "awk 'END {exit !(NR<150)}' AGENTS.md"
severity: warning
desc: "AGENTS.md is compact index (<150 lines)"
- id: AH-03
type: regex
target: AGENTS.md
value: "(?i)## commands"
severity: warning
desc: "AGENTS.md documents available commands"
- id: AH-04
type: file_exists
target: docs
severity: warning
desc: "docs/ directory exists"
# Level 2 — Verified
# Note: Comprehensive AGENTS.md reference resolution is performed by
# scripts/verify-harness.sh (run via the harness-verify CI workflow).
# The mechanical checkpoint here cannot loop with shell `for/while` under
# the assessment runner's command allowlist; it relies on `xargs test`
# over extracted markdown link targets, which catches local file refs
# but not anchor targets or templated URLs (those are validated upstream
# in verify-harness.sh).
- id: AH-10
type: command
pattern: "grep -oP '\\[.*?\\]\\(\\K[^)]+' AGENTS.md | grep -v '^http' | grep -v '^#' | sed 's/[?#].*//' | xargs -r -I {} test -e {}"
severity: error
desc: "All AGENTS.md references resolve to existing files"
- id: AH-11
type: file_exists
target: docs/ARCHITECTURE.md
severity: warning
desc: "Architecture documentation exists"
- id: AH-12
type: command
pattern: "cat .github/workflows/harness-verify.yml .gitlab-ci.yml 2>/dev/null | grep -qE 'harness-verify|verify-harness'"
severity: warning
desc: "CI harness verification workflow exists (GitHub Actions or GitLab CI)"
# Level 3 — Enforced
- id: AH-20
type: file_exists
target: "{.github/pull_request_template.md,.github/PULL_REQUEST_TEMPLATE,.gitlab/merge_request_templates}"
severity: warning
desc: "PR/MR template with harness checklist exists"
- id: AH-21
type: command
pattern: "cat .envrc .husky/install.sh .husky/husky.sh .husky/_/husky.sh composer.json package.json 2>/dev/null | grep -qE 'hooksPath|core\\.hookspath|post-install-cmd|\"prepare\"'"
severity: warning
desc: "Git hooks auto-activate on clone (.envrc, .husky, or composer/npm install hook)"
# === RETRO-SKILL INTEGRATION ===
# The harness does not own learning, but verifies that integration points
# exist for retro-skill to route session learnings into the correct
# destination. See references/skill-integration-map.md (retro-skill section).
- id: AH-22
type: command
pattern: "grep -liE '(retro|reusable.*pattern)' .github/pull_request_template.md .github/PULL_REQUEST_TEMPLATE/*.md .gitlab/merge_request_templates/*.md 2>/dev/null | head -1 | grep -q ."
severity: warning
desc: "PR/MR template includes retro question for agent-authored work"
fix_skill: "retro"
- id: AH-23
type: file_exists
target: "{.claude/hooks/session-end.json,hooks/session-end.json}"
severity: info
desc: "SessionEnd hook configured (optional; enable for auto-trigger of /retro)"
fix_skill: "retro"
# === QUALITY DELEGATION ENFORCEMENT ===
# The harness delegates quality to specialist skills but MUST verify
# the delegation produces results. These checks verify that quality
# infrastructure exists and is properly configured.
- id: AH-30
type: file_exists
target: "{Build/Scripts/runTests.sh,runTests.sh,Makefile}"
severity: warning
desc: "Test runner infrastructure must exist (runTests.sh or Makefile with test targets)"
- id: AH-31
type: command
pattern: "grep -hP '^\\s*level:\\s*(10|max|[89])' phpstan.neon Build/phpstan.neon 2>/dev/null | grep -q ."
severity: warning
desc: "PHPStan must be configured at level 8+ (PHP projects only; level 10 recommended)"
- id: AH-32
type: file_exists
target: "{.pre-commit-config.yaml,captainhook.json,lefthook.yml,lefthook.yaml,.lefthook.yml,.husky/pre-commit,.githooks/pre-commit}"
severity: warning
desc: >-
Git hooks must be configured for pre-commit quality checks (must mirror
CI's fast checks — see references/enforcement-mechanisms.md CI/Hook
Parity Principle; skill/Python projects: prefer .pre-commit-config.yaml)
- id: AH-33
type: command
pattern: "find . -name '*_test.go' -o -name '*Test.php' -o -name '*.test.js' -o -name '*.test.ts' -o -name 'test_*.py' | head -1 | grep -q ."
severity: error
desc: "Project must have at least one test file (supports Go, PHP, JS, TS, Python)"
- id: AH-34
type: file_exists
target: "{infection.json5,infection.json}"
severity: info
desc: "Mutation testing configuration should exist for mature projects"
- id: AH-35
type: file_exists
target: codecov.yml
severity: info
desc: "Code coverage configuration should exist"
- id: AH-36
type: command
pattern: >-
K1='composer ci:|golangci-lint|go vet|gofmt|validate-skill|validate\.yml';
K2='markdownlint|yamllint|biome|eslint|tsc|ruff|black|mypy|pyright';
K3='prettier|stylelint|cargo clippy|cargo fmt|phpstan|psalm|rector';
K4='php-cs-fixer|phpcs|make lint|make site-lint|make cgl|make phpstan';
K="($K1|$K2|$K3|$K4)";
H='captainhook.json .githooks/ .husky/ lefthook.yml lefthook.yaml';
H="$H .lefthook.yml .pre-commit-config.yaml";
! grep -rlE "$K" .github/workflows .gitlab-ci.yml 2>/dev/null | head -1 | grep -q .
|| grep -rlE "$K" $H 2>/dev/null | head -1 | grep -q .
severity: warning
desc: "If CI runs a fast-check command, a hook config should reference at least one fast-check command too (best-effort CI/hook parity)"
llm_reviews:
- id: AH-40
desc: AGENTS.md Architecture and Key Decisions reflect current implementation
type: llm_review
severity: warning
domain: documentation
prompt: |
Read AGENTS.md (specifically the File Map and any references to docs/).
Then follow its references to architecture, decisions, and implementation files
(such as docs/ARCHITECTURE.md, docs/adr/, or similar).
Then read the primary implementation files referenced there.
Check for concrete contradictions between what AGENTS.md and its referenced
architecture docs describe and what the code actually does. Common failure modes
after a significant implementation change:
- A tool, binary, or technique mentioned in Key Decisions that has been removed
from the code (e.g. "uses splitsh-lite" but the script no longer downloads it)
- An algorithm or step in the Architecture description that no longer matches
the actual code flow
- A file listed in the File Map that no longer exists or has a different purpose
Do NOT flag style issues, naming conventions, or missing documentation for new
features (that is a separate concern). Only flag cases where AGENTS.md or its
referenced docs make a factually false claim about the current code.
Report: either a list of specific contradictions (AGENTS.md claim vs. actual code),
or "No contradictions found."
tags: [documentation, agents-md, accuracy, staleness]
ADR-001: Verify-First Design
Status: Accepted Date: 2026-03-22 Context: The agent-harness skill could be designed as primarily a generator (creating files) or primarily a verifier (checking consistency). The initial design discussion suggested bootstrap-first, but was reversed. Decision: The skill is primarily a verifier, secondarily a bootstrapper. Consequences: Verification is the default mode; bootstrapping is explicit and optional.
Rationale
- Verification works on repos that built their harness manually -- no lock-in to skill-generated artefacts.
- It does not enforce a specific genesis path -- teams can adopt gradually.
- OpenAI's harness engineering paper (https://openai.com/index/harness-engineering/) emphasises mechanical verification over generation.
- Existing skills (agent-rules, github-project) already handle generation of specific artefacts.
- Verify-first means
make verify-harnessworks even without the skill installed at runtime.
Detail
The skill's primary mode is "check this repo," not "set up this repo." When invoked, it inspects the repository for the presence, format, and consistency of harness artefacts (AGENTS.md, CI workflows, git hooks, documentation references). It reports what is present, what is missing, and what is inconsistent.
Bootstrap is a secondary mode triggered explicitly (for example, via agent-harness:bootstrap). It generates missing artefacts using sensible defaults, but never overwrites existing files without confirmation. The generated artefacts are the same ones the verifier checks, so the workflow is: bootstrap once, verify continuously.
The verification script (verify-harness.sh) is designed to be portable. It uses only standard shell utilities and has no dependency on the skill runtime, Claude, or any agent framework. A repository can copy the script into its own CI pipeline and run it independently.
Implications
- The skill must produce a standalone verification script that works without the skill installed.
- Bootstrap must be idempotent -- running it on an already-configured repo should report "nothing to do."
- Documentation must lead with the verification workflow, not the bootstrap workflow.
- Teams that set up harness artefacts manually get the same verification benefits as teams that used bootstrap.
ADR-002: Enforcement Layers
Status: Accepted Date: 2026-03-22 Context: We evaluated 10 enforcement mechanisms for making repos agent-ready: CI workflows, Branch Protection/Rulesets, Git Hooks, .envrc (direnv), Composer plugins/scripts, npm scripts, pre-commit framework, Makefile/justfile, AGENTS.md, PR Templates. The question was which to use and how to layer them. Decision: Three-layer enforcement model ordered by strength: hard (server-side), automatic (local), and soft (convention-based). Consequences: The skill must produce artefacts for all three layers. No single mechanism is sufficient alone.
The Three Layers
1. Hard Layer (server-side, nobody bypasses)
- CI workflows (
.github/workflows/harness-verify.yml) -- runs on every PR, fails the build if harness artefacts are missing or inconsistent. - Branch Protection / Rulesets --
harness-verifyconfigured as a required status check, blocking merge on failure.
This layer is the backstop. It works regardless of contributor setup, editor, operating system, or whether they have the skill installed. If the CI check fails, the PR cannot merge.
2. Automatic Layer (activates on clone/install, local)
- `.envrc` (direnv) -- auto-sets
core.hooksPathto.githooks/when a developer enters the repo directory. - `composer post-install-cmd` / `npm prepare` -- installs git hooks automatically when dependencies are installed.
- Git hooks (`.githooks/`) -- pre-commit checks run verification before each commit; pre-push runs full verification before push.
This layer provides fast feedback during development. Developers catch issues before pushing, reducing CI round-trip time. It activates without manual setup for anyone using direnv or the project's package manager.
3. Soft Layer (convention-based, visible)
- `AGENTS.md` -- every agent reads this at session start; it points to harness documentation and verification commands.
- PR Templates -- GitHub shows a checklist to PR creators, reminding them to run verification.
- `Makefile` targets --
make verify-harnessprovides a discoverable entry point for manual checks.
This layer guides behaviour through conventions and visibility. It works for contributors who may not have direnv or the project's package manager but can read instructions.
Rationale
- The hard layer ensures no unverified code merges, regardless of the contributor's local setup.
- The automatic layer gives fast feedback during development without manual configuration.
- The soft layer guides behaviour through conventions and visibility.
- The combination works for all four contributor types: humans with skills, humans without skills, AI agents with skills, AI agents without skills.
- Each layer is optional -- a repo at Level 1 (see ADR-005) may only have soft enforcement, while Level 3 has all three.
Trade-offs and Limitations
.envrcrequires direnv -- documented as recommended, not required.- Composer/npm hooks only work for projects using those ecosystems. For other ecosystems,
.envrcor manualgit config core.hooksPath .githooks/is the fallback. - The hard layer requires repository admin access to configure branch protection.
- Git hooks can be bypassed with
--no-verifylocally, which is why the hard layer exists as backstop.
ADR-003: Skill Delegation Model
Status: Accepted Date: 2026-03-22 Context: The agent-harness skill could implement everything itself (AGENTS.md generation, branch protection setup, quality gates, test infrastructure) or delegate specialised work to existing skills. Several skills already exist in the Netresearch ecosystem: agent-rules, github-project, enterprise-readiness, typo3-testing, git-workflow, automated-assessment, and more. Decision: agent-harness delegates specialised work to existing skills and defines the integration contract (what artefacts it expects back). Consequences: The harness skill remains lean and focused on orchestration and verification. Delegation is advisory, not forced.
Delegation Map
| Task | Delegate To | Expected Artefact | Harness Verifies |
|---|---|---|---|
| AGENTS.md content | agent-rules-skill | AGENTS.md file | Is it index-format? Under 150 lines? No dead refs? |
| Branch protection | github-project-skill | Ruleset/protection config | Is harness-verify a required check? |
| Quality gates | enterprise-readiness-skill | Quality gate config | Are quality gates present? |
| Test infrastructure | typo3-testing / go-development / etc. | Test config and CI jobs | Do documented test commands work? |
| Commit conventions | git-workflow-skill | Git hooks, commit config | Are hooks installed? |
| Plan lifecycle | superpowers:writing-plans | Plan documents | Do active plans exist in docs/exec-plans/? |
| Maturity audit | automated-assessment-skill | Checkpoint evaluation | Do checkpoints pass at target level? |
How Delegation Works
The harness skill does not call delegated skills directly. Instead, it operates in two modes:
1. Verification mode -- checks whether the expected artefacts exist and are well-formed. This mode has no dependency on any delegated skill. It checks files and configurations, not tools.
2. Guidance mode -- when artefacts are missing or malformed, the skill reports what is wrong and which skill to invoke to fix it. For example: "AGENTS.md is 230 lines. Run agent-rules:agents to restructure it as an index (see ADR-004)."
This separation means teams can adopt harness verification without adopting all delegated skills. A team that manages AGENTS.md manually still gets verification. A team that uses agent-rules gets the same verification plus automated generation.
Rationale
- Avoids duplication -- each skill maintains its domain expertise.
- Allows the harness skill to remain lean and focused on orchestration.
- Skills evolve independently -- the harness skill does not need updating when agent-rules improves its AGENTS.md generation.
- Teams can adopt harness verification without adopting all delegated skills.
Implications
- The harness skill must clearly document when to invoke which delegate.
- The verification script works without delegated skills (it checks artefacts, not tools).
- The delegation map must be kept current as new skills are added to the ecosystem.
- Circular dependencies must be avoided -- delegated skills should not depend on agent-harness.
ADR-004: AGENTS.md as Index
Status: Accepted Date: 2026-03-22 Context: AGENTS.md files in practice tend to grow into encyclopedias -- long documents with detailed instructions, code patterns, API documentation, and architectural detail. This wastes agent context window (AGENTS.md is read every session), makes drift harder to detect, and duplicates information better stored elsewhere. OpenAI's harness engineering paper (https://openai.com/index/harness-engineering/) explicitly recommends AGENTS.md as a "table of contents" that points to detailed documentation elsewhere. Decision: AGENTS.md must be a compact index (hard limit: under 150 lines), not an encyclopedia. Detail lives in docs/ and other referenced files. Consequences: The verification script enforces the line limit and checks that all internal references resolve.
What AGENTS.md Should Contain
- Repo structure map -- where is what (10-15 lines). Enough for an agent to orient itself without reading every directory.
- Available commands -- build, test, lint, verify (10-15 lines). The commands an agent needs to validate its own work.
- Key rules -- architecture boundaries, commit format, coding standards (10-15 lines). Only rules that apply to every change.
- References -- links to ARCHITECTURE.md, design docs, ADRs, and other detailed documentation. The index entries.
What AGENTS.md Should NOT Contain
- Detailed API documentation (belongs in docs/ or inline code docs).
- Code patterns or examples (belongs in docs/patterns/ or a cookbook).
- Full architecture descriptions (belongs in docs/ARCHITECTURE.md).
- Historical context or ADRs (belongs in docs/adr/ or similar).
- CI/CD pipeline details (belongs in docs/ci.md or workflow comments).
- Troubleshooting guides (belongs in docs/troubleshooting.md).
Rationale
- Agents read AGENTS.md every session -- every line costs context window space.
- Short files are easier to keep current. Less drift surface means fewer stale instructions.
- The index pattern makes dead-reference detection mechanical: parse references, check they resolve.
- Detail in referenced files can be read on-demand, only when relevant to the current task.
- Multiple agents (Claude, Codex, Copilot, Gemini) all read AGENTS.md -- the compact format benefits all of them.
Enforcement
The verify-harness.sh script checks two things related to this ADR:
1. Line count -- AGENTS.md must be under 150 lines. If it exceeds this limit, verification fails with a message indicating the current line count and the limit.
2. Reference resolution -- every file path referenced in AGENTS.md (detected by patterns like docs/..., ./..., relative paths) must resolve to an existing file or directory in the repository. Dead references cause verification failure.
Migration Path for Existing Repos
Repos with long AGENTS.md files can migrate incrementally:
1. Identify sections that are detailed documentation (not index entries). 2. Move each section to an appropriate file in docs/. 3. Replace the section in AGENTS.md with a one-line reference to the new location. 4. Run make verify-harness to confirm the result is under 150 lines and all references resolve.
ADR-005: Checkpoint Maturity Model
Status: Accepted Date: 2026-03-22 Context: Binary "harness yes/no" is insufficient for gradual adoption. Teams need to understand their current maturity and what to do next. OpenAI's harness engineering paper describes maturity levels (single developer to small team to production). The Netresearch automated-assessment-skill already provides a checkpoint-based audit system. Decision: Three maturity levels, each with mechanical checkpoints that automated-assessment can evaluate. Consequences: Verification accepts a --level=N flag. Checkpoint IDs follow the scheme AH-0x (Level 1), AH-1x (Level 2), AH-2x (Level 3).
Level 1 -- Basic
Suitable for any repo at any team size. The minimum bar for agent-readiness.
| Checkpoint | ID | Verification |
|---|---|---|
| AGENTS.md exists | AH-01 | File exists at repo root |
| AGENTS.md is index-format | AH-02 | Under 150 lines (see ADR-004) |
| Commands are documented | AH-03 | AGENTS.md contains a commands section |
| docs/ directory exists | AH-04 | Directory exists at repo root |
Level 2 -- Verified
Suitable for team repos with CI. Adds consistency checks.
| Checkpoint | ID | Verification |
|---|---|---|
| All Level 1 checkpoints pass | -- | Prerequisite |
| All AGENTS.md references resolve | AH-11 | Every referenced path exists |
| Documented commands match actual targets | AH-12 | Commands listed in AGENTS.md exist in Makefile, composer.json, or package.json |
| docs/ARCHITECTURE.md exists | AH-13 | File exists |
| CI harness verification workflow exists | AH-14 | .github/workflows/harness-verify.yml exists |
Level 3 -- Enforced
Suitable for production repos with full enforcement. Adds server-side guarantees.
| Checkpoint | ID | Verification |
|---|---|---|
| All Level 2 checkpoints pass | -- | Prerequisite |
| harness-verify is a required check | AH-21 | Branch protection or ruleset includes harness-verify as required status check |
| Git hooks auto-activate on clone | AH-22 | .envrc sets core.hooksPath or equivalent mechanism exists |
| PR template includes harness checklist | AH-23 | .github/pull_request_template.md references harness verification |
| Drift detection is active | AH-24 | Structural changes (new dirs, renamed files) trigger docs-update warnings in CI |
Rationale
- Gradual adoption -- teams start at Level 1 and upgrade when ready.
- Each level is strictly additive -- Level 2 includes all of Level 1.
- Mechanical checkpoints make maturity measurable, not subjective. Every checkpoint can be evaluated by a script without human judgment.
- Integration with automated-assessment gives cross-skill audit capability.
- Levels map roughly to OpenAI's single-developer / small-team / production model.
Usage
The verification script accepts a level flag:
# Check Level 1 only (default)
./verify-harness.sh --level=1
# Check Levels 1 and 2
./verify-harness.sh --level=2
# Check all levels
./verify-harness.sh --level=3Teams can set their target level in project configuration (for example, in .harness.yml or as a variable in the CI workflow). The skill reports the current level and what is needed to reach the next level.
Checkpoint ID Scheme
- AH-0x -- Level 1 (Basic). IDs 01 through 09.
- AH-1x -- Level 2 (Verified). IDs 11 through 19.
- AH-2x -- Level 3 (Enforced). IDs 21 through 29.
This scheme leaves room for additional checkpoints within each level without renumbering.
Agent-First Architecture
Design choices that make a repository legible and predictable for AI coding agents. These complement the four system functions (constrain, inform, verify, correct) by addressing what the agent sees when it runs the system, not just when it reads about it.
Source: OpenAI Harness Engineering (<https://openai.com/index/harness-engineering/>).
Application Legibility
For an agent to validate its own changes, it must be able to inspect the running system. Without this, the agent is flying blind and depends entirely on test-suite proxies for correctness.
Three legibility primitives:
- Isolated runtime per worktree. Every git worktree should be able to spin up an isolated instance of the product on a unique port/socket so the agent's branch and the agent's running system are tied together. Tools: ddev with project-scoped names, docker compose with project-name overrides, devcontainers per worktree.
- Visual inspection. Agents inspect rendered output, not just code. Wire up Chrome DevTools Protocol or Playwright so the agent can request DOM snapshots and screenshots. Frontend changes that look correct in JSX may render broken; the harness should let the agent see that.
- Queryable observability. Logs, metrics, and traces should be locally accessible to the agent in structured form.
docker compose logs --since=30s --no-coloris enough for many cases. Without observability, agents debug by intuition.
These belong in the project's dev-environment scripts and Makefile/composer/npm targets, surfaced through AGENTS.md so the agent knows they exist.
Layered Dependency Model
OpenAI enforces a strict layered architecture. Their canonical stack:
Types -> Config -> Repo -> Service -> Runtime -> UIThe specific layer names are not the point; the point is that the dependency graph is explicit, declared in code, and enforced by tooling. Agents do not absorb architecture from culture -- they follow rules that produce errors.
Read the diagram left-to-right as "depends only on the next layer to the left": UI depends on Runtime; Runtime depends on Service; Service depends on Repo; and so on. A UI module reaching past Runtime to import Service or Repo directly is a violation.
Custom linters check imports against this rule. When a violation occurs, the linter must produce an actionable error message aimed at the agent: name the file, name the rule, name the fix.
Compare:
- ❌ "Architectural violation in
component.tsx" - ✅ "
component.tsx(UI layer) imports fromsrc/service/payments.ts(Service layer); UI must access Service through the Runtime layer. Seedocs/ARCHITECTURE.md#layer-rules."
Recommended starting points for repos using this skill:
1. Document the layer model in docs/ARCHITECTURE.md with a dependency diagram. 2. Add a custom linter rule (eslint-plugin-boundaries, deptrac for PHP, or a small AST script) that enforces it. 3. Make the rule a hard CI gate, not advisory.
Agent-First Technology Choices
Prefer composable, boring technologies with stable APIs over cutting-edge libraries with opaque internals.
Why: agents reason from context. A library with predictable, well-documented behaviour fits in the context window and yields correct code. A library that "does magic" forces the agent to either guess or re-read its source -- both of which fail at scale.
Practical implications:
- Use libraries with stable, well-documented APIs over those that change frequently or rely on convention-over-configuration.
- When an external library proves consistently unpredictable for agents (mocks fail; generated code looks plausible but is wrong; the agent invents APIs that do not exist), consider reimplementing the slice you actually need in-repo. Repo code is fully legible to the agent; library code is not.
- Boring beats clever for harnessed repos. The cost of a less-clever library is paid once; the cost of an opaque library is paid on every agent interaction.
This is not a license to NIH everything. It is a deliberate trade-off: pay implementation cost once to get reliable agent behaviour forever after.
How These Relate to the Four Functions
| Concept | Function | Where it lives |
|---|---|---|
| Application legibility | Inform + Verify | Dev-environment scripts, observability tooling, Makefile targets |
| Layered dependency model | Constrain | docs/ARCHITECTURE.md + custom linter |
| Boring technology choices | Constrain | Dependency policy in AGENTS.md, ADRs documenting reimplementation decisions |
These reinforce one another: a layered architecture composed of opaque libraries is no architecture at all, and legibility without constraint just shows the agent more chaos.
Enforcement Mechanisms Reference
This document covers all 10 enforcement instruments available for making repositories agent-ready. Mechanisms are ordered by enforcement strength, from hardest (server-side, nobody bypasses) to softest (convention-based, reminder only).
CI / Hook Parity Principle
The single most load-bearing rule across all 10 mechanisms: every fast, deterministic check that runs in CI must also run as a pre-commit hook. CI is the slow, parallel, authoritative backstop. It is not the first feedback loop. When a contributor (human or agent) commits broken code and learns about it 90 seconds later from a CI failure rather than 2 seconds earlier from a pre-commit hook, the harness has a gap — even if every CI gate is correctly configured.
The corollary: when CI catches a mechanical issue that a hook could have caught, the absence of the hook is the bug. Strengthen the harness rather than asking the operator to be more careful.
What counts as a fast check
A check qualifies for the hook layer if it:
- Completes in under ~5 seconds on a typical commit on the contributor's machine
- Is deterministic (same input → same result, no flakes)
- Has no external dependencies that the commit machine cannot satisfy (no remote API calls, no Docker pulls)
- Operates on the working tree or staged changes, not on a matrix of environments
Examples: linters, formatters, type-checkers, schema validators, AST-based static analysis, file-shape validators (e.g. SKILL.md word count, YAML well-formedness).
Examples that do NOT qualify and should stay CI-only: full test suites, mutation testing, security scanners with remote feeds, multi-version matrices, container builds, integration tests against live services.
Stack-native framework choice
Pick the hook framework the ecosystem already expects, not the one you personally prefer:
| Stack | Default framework | Why |
|---|---|---|
| PHP | captainhook/captainhook | Composer-installable, integrates with composer install |
| Go (binary-shipping projects) | lefthook | Single static binary, no runtime dependency, fast |
| Node-heavy frontends | husky + lint-staged | Ecosystem-native, integrates with npm prepare |
| Python / skill repos / mixed | pre-commit | Canonical Python-world tool; huge ecosystem of pre-built hooks with repo:+rev: pinning that Renovate/Dependabot bumps automatically; runs each hook in an isolated language env so contributor PATH doesn't matter |
| Shell-only / minimal | direct .githooks/ + .envrc | Zero dependencies, see mechanism #3 |
For skill repos specifically, prefer pre-commit over lefthook even though both work: skill repos contain Python helper scripts, contributors usually already have Python tooling (uv, ruff, validation scripts), and the upstream tools the validation pipeline depends on (markdownlint-cli2, yamllint, actionlint, ruff, shellcheck) all ship .pre-commit-hooks.yaml definitions that can be pinned by rev: and updated by dependency bots. See this repo's .pre-commit-config.yaml as the reference shape.
The framework choice is secondary to the principle. What matters is that the local set is a subset of the CI set — never a separate pipeline that drifts.
How parity fails in practice
Most parity gaps follow one of three patterns:
1. CI added a check, hook never updated. New linter, new validator, new format rule — wired into CI, forgotten locally. 2. Hook framework exists but is hollow. lefthook.yml is present and runs echo "lint", but the actual composer lint / go vet / validate-skill.sh invocation lives only in CI. 3. Hook bypassed by default. Contributors run git commit --no-verify because some hook step is slow or flaky. The fix is to make that step fast (or move it to pre-push / CI), not to tolerate the bypass.
Audit periodically: for each command line in CI workflows that meets the "fast check" definition above, grep the hook config files. If the command is not represented, that is the harness gap.
Mechanism Summary
| # | Mechanism | Triggers | Affects | Strength |
|---|---|---|---|---|
| 1 | Branch Protection / Rulesets | Merge attempt | Everyone | Hard |
| 2 | CI Workflows | PR push | Everyone | Hard |
| 3 | Git Hooks | Commit / push | Local devs | Automatic |
| 4 | .envrc (direnv) | cd into repo | Local devs with direnv | Automatic |
| 5 | Composer post-install-cmd | composer install | PHP devs | Automatic |
| 6 | npm prepare script | npm install | Node devs | Automatic |
| 7 | Makefile / justfile | Manual invocation | Everyone | Soft |
| 8 | AGENTS.md | Agent session start | AI agents | Soft |
| 9 | PR Templates | PR creation | PR authors | Soft |
| 10 | pre-commit framework | Commit (after install) | Local devs | Automatic |
Detailed Mechanisms
1. Branch Protection / Rulesets
What it is: GitHub server-side rules that block merging unless required conditions are met.
When it triggers: On merge attempt (merge button, API merge call, gh pr merge).
Who it affects: Everyone -- humans, agents, CI bots. No bypass without admin override.
Strength: Hard. Server-side enforcement cannot be circumvented locally.
Setup:
- Configure via GitHub UI: Settings > Branches > Branch protection rules, or Settings > Rules > Rulesets.
- Configure via API:
gh api repos/OWNER/REPO/branches/main/protection -X PUT. - Configure via
github-project-skill: delegates branch protection setup.
Key configuration: Add harness-verify as a required status check. This means the CI workflow from mechanism 2 must pass before any PR can merge.
Limitations: Requires repository admin access. Does not provide fast local feedback.
GitLab equivalent:
- Configure via GitLab UI: Settings > Repository > Protected branches, or Settings > Merge requests > Merge checks.
- Configure via API:
glab api projects/:id/protected_branches. - Add
harness-verifyas a required pipeline job. Under Settings > Merge requests, enable "Pipelines must succeed".
---
2. CI Workflows
What it is: A GitHub Actions workflow (.github/workflows/harness-verify.yml) that runs verify-harness.sh on every pull request.
When it triggers: On every PR push event. Can also trigger on push to specific branches.
Who it affects: Everyone. CI runs regardless of contributor setup.
Strength: Hard (when combined with branch protection). Automatic (standalone -- visible but not blocking).
Setup:
Copy or generate the workflow from templates/harness-verify.yml.tmpl:
name: Harness Verify
on:
pull_request:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify harness
run: bash scripts/verify-harness.sh --level=2The workflow uses only actions/checkout and bash -- no external action dependencies.
Reports: Results appear as GitHub Actions annotations (::error::, ::warning::) visible on the PR Files Changed tab.
Limitations: Requires a round-trip to CI. Local feedback is faster via hooks.
GitLab equivalent:
A GitLab CI job in .gitlab-ci.yml that runs verify-harness.sh on every merge request:
harness-verify:
stage: test
script:
- bash scripts/verify-harness.sh --level=2 --format=gitlab
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'Results appear in the job log. GitLab does not have inline file annotations, but the structured output is visible in the pipeline job output.
---
3. Git Hooks
What it is: Local scripts in .githooks/ that run before commits (pre-commit) and before pushes (pre-push).
When it triggers: pre-commit runs before every git commit. pre-push runs before every git push.
Who it affects: Local developers who have hooks activated. Does not affect CI or web-based edits.
Strength: Automatic (once activated). Can be bypassed with git commit --no-verify.
Setup:
# Activate hooks for this repo
git config core.hooksPath .githooks
# Or system-wide
git config --global core.hooksPath .githooksHooks should call verify-harness.sh:
#!/usr/bin/env bash
# .githooks/pre-commit
bash scripts/verify-harness.sh --level=1 --format=textLimitations: Requires activation. Bypassable with --no-verify. This is why the hard layer (CI + branch protection) exists as a backstop.
---
4. .envrc (direnv)
What it is: A direnv configuration file that activates automatically when a developer enters the repository directory.
When it triggers: On cd into the repo directory (if direnv is installed and allowed).
Who it affects: Local developers with direnv installed.
Strength: Automatic. Silent activation -- no manual step required after initial direnv allow.
Setup:
# .envrc
# Activate git hooks
git config core.hooksPath .githooks
# Add project scripts to PATH
PATH_add scripts
PATH_add binAfter creating .envrc, a developer entering the directory for the first time sees:
direnv: error .envrc is blocked. Run `direnv allow` to approve its contentAfter running direnv allow, all subsequent directory entries silently activate the configuration.
Limitations: Requires direnv installed. First-time direnv allow is a manual step. Not available in CI (not needed -- CI has its own workflow).
---
5. Composer post-install-cmd
What it is: A Composer lifecycle hook that runs after composer install or composer update.
When it triggers: After dependency installation in PHP projects.
Who it affects: PHP developers using Composer.
Strength: Automatic. Transparent to the developer -- hooks install as a side effect of normal workflow.
Setup:
Add to composer.json:
{
"scripts": {
"post-install-cmd": [
"git config core.hooksPath .githooks || true"
],
"post-update-cmd": [
"git config core.hooksPath .githooks || true"
]
}
}The || true ensures the script does not fail in environments without git (CI Docker containers, production deploys).
Limitations: PHP/Composer projects only. Does not work for contributors who skip composer install.
---
6. npm prepare Script
What it is: An npm lifecycle script that runs after npm install.
When it triggers: After dependency installation in Node projects.
Who it affects: Node developers using npm/yarn/pnpm.
Strength: Automatic. Transparent to the developer.
Setup (direct):
{
"scripts": {
"prepare": "git config core.hooksPath .githooks || true"
}
}Setup (with Husky):
{
"scripts": {
"prepare": "husky"
}
}Then configure Husky hooks to call verify-harness.sh.
Limitations: Node projects only. Does not work if --ignore-scripts is used.
---
7. Makefile / justfile
What it is: A build automation target that runs harness verification on demand.
When it triggers: Manual invocation (make verify-harness or just verify-harness).
Who it affects: Everyone who can run make/just. Language-agnostic.
Strength: Soft. Requires the contributor to know about and choose to run it.
Setup:
.PHONY: verify-harness
verify-harness:
bash scripts/verify-harness.sh --format=text
.PHONY: bootstrap-harness
bootstrap-harness:
@echo "Run agent-harness:bootstrap via your agent framework"
.PHONY: harness-status
harness-status:
bash scripts/verify-harness.sh --format=text --level=3 || trueAdvantages: Works in any project regardless of language or package manager. Discoverable via make help or reading the Makefile. Can be called by CI workflows.
Limitations: Requires manual invocation. Not enforced.
---
8. AGENTS.md
What it is: A markdown file at the repo root read by AI agents at the start of every session.
When it triggers: Agent session start. Claude Code, OpenAI Codex, GitHub Copilot, Gemini CLI, and other agents look for this file automatically.
Who it affects: AI agents. Humans can read it but it is optimised for agent consumption.
Strength: Soft. Convention-based. The agent reads it but is not mechanically forced to comply.
Setup:
Create AGENTS.md at the repo root following the index format (see ADR-004). Keep it under 150 lines. Reference detailed documentation in docs/ rather than inlining it.
# AGENTS.md
## Repo Structure
- `src/` -- application source
- `docs/` -- documentation (ARCHITECTURE.md, ADRs, design docs)
- `scripts/` -- automation scripts
## Commands
- `make build` -- build the project
- `make test` -- run all tests
- `make verify-harness` -- verify harness consistency
## Rules
- Follow conventional commits
- All new subsystems must be documented in ARCHITECTURE.mdLimitations: No mechanical enforcement. An agent can ignore instructions. This is why CI and hooks exist as harder layers.
---
9. PR Templates
What it is: A GitHub pull request template (.github/pull_request_template.md) that pre-fills the PR description with a checklist.
When it triggers: PR creation via GitHub UI or gh pr create.
Who it affects: PR authors. Visible reminder during PR creation.
Strength: Soft. Reminder only -- unchecked items do not block merge.
Setup:
Create .github/pull_request_template.md:
## Changes
<!-- Describe your changes -->
## Harness Checklist
- [ ] AGENTS.md updated (if commands or structure changed)
- [ ] docs/ updated (if architecture or design changed)
- [ ] New subsystems documented in ARCHITECTURE.md
- [ ] Exec plan created (if multi-file structural change)Limitations: Reminder, not enforcement. Contributors can delete the template text. No merge blocking.
GitLab equivalent:
GitLab uses merge request templates stored in .gitlab/merge_request_templates/:
<!-- .gitlab/merge_request_templates/Default.md -->
## Changes
<!-- Describe your changes -->
## Harness Checklist
- [ ] AGENTS.md updated (if commands or structure changed)
- [ ] docs/ updated (if architecture or design changed)
- [ ] New subsystems documented in ARCHITECTURE.md
- [ ] Exec plan created (if multi-file structural change)The Default.md template is automatically applied to new merge requests. Additional named templates can coexist in the same directory.
---
10. pre-commit Framework
What it is: A multi-language hook manager that standardises git hook setup via .pre-commit-config.yaml.
When it triggers: On commit (after pre-commit install has been run).
Who it affects: Local developers who have run pre-commit install.
Strength: Automatic (once installed). Bypassable with --no-verify.
Setup:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: verify-harness
name: Verify harness consistency
entry: bash scripts/verify-harness.sh --level=1 --format=text
language: system
pass_filenames: false
always_run: trueThen: pre-commit install
Advantages: Standardised hook management. Easy to add additional hooks (linting, formatting). Supports auto-update of hook versions.
Limitations: Requires pre-commit installed (pip install pre-commit). Requires pre-commit install to be run once. Bypassable with --no-verify.
The Activation Chain
This diagram shows how enforcement mechanisms activate in sequence during a typical development workflow:
Developer clones repo
|
+---> .envrc detected by direnv
| +---> git config core.hooksPath .githooks
| +---> scripts/ added to PATH
|
+---> composer install / npm install
| +---> post-install-cmd / prepare script
| +---> git hooks confirmed active
|
+---> Developer makes changes, runs git commit
| +---> .githooks/pre-commit runs
| +---> verify-harness.sh --level=1 (fast check)
| +---> Commit succeeds or fails with feedback
|
+---> Developer runs git push
| +---> .githooks/pre-push runs
| +---> verify-harness.sh --level=2 (full check)
| +---> Push succeeds or fails with feedback
|
+---> PR/MR created
| +---> PR/MR template pre-fills harness checklist
| +---> CI workflow/pipeline triggers
| +---> verify-harness.sh runs in CI
| +---> Results reported as annotations (GitHub) or job log (GitLab)
|
+---> Merge attempted
+---> Branch protection checks required status
+---> harness-verify must be green
+---> Merge succeeds or is blockedEach layer catches issues that earlier layers missed or that bypassed them. The chain is designed so that the last layer (branch protection) is impossible to bypass without admin access.
Choosing Mechanisms for Your Project
Minimum (any project)
- AGENTS.md (mechanism 8)
- CI workflow (mechanism 2)
- Makefile target (mechanism 7)
This is the Level 1 baseline. Works for any language, any team size.
PHP project
All of the minimum, plus:
- Composer post-install-cmd (mechanism 5)
- .envrc (mechanism 4)
- Git hooks (mechanism 3)
Node project
All of the minimum, plus:
- npm prepare script (mechanism 6)
- Husky or direct hooks (mechanism 3)
- .envrc (mechanism 4)
Go project
All of the minimum, plus:
- .envrc (mechanism 4)
- Makefile targets (mechanism 7 -- Go projects already use Make heavily)
- Git hooks (mechanism 3)
Maximum (Level 3)
All mechanisms active:
- Branch protection with
harness-verifyas required check (mechanism 1) - CI workflow (mechanism 2)
- Git hooks via .githooks/ (mechanism 3)
- .envrc for automatic activation (mechanism 4)
- Language-specific auto-setup (mechanism 5 or 6)
- Makefile targets (mechanism 7)
- AGENTS.md as index (mechanism 8)
- PR template with harness checklist (mechanism 9)
- pre-commit framework (mechanism 10, optional -- overlaps with direct hooks)
Harness Engineering Overview
What is Harness Engineering?
Harness engineering is the discipline of designing repo-level infrastructure that makes AI coding agents reliable at scale. It represents a fundamental shift in how teams work with AI: from "humans write code, AI helps" to "humans design environments, agents execute."
The metaphor is straightforward. Modern AI models are powerful but directionless. A model with no constraints, no context, and no verification will produce plausible-looking output that may or may not solve the actual problem. The harness channels that raw capability into productive, verifiable work -- the same way a test harness channels code execution into observable, repeatable outcomes.
The harness is everything the model reads and everything that checks its output: AGENTS.md, architecture docs, CI workflows, git hooks, branch protection, linting rules, test suites, and the structural conventions that tie them together.
The Four System Functions
OpenAI's harness engineering research (<https://openai.com/index/harness-engineering/>) identifies four system functions that a well-designed harness must provide. These are not sequential phases but concurrent, reinforcing layers.
1. Constrain
Define architectural boundaries and dependency rules. Tell the agent what it must not do, what patterns to follow, and where code belongs.
Constraining the solution space makes agents more productive, not less. An agent that knows "all database access goes through the repository layer" does not waste tokens exploring direct SQL in controllers. An agent that knows "this project uses conventional commits" does not invent its own commit message format.
Constraints live in AGENTS.md, ARCHITECTURE.md, linter configurations, and dependency rules.
2. Inform
Provide rich context so the agent understands the system it is working in. This includes architecture documentation, API specs, design decisions (ADRs), test expectations, and observability data.
The repository is the single source of truth. If the agent needs to know something to do its job, that information must be in the repo -- not in a team member's head, not in a Confluence page, not in a Slack thread. Context engineering is the practice of making relevant information discoverable and machine-readable within the repo structure.
Information lives in docs/, AGENTS.md references, inline code comments, and structured configuration files.
3. Verify
Test and validate agent output through mechanical means: linting, CI pipelines, structural tests, type checking, and harness consistency checks. Mechanical verification catches problems that human review misses or delays.
The key insight is that verification must be automatic and continuous. A verification step that requires a human to remember to run it is not verification -- it is a suggestion. CI workflows, pre-commit hooks, and required status checks provide genuine verification.
Verification lives in .github/workflows/, .githooks/, Makefile targets, and test suites.
4. Correct
Build feedback loops that let agents iterate until criteria are satisfied. When verification fails, the agent receives structured feedback (error messages, lint output, test failures) and tries again. Self-repair turns a single-shot interaction into a convergent loop.
Correction depends on clear, actionable error messages. A CI check that reports "harness verification failed" is less useful than one that reports "AGENTS.md references docs/API.md but that file does not exist." The more specific the feedback, the fewer iterations needed.
Correction lives in CI annotations, hook output, and structured error reporting from verification scripts.
The harness does not store learning itself. It provides the rails: memory files, rule files, CI checks, hooks, review templates. Learning — capturing reusable patterns from sessions and routing them to the correct destination — is performed by retro-skill (see skill-integration-map.md #12) and materialized through specialist skills (agent-rules, skill-repo, automated-assessment). The harness verifies the integration points exist (AH-22, AH-23) but does not own the learning loop.
Complementary Perspectives
Anthropic / Claude Code
Anthropic's agent development guidance (<https://docs.anthropic.com/en/docs/build-with-claude/agentic-systems>) emphasises:
- TDD-first workflows -- write tests before implementation so the agent has a concrete target.
- Plan mode -- agents propose a plan, get human approval, then execute. Separates thinking from doing.
- Compact context transfer -- keep instruction documents short and reference external files for detail. AGENTS.md as an index, not an encyclopedia.
- Dedicated review steps -- do not assume agent output is correct. Build review into the workflow.
LangGraph and Durable Execution
LangGraph and similar frameworks focus on runtime durability:
- Checkpointing -- save agent state at each step so work survives failures.
- Resume after failures -- crashed agents pick up where they left off instead of restarting.
- Human-in-the-loop -- pause execution for human approval at defined points.
These runtime concerns are complementary to repo-level harness engineering. This skill focuses on the repo structure and verification layer. Runtime durability (tracing, evals, checkpointing) is a future extension.
Industry Consensus
Across vendors and frameworks, several principles have converged:
- Large monolithic instruction files are counterproductive. Context must be structured and layered.
- Agents need external feedback loops. Self-assessment is unreliable; mechanical verification is essential.
- The repo itself is the best place to store agent instructions. External configuration drifts.
- Enforcement must work without the agent framework installed. Project-level mechanisms (CI, hooks, branch protection) outlive any specific tool.
Operational Patterns from OpenAI's Deployment
OpenAI's five-month internal deployment (~1,500 PRs, ~1M LOC, team scaled 3 to 7 engineers) surfaced operational patterns that go beyond the four system functions. These describe how to run a harnessed repo day-to-day, not how to structure it.
Merge Philosophy: Minimal Blocking Gates
Conventional code-review norms (two approvals, comprehensive manual QA, "every PR gets a comment") become bottlenecks once agents open dozens of PRs per day. OpenAI's stance:
- Minimal blocking merge gates -- only mechanical checks block (tests, linting, harness verification). Subjective gates do not.
- Short-lived pull requests -- merge fast, iterate via follow-up PRs.
- Higher tolerance for quick post-merge corrections -- "the cost of a quick correction is low when the agent can implement it in minutes. The cost of blocking every merge on comprehensive upfront validation compounds across hundreds of concurrent tasks."
This is consistent with the Level 3 stance that branch protection requires harness-verify to pass -- because that check is fast and mechanical. It is not consistent with stacking subjective approval gates, manual QA sign-off, or "minimum reviewer count" policies on top of an agent-driven workflow.
Continuous Entropy Management
Treat pattern drift as a continuous background process, not a periodic sprint:
- Define canonical patterns (logging format, naming conventions, component shape) as mechanical linter rules.
- Run recurring background agents that scan for deviations and open auto-mergeable refactor PRs.
- Treat technical debt as compound interest -- small continuous cleanup payments are far cheaper than waiting for a large refactor sprint.
The opposite pattern -- batching cleanup into periodic "fix the AI slop" sessions -- is explicitly called out as inefficient. Continuous correction beats episodic correction.
Additional Anti-Patterns
In addition to the anti-patterns covered earlier (monolithic instruction files, stale documentation), the article identifies two more:
- Unpredictable third-party dependencies. Libraries with opaque internals or unstable APIs make agents unreliable because they cannot reason about behaviour. See
agent-first-architecture.mdfor the agent-first technology trade-off. - Periodic cleanup sprints. Batching technical debt is more disruptive and more expensive than continuous background cleanup. See "Continuous entropy management" above.
The Key Principle
"The model is commodity; the harness is moat."
-- OpenAI, Harness Engineering
OpenAI's research demonstrated this quantitatively. Improving the harness -- without changing the underlying model -- raised task performance from 52.8% to 66.5%. The same model, given better constraints, better context, better verification, and better correction loops, produced dramatically better results.
This means that investment in harness engineering compounds. Every improvement to documentation, CI checks, architectural constraints, and feedback loops benefits every agent interaction going forward, regardless of which model or framework is used.
What This Skill Implements
The agent-harness skill implements the repo-structure and verification layer of harness engineering:
- Constrain: AGENTS.md with architectural rules, ARCHITECTURE.md with dependency boundaries.
- Inform: Structured
docs/directory, index-format AGENTS.md with references to detailed documentation. - Verify:
verify-harness.shscript, CI workflow (harness-verify.yml), git hooks, maturity-level checkpoints. - Correct: Actionable error messages from verification, bootstrap mode to create missing artefacts, structured output for CI annotations.
Runtime concerns (agent tracing, evaluation frameworks, durable execution, LLM observability) are outside the current scope and tracked as future extensions.
Sources
- OpenAI Harness Engineering: <https://openai.com/index/harness-engineering/>
- SWE Quiz commentary on the OpenAI writeup (source of the deployment metrics and operational-pattern framing in this doc): <https://www.swequiz.com/articles/openai-harness-engineering>
- Anthropic Agent Development: <https://docs.anthropic.com/en/docs/build-with-claude/agentic-systems>
- Claude Code SDK: <https://docs.claude.com/en/api/agent-sdk>
Harness Maturity Levels
The harness maturity model defines three levels of agent-readiness for a repository. Each level builds on the previous one, adding stronger enforcement and more comprehensive verification. Levels are measured mechanically via checkpoints -- there is no subjective assessment.
Level Overview
| Level | Name | Target | Effort (manual) | Effort (with skill) |
|---|---|---|---|---|
| 1 | Basic | Any repo, solo dev, minimal effort | ~15 minutes | ~2 minutes |
| 2 | Verified | Team repos, CI-backed, actively maintained | ~30 minutes | ~5 minutes |
| 3 | Enforced | Production repos, full enforcement, drift-resistant | ~1 hour | ~10 minutes |
Level 1 -- Basic
Target audience: Any repository, solo developer or small team, minimal effort to adopt.
Requirements
| Checkpoint | Check | Severity |
|---|---|---|
| AH-01 | AGENTS.md exists at repo root | Error |
| AH-02 | AGENTS.md is index-format (under 150 lines) | Warning |
| AH-03 | AGENTS.md documents available commands (build, test, lint) | Warning |
| -- | docs/ directory exists (even if minimal) | Warning |
What it gives you
- Any AI agent can understand your repo. Claude Code, OpenAI Codex, GitHub Copilot, and Gemini CLI all read
AGENTS.mdat session start. A compact, well-structured AGENTS.md means every agent interaction starts with correct context. - Contributors know what commands to run. New team members (human or AI) can find build, test, and lint commands without reading source code.
- Baseline for gradual improvement. Level 1 is the foundation. Everything at Level 2 and 3 builds on these artefacts.
What it does not give you
- No mechanical verification that docs are accurate.
- No CI enforcement.
- No protection against documentation drift.
How to set up
Manual:
1. Create AGENTS.md at the repo root. Use the index format -- keep it under 150 lines. Include sections for repo structure, commands, and rules. 2. Create a docs/ directory. Add at least a placeholder file. 3. Document your build, test, and lint commands in AGENTS.md.
With skill bootstrap:
agent-harness:bootstrap --level=1The skill analyses the repo, detects available commands from Makefile/composer.json/package.json, and generates AGENTS.md from the template.
Verification
bash scripts/verify-harness.sh --level=1 --format=textExample output:
Agent Harness Verification
==========================
Level 1 -- Basic
✓ AGENTS.md exists
✓ AGENTS.md is index-format (87 lines)
✓ Commands section found
✓ docs/ directory exists
Summary: Level 1 COMPLETE | 0 error(s), 0 warning(s)---
Level 2 -- Verified
Target audience: Team repositories with CI, actively maintained, multiple contributors.
Requirements
All of Level 1, plus:
| Checkpoint | Check | Severity |
|---|---|---|
| AH-10 | All references in AGENTS.md resolve to existing files | Error |
| -- | Documented commands match actual Makefile/composer/npm targets | Warning |
| AH-11 | docs/ARCHITECTURE.md exists with system overview | Warning |
| AH-12 | CI workflow runs harness verification on every PR/MR | Warning |
| AH-30 | Test runner infrastructure exists (runTests.sh or Makefile) | Warning |
| AH-31 | PHPStan configured at level 8+ (PHP projects only) | Warning |
| AH-32 | Git hooks configured for pre-commit quality checks — must mirror CI's fast checks (see CI/Hook Parity Principle in references/enforcement-mechanisms.md; skill/Python projects: prefer .pre-commit-config.yaml) | Warning |
| AH-33 | At least one test file exists (multi-language) | Error |
| AH-36 | Hook config references at least one of CI's fast-check commands (best-effort parity check) | Warning |
Note: AH-30..AH-33 and AH-36 are assessed via the automated-assessment checkpoint runner (/assess agent-harness), not byverify-harness.sh. The verification script covers structural harness checks; quality delegation checkpoints are evaluated by the assessment skill.
What it gives you
- Mechanical guarantee that docs are not lying. Every file path referenced in AGENTS.md is verified to exist. Every command documented in AGENTS.md is verified to match an actual build target. If someone renames a file or removes a Makefile target, verification catches it.
- Architecture is documented for onboarding. New contributors (human or AI) can read ARCHITECTURE.md to understand the system before modifying it. This is the "Inform" function from harness engineering.
- CI catches harness drift automatically. The harness verification workflow runs on every PR. If a PR changes the Makefile but does not update AGENTS.md, the CI check warns about it.
What it does not give you
- CI results are advisory, not blocking (unless branch protection is configured).
- No automatic hook setup -- contributors must manually activate hooks.
- No drift detection for structural file changes.
How to set up
Manual:
1. Complete all Level 1 requirements. 2. Audit every file reference in AGENTS.md. Fix or remove any that point to non-existent files. 3. Audit every command in AGENTS.md. Ensure each one matches an actual Makefile target, composer script, or npm script. 4. Create docs/ARCHITECTURE.md. Include at minimum: system overview (1 paragraph), component map, and dependency rules. 5. Create .github/workflows/harness-verify.yml using the template. This workflow runs verify-harness.sh on every PR. 6. GitLab alternative: If using GitLab, add a harness-verify job to .gitlab-ci.yml using the template. This job runs verify-harness.sh on every merge request.
With skill bootstrap:
agent-harness:bootstrap --level=2The skill creates ARCHITECTURE.md from the template, generates the CI workflow, and fixes any broken references it can detect.
Verification
bash scripts/verify-harness.sh --level=2 --format=textExample output:
Agent Harness Verification
==========================
Level 1 -- Basic
✓ AGENTS.md exists
✓ AGENTS.md is index-format (87 lines)
✓ Commands section found
✓ docs/ directory exists
Level 2 -- Verified
✓ All references resolve
✓ All make targets verified (3 targets)
✓ docs/ARCHITECTURE.md exists
✓ CI harness workflow exists
Summary: Level 2 COMPLETE | 0 error(s), 0 warning(s)---
Level 3 -- Enforced
Target audience: Production repositories, full enforcement, drift-resistant. Repos where harness consistency is a hard requirement.
Requirements
All of Level 2, plus:
| Checkpoint | Check | Severity |
|---|---|---|
| AH-20 | PR/MR template includes harness checklist | Warning |
| AH-21 | Git hooks auto-activate on clone (via the chosen framework: prepare script in package.json, post-install-cmd in composer.json, or .envrc via direnv) | Warning |
| AH-22 | PR/MR template includes retro question for agent-authored work | Warning |
| AH-23 | SessionEnd hook configured (optional convenience for retro auto-trigger) | Info |
| AH-34 | Mutation testing configuration exists | Info |
| AH-35 | Code coverage configuration exists | Info |
| -- | Assessment checkpoints pass for all applicable skills | Warning |
| -- | Drift detection: structural file changes trigger warnings if AGENTS.md is not also updated | Warning |
What it gives you
- No unverified code merges.
harness-verifyis a required status check in branch protection. If the harness is inconsistent, the PR cannot merge. This works for all contributors -- human or AI, with or without skills installed. - New contributors get fast feedback immediately. Git hooks auto-activate on clone via the stack-native mechanism — the
preparescript inpackage.json(Node),post-install-cmdincomposer.json(PHP), or.envrcvia direnv (any stack, especially Python-only / skill repos). No manual setup required. The first commit attempt runs verification. - Structural changes cannot silently break documentation. Drift detection monitors changes to structural files (Makefile, composer.json, package.json, CI workflows). If these files change in a PR but AGENTS.md is not also updated, the verification emits a warning.
- Full enforcement works for everyone. The enforcement is project-level (CI workflows, branch protection, git hooks), not tool-level. It works whether the contributor uses Claude Code, VS Code, vim, or the GitHub web editor.
What it does not give you
- Runtime agent observability (tracing, evals).
- Automatic AGENTS.md updates (the skill detects drift but does not auto-fix).
- Cross-repo consistency (each repo is verified independently).
How to set up
Manual:
1. Complete all Level 2 requirements. 2. Configure branch protection: on GitHub, add harness-verify as a required status check on the default branch. On GitLab, enable 'Pipelines must succeed' under Settings > Merge requests. 3. Choose a hook framework appropriate for the stack:
- `pre-commit` (recommended for skill/Python projects) — add a
.pre-commit-config.yamlreferencing the hook providers andpre-commit install --install-hooksto activate. Seereferences/enforcement-mechanisms.md§ "Stack-native framework choice" and § "CI / Hook Parity Principle" for full rationale; skill repos consumevalidate-skill+check-version-parityfromnetresearch/skill-repo-skill@v1.22.0+(pin a specific tag and let Renovate bump). captainhook/captainhook(PHP) — install via composer, configurecaptainhook.json.lefthook(Go binary-shipping projects, e.g. ofelia) — install the static binary, configurelefthook.yml.husky+lint-staged(Node-heavy frontends) — install via npm, wire intopackage.json.- Direct
.githooks/+.envrcwithgit config core.hooksPath .githooks(zero-dependency fallback).
4. Wire hook auto-activation so contributors don't run the install command manually. Pick the option that matches the contributor's typical install step:
pre-commitprojects withpackage.json: add apreparescript underpackage.json'sscriptsrunningpre-commit install --install-hooks(silent no-op if pre-commit isn't on PATH).pre-commitprojects withcomposer.json: add apost-install-cmdtocomposer.jsondoing the same.pre-commitprojects with neither (pure Python / skill repos): add an.envrc(direnv) that runspre-commit install --install-hooksoncdinto the repo. This is the canonical Python-ecosystem path.- Direct
.githooks/route: an.envrcwithgit config core.hooksPath .githooksworks for direnv users.
5. Create the PR/MR template. For GitHub: copy to .github/pull_request_template.md. For GitLab: copy to .gitlab/merge_request_templates/Default.md. 6. Ensure the chosen hook framework's hook checks are a subset of CI — see references/enforcement-mechanisms.md § "CI / Hook Parity Principle". For the direct .githooks/ route, ensure .githooks/pre-commit and .githooks/pre-push exist and are executable. The structural-vs-quality split (structural harness checks via verify-harness.sh, quality checks delegated to the automated-assessment runner) is encoded in checkpoints.yaml — treat that file as the authoritative source for what each checkpoint requires.
With skill bootstrap:
agent-harness:bootstrap --level=3The skill creates all missing artefacts and delegates branch protection setup to github-project-skill.
Verification
bash scripts/verify-harness.sh --level=3 --format=textExample output:
Agent Harness Verification
==========================
Level 1 -- Basic
✓ AGENTS.md exists
✓ AGENTS.md is index-format (92 lines)
✓ Commands section found
✓ docs/ directory exists
Level 2 -- Verified
✓ All references resolve
✓ All make targets verified (6 targets)
✓ docs/ARCHITECTURE.md exists
✓ CI harness workflow exists
Level 3 -- Enforced
✓ Git hooks auto-setup via .envrc
✓ PR template exists (repo-level)
✓ No drift detected
Summary: Level 3 COMPLETE | 0 error(s), 0 warning(s)---
Upgrade Paths
Level 1 to Level 2
1. Add the CI workflow. Copy templates/harness-verify.yml.tmpl to .github/workflows/harness-verify.yml. Adjust the level flag to --level=2. 2. Create ARCHITECTURE.md. Use templates/ARCHITECTURE.md.tmpl as a starting point. Document the system overview, component map, and dependency rules. 3. Fix dead references. Run verify-harness.sh --level=2 and fix any file paths in AGENTS.md that do not resolve. 4. Align commands. Ensure every command listed in AGENTS.md has a matching Makefile target, composer script, or npm script.
Level 2 to Level 3
1. Configure branch protection. Add harness-verify as a required status check. This is the single most impactful change -- it turns advisory CI into blocking enforcement. 2. Choose a hook framework (skill repos consume validate-skill + check-version-parity from netresearch/skill-repo-skill@v1.22.0+). Skill/Python projects: pre-commit with .pre-commit-config.yaml (recommended). PHP: captainhook. Go binary-shipping: lefthook. Node-heavy frontends: husky + lint-staged. Zero-dependency fallback: direct .githooks/ + .envrc. See references/enforcement-mechanisms.md § "Stack-native framework choice" for the full table. 3. Add hook auto-setup so contributors don't run install manually. Pick the option that matches the contributor's typical install step:
pre-commitprojects withpackage.json: apreparescript underscriptsrunningpre-commit install --install-hooks.pre-commitprojects withcomposer.json: apost-install-cmddoing the same.pre-commitprojects with neither (pure Python / skill repos): an.envrc(direnv) runningpre-commit install --install-hooksoncd.- Direct
.githooks/route:.envrcwithgit config core.hooksPath .githooks.
4. Create the PR template. Copy templates/pull_request_template.md.tmpl to .github/pull_request_template.md. 5. Ensure CI/Hook parity. Whatever framework runs locally, its hook checks must be a subset of what CI runs (see references/enforcement-mechanisms.md § "CI / Hook Parity Principle"). checkpoints.yaml is the authoritative source for what each AH-* requires. For the direct route, add .githooks/pre-commit and .githooks/pre-push calling verify-harness.sh.
Measuring Maturity
Command-line usage
# Check current maturity level (runs all checks, reports highest passing level)
bash scripts/verify-harness.sh --format=text
# Check a specific level
bash scripts/verify-harness.sh --level=2 --format=text
# Use in CI (exits non-zero on failure)
bash scripts/verify-harness.sh --level=2
# Run a single check category
bash scripts/verify-harness.sh --check=refs --format=textCI usage
# .github/workflows/harness-verify.yml
- name: Verify harness (Level 2)
run: bash scripts/verify-harness.sh --level=2The default output format uses GitHub Actions annotation syntax (::error::, ::warning::), which makes results visible directly on the PR Files Changed tab.
# .gitlab-ci.yml
harness-verify:
stage: test
script: bash scripts/verify-harness.sh --level=2 --format=gitlab
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'The GitLab format uses structured log output. Enable "Pipelines must succeed" in GitLab merge request settings to make it a hard gate.
Automated assessment usage
The checkpoints.yaml file integrates with automated-assessment-skill for batch auditing across multiple repositories:
# Audit a single repo
automated-assessment:audit --skill=agent-harness --target=/path/to/repo
# Audit all repos in an organisation
automated-assessment:audit --skill=agent-harness --org=netresearchCheckpoint Reference
| ID | Level | Check | Severity | Type |
|---|---|---|---|---|
| AH-01 | 1 | AGENTS.md exists | Error | file_exists |
| AH-02 | 1 | AGENTS.md under 150 lines | Warning | command |
| AH-03 | 1 | AGENTS.md has commands section | Warning | regex |
| AH-04 | 1 | docs/ directory exists | Warning | command |
| AH-10 | 2 | No dead references in AGENTS.md | Error | command |
| AH-11 | 2 | docs/ARCHITECTURE.md exists | Warning | file_exists |
| AH-12 | 2 | CI harness verification workflow exists (GitHub Actions or GitLab CI) | Warning | command |
| AH-20 | 3 | PR/MR template with harness checklist | Warning | command |
| AH-21 | 3 | Git hooks auto-activate | Warning | command |
| AH-22 | 3 | PR/MR template includes retro question | Warning | command |
| AH-23 | 3 | SessionEnd hook configured (optional) | Info | file_exists |
| AH-30 | 2 | Test runner infrastructure exists | Warning | command |
| AH-31 | 2 | PHPStan level 8+ configured (PHP only) | Warning | command |
| AH-32 | 2 | Git hooks for pre-commit quality checks | Warning | command |
| AH-33 | 2 | At least one test file exists (multi-language) | Error | command |
| AH-34 | 3 | Mutation testing configuration exists | Info | file_exists |
| AH-35 | 3 | Code coverage configuration exists | Info | file_exists |
| AH-36 | 2 | Hook config references at least one of CI's fast-check commands (parity) | Warning | command |
Skill Integration Map
The agent-harness skill does not operate in isolation. It delegates specialised work to other skills in the ecosystem and verifies that the output of those skills meets harness requirements. This document defines the integration contract for each skill.
Integration Principle
The harness skill checks artefacts, not tools. It verifies that the OUTPUT of delegated skills is present and consistent. It does not require the delegated skill to be installed. A team that creates AGENTS.md manually gets the same verification as a team that used agent-rules-skill to generate it.
This means:
- The harness skill never imports or calls another skill's code directly.
- Integration is through shared file conventions (AGENTS.md, ARCHITECTURE.md, CI workflows).
- Verification works on any repo, regardless of which skills were used to set it up.
Skill Integration Details
1. agent-rules-skill
What it provides: Generates AGENTS.md content following best practices for agent-readable repository documentation.
When harness delegates to it: When AGENTS.md needs to be created (bootstrap mode) or updated (after structural changes). The harness skill invokes agent-rules when it detects AGENTS.md is missing or when a user explicitly requests AGENTS.md generation.
What harness expects back:
- An
AGENTS.mdfile at the repo root. - Index format: compact, under 150 lines.
- Contains at minimum: repo structure section, commands section, rules section.
- References external documentation in
docs/rather than inlining detail.
What harness verifies:
AGENTS.mdexists (checkpoint AH-01).AGENTS.mdis under 150 lines (checkpoint AH-02).AGENTS.mdcontains a commands section (checkpoint AH-03).- All file references in
AGENTS.mdresolve to existing files (checkpoint AH-10).
---
2. github-project-skill / GitLab project settings
What it provides: Configures platform features: branch protection rules, PR/MR templates, CODEOWNERS/code owners, repository settings, label schemas.
Platform notes:
- GitHub: Delegates to
github-project-skillfor branch protection and PR template setup. - GitLab: No equivalent skill exists yet. Configure branch protection and merge request settings manually via GitLab UI (Settings > Repository > Protected branches, Settings > Merge requests).
When harness delegates to it (GitHub): When Level 3 enforcement needs to be set up on GitHub, the harness skill delegates branch protection configuration and PR template creation to github-project-skill. On GitLab, the harness does not delegate these actions; it only verifies that branch protection and merge request templates have been configured manually as described above.
What harness expects back:
- Branch protection rule on the default branch with
harness-verifyas a required status/pipeline check. - PR template at
.github/pull_request_template.md(GitHub) or MR template at.gitlab/merge_request_templates/Default.md(GitLab). - CODEOWNERS file if the project has designated maintainers.
What harness verifies:
- PR template exists (checkpoint AH-20).
harness-verifyis listed as a required status check (verified viagh api, not by file inspection).- PR template contains harness-related checklist items.
---
3. enterprise-readiness-skill
What it provides: Quality gates, SLSA provenance configuration, SBOM generation, OpenSSF Scorecard integration, supply chain security setup.
When harness delegates to it: When assessing production-readiness of a repository. The harness skill does not directly invoke enterprise-readiness but references it when a repo needs to move beyond harness maturity into production-readiness concerns.
What harness expects back:
- Quality gate configuration in CI workflows.
- Security scanning enabled (dependency review, CodeQL, or equivalent).
- SLSA provenance configured for releases.
What harness verifies:
- Quality gate workflows exist (informational -- not a harness checkpoint).
- The harness skill reports enterprise-readiness as a separate concern, not a harness maturity requirement.
---
4. typo3-testing-skill
What it provides: Test infrastructure for TYPO3 extensions: PHPUnit configuration, functional test setup, CI test matrix, code coverage configuration.
When harness delegates to it: When the target repo is a TYPO3 extension and test infrastructure needs setup. The harness skill detects TYPO3 extensions by the presence of ext_emconf.php or TYPO3-specific composer types.
What harness expects back:
- Test commands defined in
composer.jsonscripts (e.g.,ci:test:php:unit,ci:test:php:functional). - Test commands documented in AGENTS.md.
- CI workflow that runs tests.
What harness verifies:
- Documented test commands in AGENTS.md match actual
composer.jsonscript definitions (checkpoint AH-11). - CI workflow exists and references the test commands.
---
5. go-development-skill
What it provides: Go application patterns, test infrastructure, linting configuration (golangci-lint), Makefile targets for Go projects.
When harness delegates to it: When the target repo is a Go project (detected by go.mod). Same delegation pattern as typo3-testing but for Go.
What harness expects back:
- Test commands defined as Makefile targets (e.g.,
make test,make lint). - Test commands documented in AGENTS.md.
- CI workflow that runs Go tests and linting.
What harness verifies:
- Documented
maketargets in AGENTS.md match actual Makefile targets (checkpoint AH-11). - CI workflow exists and runs tests.
---
6. git-workflow-skill
What it provides: Commit conventions, branching strategy, git hooks, changelog generation, release workflow patterns.
When harness delegates to it: When git workflow setup is needed (hooks, commit message format, branching rules). The harness skill delegates hook content and commit format rules to git-workflow-skill.
What harness expects back:
- Git hooks configured in
.githooks/directory. - Commit format defined (conventional commits or project-specific).
- Hooks documented in AGENTS.md rules section.
What harness verifies:
.githooks/directory exists with executable hooks (checkpoint AH-21 -- partial).- Hook auto-activation is configured via
.envrc, composer, or npm (checkpoint AH-21). - Commit format rules are documented in AGENTS.md.
---
7. concourse-ci-skill
What it provides: Concourse CI pipeline definitions, task configurations, resource types.
When harness delegates to it: When the target repo uses Concourse CI instead of or alongside GitHub Actions. The harness skill detects Concourse by the presence of ci/ or concourse/ directories with pipeline YAML files.
What harness expects back:
- Pipeline definition files in a standard location.
- CI commands documented in AGENTS.md.
What harness verifies:
- Documented CI commands match pipeline task definitions (checkpoint AH-11 -- adapted for Concourse).
- If both GitHub Actions and Concourse are present, both are documented.
---
8. docker-development-skill
What it provides: Docker setup, docker-compose configuration, multi-stage build patterns, development environment containerisation.
When harness delegates to it: When Docker-based development setup is needed. The harness skill does not directly manage Docker configuration but verifies that Docker commands are documented.
What harness expects back:
- Docker commands documented in AGENTS.md (e.g.,
docker compose up,make docker-build). docker-compose.ymlor equivalent present if referenced.
What harness verifies:
- Documented Docker commands reference files that exist (checkpoint AH-10 -- general reference check).
- Docker-related commands in AGENTS.md match actual compose file service definitions (best-effort).
---
9. automated-assessment-skill
What it provides: Checkpoint-based audit system. Reads checkpoints.yaml from skills and evaluates them mechanically against a target repository.
When harness delegates to it: The relationship is inverted -- automated-assessment reads the harness skill's checkpoints, not the other way around. The harness skill provides checkpoints.yaml that defines what to check; automated-assessment provides the runtime that evaluates those checks.
What harness provides to it:
checkpoints.yamlwith maturity-level checks (AH-01 through AH-21).- Preconditions (must be a git repository).
- Severity levels (error vs. warning) for each checkpoint.
What harness expects back:
- Assessment results in structured format (pass/fail per checkpoint).
- Maturity level determination (Level 1/2/3 based on which checkpoints pass).
What harness verifies: N/A -- automated-assessment is the verifier, not the verified.
Integration Rule: Assessment Before Enhancement
When any quality-related skill is invoked to ENHANCE (not just verify) a project's quality posture, the automated-assessment skill MUST run first. This applies to:
typo3-testinginvoked with "enhance", "improve", "strengthen"enterprise-readinessinvoked with "audit", "production ready"php-modernizationinvoked with "upgrade", "modernize"security-auditinvoked with "audit", "scan", "review"
The assessment generates a structured gap report from checkpoints. This report becomes the task list, preventing iterative manual discovery of issues that checkpoints would catch automatically.
The harness enforces this through AH-30..AH-35: if quality infrastructure is missing, the harness flags it before any enhancement work begins.
---
10. superpowers (writing-plans, executing-plans)
What it provides: Plan lifecycle management. Writing-plans creates structured execution plans; executing-plans tracks and executes them step by step.
When harness delegates to it: When the harness detects a complex change that should be planned before execution. The harness skill recommends plan creation for multi-file structural changes.
What harness expects back:
docs/superpowers/plans/directory exists if the project uses plans.- Active plans are tracked with checkbox syntax.
What harness verifies:
- If
docs/superpowers/plans/is referenced in AGENTS.md, the directory exists (checkpoint AH-10 -- general reference check). - Plan template is available for bootstrap mode (
templates/exec-plan.md.tmpl).
---
11. skill-repo-skill
What it provides: Defines the structure of a skill repository: .claude-plugin/plugin.json, skills/<name>/SKILL.md, split licensing (MIT + CC-BY-SA-4.0), release workflows, composer integration. Also defines the materialization-contract.md followed by tools that submit PRs to skill repos (notably retro-skill).
When harness applies alongside it: Skill repos benefit from both layers: skill-repo-skill verifies skill-specific structure (.claude-plugin/plugin.json, skills/<name>/SKILL.md, composer.json conventions) via its own validate-skill.sh; harness layers generic agent-readiness on top (AGENTS.md as index, docs/ structure, .github/workflows/harness-verify.yml). The two verifiers don't overlap — they target different artefacts.
What harness expects back:
- An
AGENTS.mdindex for the skill repo. - The standard harness workflows (
harness-verify.yml).
What harness verifies in skill repos:
- The same generic harness checkpoints apply as for any other repo (
AH-01AGENTS.mdexists,AH-02line count,AH-12harness-verify.ymlexists). Skill-specific structural validation is left toskill-repo-skill's ownvalidate-skill.sh.
---
12. retro-skill
What it provides: LLM-driven session retrospection. Detects friction in agent sessions (~32 signals across 3 layers: mechanical pre-pass, LLM inference, cross-session) and materializes approved learnings into one of six destinations: user-memory, project-rule, skill-update, new-skill, checkpoint, harness-artefact.
When harness delegates to it: At end of any non-trivial session, or on-demand for specific issues. The harness does not invoke retro-skill at runtime; it verifies that the artefacts retro-skill needs to materialize learnings exist in the repo.
What harness expects back from a retro-active repo:
- PR/MR template contains a retro question (so contributors can flag reusable patterns to route).
- Optional
SessionEndhook (.claude/hooks/session-end.json) is present if the team wants auto-trigger of/retro. docs/feedback/directory exists when project-rule learnings have been approved.- Approved learnings in
docs/feedback/follow thefeedback-memory-schemadefined byagent-rules-skill.
What harness verifies:
AH-22(warning, Level 3): PR/MR template includes a retro question.AH-23(info, Level 3): SessionEnd hook present (optional convenience).- Indirect:
AH-10ensures anydocs/feedback/<slug>.mdreferenced from AGENTS.md actually exists.
Why this delegation matters: The harness used to risk becoming the meta-owner for "anything agent-readiness-shaped", including learning. retro-skill carves out the learning ownership cleanly, leaving the harness as a thin verifier of integration points. See references/harness-engineering-overview.md for the principle.
Integration Flow Diagram
agent-harness (verify / bootstrap / audit)
|
+-----------+-----------+------------------+
| | | |
[Verify] [Bootstrap] [Audit] [Delegate]
| | | |
v v v v
verify-harness.sh templates/ checkpoints.yaml Other skills
| | | |
| | | +---------+---------+
| | | | | |
| | | agent-rules github- git-workflow
| | | (AGENTS.md) project (hooks)
| | | (branch
| | | protection)
| | |
+-----+-----+----------+
|
v
Artefact checks
(files exist, refs resolve,
commands match targets)The harness skill sits at the centre, delegating creation to specialised skills and verifying the output. The verification layer works independently of which skill created the artefacts.
#!/usr/bin/env bash
# verify-harness.sh — Portable harness consistency checker
# Checks AGENTS.md and related files for agent harness maturity.
# Dependencies: coreutils + git (jq optional, graceful fallback)
set -euo pipefail
# ---------------------------------------------------------------------------
# Globals
# ---------------------------------------------------------------------------
ERRORS=0
WARNINGS=0
FORMAT=""
MAX_LEVEL=3
SINGLE_CHECK=""
STATUS_ONLY=false
PLATFORM="${PLATFORM:-}"
# Collected output lines (for final rendering)
declare -a OUTPUT_LINES=()
declare -a GITHUB_LINES=()
declare -a GITLAB_LINES=()
# Per-level pass/total counters
declare -A LEVEL_PASS=( [1]=0 [2]=0 [3]=0 )
declare -A LEVEL_TOTAL=( [1]=0 [2]=0 [3]=0 )
# Track the first failing level-1 suggestion for --status
NEXT_STEP=""
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
usage() {
cat <<'USAGE'
Usage: verify-harness.sh [OPTIONS]
Verify agent harness consistency in the current repository.
Must be run from the repo root.
Options:
--format=text Plain text output (default for terminals)
--format=github GitHub Actions annotations (auto-detected in CI)
--format=gitlab GitLab CI section annotations (auto-detected in CI)
--platform=P Target platform: github, gitlab or forgejo (auto-detected
from CI environment or git remote URL if not specified)
--level=N Only check up to level N (1, 2, or 3; default: all)
--check=NAME Run single check category: refs, commands, drift, structure
--status Show current maturity level summary only
--help Show this help message
Exit codes:
0 All checks pass
1 Errors found (Level 1/2 failures)
2 Only warnings (Level 3 suggestions)
USAGE
exit 0
}
# Detect output format: github if running in CI, otherwise text
detect_format() {
if [[ -n "$FORMAT" ]]; then
return
fi
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
FORMAT="github"
elif [[ "${GITLAB_CI:-}" == "true" ]]; then
FORMAT="gitlab"
else
FORMAT="text"
fi
}
# Detect hosting platform from CI env, git remote, or flag
detect_platform() {
if [[ -n "$PLATFORM" ]]; then
if [[ "$PLATFORM" != "github" && "$PLATFORM" != "gitlab" && "$PLATFORM" != "forgejo" ]]; then
echo "Error: Unsupported PLATFORM '${PLATFORM}'. Expected 'github', 'gitlab' or 'forgejo'." >&2
exit 1
fi
return
fi
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
# Forgejo/Gitea Actions also export GITHUB_ACTIONS=true; tell them apart
# by the server URL — github.com (or a *.github.* Enterprise host) is real
# GitHub, anything else is a self-hosted Forgejo/Gitea instance.
if [[ -n "${GITHUB_SERVER_URL:-}" && "${GITHUB_SERVER_URL}" != *"github."* ]]; then
PLATFORM="forgejo"
else
PLATFORM="github"
fi
return
fi
if [[ "${GITLAB_CI:-}" == "true" ]]; then
PLATFORM="gitlab"
return
fi
local remote_url=""
remote_url=$(git remote get-url origin 2>/dev/null || true)
if [[ "$remote_url" == *"forgejo"* || "$remote_url" == *"gitea"* ]]; then
PLATFORM="forgejo"
elif [[ "$remote_url" == *"github"* ]]; then
PLATFORM="github"
elif [[ "$remote_url" == *"gitlab"* ]]; then
PLATFORM="gitlab"
elif [[ -f ".gitlab-ci.yml" ]]; then
# Infer GitLab from CI config presence (e.g. self-hosted GitLab)
PLATFORM="gitlab"
elif [[ -d ".forgejo" || -d ".gitea" ]]; then
# Infer Forgejo/Gitea from config presence (self-hosted)
PLATFORM="forgejo"
elif [[ -d ".github" ]]; then
PLATFORM="github"
else
PLATFORM="github"
fi
}
# Record a passing check
pass() {
local level="$1"
local msg="$2"
(( LEVEL_PASS[$level]++ )) || true
(( LEVEL_TOTAL[$level]++ )) || true
OUTPUT_LINES+=(" PASS|${level}|${msg}")
}
# Record a failing check (error)
fail() {
local level="$1"
local msg="$2"
local file="${3-AGENTS.md}"
(( ERRORS++ )) || true
(( LEVEL_TOTAL[$level]++ )) || true
OUTPUT_LINES+=(" FAIL|${level}|${msg}")
GITHUB_LINES+=("::error file=${file}::${msg} -- required for Level ${level} harness maturity")
GITLAB_LINES+=("ERROR: [Level ${level}] ${msg}${file:+ (${file})}")
# Capture first actionable suggestion for --status
if [[ -z "$NEXT_STEP" ]]; then
NEXT_STEP="$msg"
fi
}
# Record a warning
warn() {
local level="$1"
local msg="$2"
local file="${3-AGENTS.md}"
(( WARNINGS++ )) || true
(( LEVEL_TOTAL[$level]++ )) || true
OUTPUT_LINES+=(" WARN|${level}|${msg}")
GITHUB_LINES+=("::warning file=${file}::${msg}")
GITLAB_LINES+=("WARNING: [Level ${level}] ${msg}${file:+ (${file})}")
if [[ -z "$NEXT_STEP" ]]; then
NEXT_STEP="$msg"
fi
}
# ---------------------------------------------------------------------------
# Level 1 checks — Basic
# ---------------------------------------------------------------------------
check_agents_md_exists() {
if [[ -f "AGENTS.md" ]]; then
pass 1 "AGENTS.md exists"
else
fail 1 "AGENTS.md missing at repo root"
fi
}
check_agents_md_length() {
if [[ ! -f "AGENTS.md" ]]; then
fail 1 "AGENTS.md length check skipped (file missing)"
return
fi
local lines
lines=$(wc -l < "AGENTS.md")
if (( lines < 150 )); then
pass 1 "AGENTS.md is index-format (${lines} lines)"
else
fail 1 "AGENTS.md is ${lines} lines (should be under 150)"
fi
}
check_agents_md_commands() {
if [[ ! -f "AGENTS.md" ]]; then
fail 1 "Commands section check skipped (AGENTS.md missing)"
return
fi
if grep -qi '^## *\(available \)\?commands' "AGENTS.md"; then
pass 1 "Commands section found"
else
fail 1 "AGENTS.md missing ## Commands section"
fi
}
check_docs_exists() {
if [[ -d "docs" ]]; then
pass 1 "docs/ directory exists"
else
fail 1 "docs/ directory missing" ""
fi
}
run_level1() {
check_agents_md_exists
check_agents_md_length
check_agents_md_commands
check_docs_exists
}
# ---------------------------------------------------------------------------
# Level 2 checks — Verified
# ---------------------------------------------------------------------------
# Check that all local file references in AGENTS.md resolve
check_refs() {
if [[ ! -f "AGENTS.md" ]]; then
fail 2 "Reference check skipped (AGENTS.md missing)"
return
fi
local has_broken=false
# Extract markdown links: [text](path) — skip http(s):// and #anchors
while IFS= read -r ref; do
# Strip anchor (#...) and query string (?...)
local clean
clean="${ref%%#*}"
clean="${clean%%\?*}"
# Skip empty after stripping
[[ -z "$clean" ]] && continue
# Skip URLs
[[ "$clean" =~ ^https?:// ]] && continue
# Check if file/dir exists
if [[ ! -e "$clean" ]]; then
warn 2 "Broken reference in AGENTS.md: ${ref} -> ${clean} not found"
has_broken=true
fi
done < <(grep -oP '\]\(\K[^)]+' "AGENTS.md" 2>/dev/null || true)
if [[ "$has_broken" == false ]]; then
pass 2 "All references resolve"
fi
}
# Check that documented commands have matching targets/scripts
check_commands() {
if [[ ! -f "AGENTS.md" ]]; then
fail 2 "Command check skipped (AGENTS.md missing)"
return
fi
local found_any=false
# -- Makefile targets --
if [[ -f "Makefile" ]]; then
found_any=true
local has_make_issue=false
while IFS= read -r target; do
# Check if Makefile defines this target (pattern: "target:" at start of line)
if ! grep -qE "^${target}[[:space:]]*:" "Makefile"; then
warn 2 "make ${target}: no matching Makefile target (warning)"
has_make_issue=true
fi
done < <(grep -oP '`make\s+\K[a-zA-Z0-9_-]+' "AGENTS.md" 2>/dev/null || true)
if [[ "$has_make_issue" == false ]]; then
local make_count
make_count=$(grep -oP '`make\s+\K[a-zA-Z0-9_-]+' "AGENTS.md" 2>/dev/null | wc -l || true)
if [[ "$make_count" -gt 0 ]]; then
pass 2 "All make targets verified (${make_count} targets)"
fi
fi
fi
# -- composer.json scripts --
if [[ -f "composer.json" ]]; then
found_any=true
local has_composer_issue=false
# Built-in composer commands that are NOT user-defined scripts
local composer_builtins="install|update|require|remove|dump-autoload|dumpautoload|clear-cache|clearcache|config|create-project|exec|global|init|outdated|prohibits|why|why-not|search|self-update|selfupdate|show|status|validate|archive|browse|check-platform-reqs|diagnose|fund|licenses|run-script|suggests|upgrade"
while IFS= read -r script; do
# Skip built-in composer commands
if echo "$script" | grep -qE "^(${composer_builtins})$"; then
continue
fi
# Look for the script name in composer.json's scripts section
# Using grep since jq is optional
if ! grep -qE "\"${script}\"" "composer.json"; then
warn 2 "composer ${script}: no matching composer.json script (warning)"
has_composer_issue=true
fi
done < <(grep -oP '`composer\s+\K[a-zA-Z0-9:_-]+' "AGENTS.md" 2>/dev/null || true)
if [[ "$has_composer_issue" == false ]]; then
local composer_count
composer_count=$(grep -oP '`composer\s+\K[a-zA-Z0-9:_-]+' "AGENTS.md" 2>/dev/null | wc -l || true)
if [[ "$composer_count" -gt 0 ]]; then
pass 2 "All composer scripts verified (${composer_count} scripts)"
fi
fi
fi
# -- package.json scripts --
if [[ -f "package.json" ]]; then
found_any=true
local has_npm_issue=false
while IFS= read -r script; do
if ! grep -qE "\"${script}\"" "package.json"; then
warn 2 "npm run ${script}: no matching package.json script (warning)"
has_npm_issue=true
fi
done < <(grep -oP '`npm run\s+\K[a-zA-Z0-9:_-]+' "AGENTS.md" 2>/dev/null || true)
if [[ "$has_npm_issue" == false ]]; then
local npm_count
npm_count=$(grep -oP '`npm run\s+\K[a-zA-Z0-9:_-]+' "AGENTS.md" 2>/dev/null | wc -l || true)
if [[ "$npm_count" -gt 0 ]]; then
pass 2 "All npm scripts verified (${npm_count} scripts)"
fi
fi
fi
if [[ "$found_any" == false ]]; then
pass 2 "No build system files found to check commands against"
fi
}
check_architecture_doc() {
if [[ -f "docs/ARCHITECTURE.md" ]]; then
pass 2 "docs/ARCHITECTURE.md exists"
else
fail 2 "docs/ARCHITECTURE.md missing" ""
fi
}
check_ci_workflow() {
if [[ "$PLATFORM" == "gitlab" ]]; then
if [[ -f ".gitlab-ci.yml" ]]; then
# Search root file and all include:local files for harness job
local found_harness=false
if grep -qE "harness-verify|verify-harness" ".gitlab-ci.yml"; then
found_harness=true
else
# Check files referenced via include:local (supports globs).
# Portable parser using sed/awk — handles common GitLab CI forms:
# include: { local: 'path' }
# include:
# - local: 'path'
# include:
# - local:
# - path1
# - path2
# Skips PCRE (-P) and lookaround for BSD/macOS grep portability.
while IFS= read -r inc_pattern; do
[[ -z "$inc_pattern" ]] && continue
# shellcheck disable=SC2086
for inc_file in $inc_pattern; do
if [[ -f "$inc_file" ]] && grep -qE "harness-verify|verify-harness" "$inc_file"; then
found_harness=true
break 2
fi
done
done < <(awk '
/^[[:space:]]*-?[[:space:]]*local:[[:space:]]*\[/ {
# inline list form: local: [a.yml, b.yml]
s=$0; sub(/.*local:[[:space:]]*\[/,"",s); sub(/\].*/,"",s);
n=split(s, a, /[[:space:]]*,[[:space:]]*/);
for (i=1;i<=n;i++) print a[i]; next
}
/^[[:space:]]*-?[[:space:]]*local:[[:space:]]*[^[:space:]\[]/ {
# scalar form: local: path or - local: path
s=$0; sub(/.*local:[[:space:]]*/,"",s); print s; next
}
' ".gitlab-ci.yml" 2>/dev/null | tr -d "'\"" || true)
fi
if [[ "$found_harness" == true ]]; then
pass 2 "CI harness job found in GitLab CI config"
else
warn 2 "CI config exists (.gitlab-ci.yml) but no harness-verify job found"
fi
else
fail 2 "CI harness workflow missing -- create .gitlab-ci.yml with a harness-verify job" ""
fi
elif [[ "$PLATFORM" == "forgejo" ]]; then
if [[ -f ".forgejo/workflows/harness-verify.yml" || -f ".gitea/workflows/harness-verify.yml" ]]; then
pass 2 "CI harness workflow exists"
else
fail 2 "CI harness workflow missing -- create .forgejo/workflows/harness-verify.yml" ""
fi
else
if [[ -f ".github/workflows/harness-verify.yml" ]]; then
pass 2 "CI harness workflow exists"
else
fail 2 "CI harness workflow missing -- create .github/workflows/harness-verify.yml" ""
fi
fi
}
run_level2() {
check_refs
check_commands
check_architecture_doc
check_ci_workflow
}
# ---------------------------------------------------------------------------
# Level 3 checks — Enforced
# ---------------------------------------------------------------------------
check_hooks_autosetup() {
local found=false
local via=""
# Check .envrc for hooksPath
if [[ -f ".envrc" ]] && grep -q "hooksPath" ".envrc"; then
found=true
via=".envrc"
fi
# Check for Husky
if [[ -d ".husky" ]]; then
found=true
via=".husky"
fi
# Check composer.json for post-install-cmd with hooks
if [[ -f "composer.json" ]] && grep -q "post-install-cmd" "composer.json"; then
if grep -q "hook" "composer.json"; then
found=true
via="composer.json post-install-cmd"
fi
fi
if [[ "$found" == true ]]; then
pass 3 "Git hooks auto-setup via ${via}"
else
warn 3 "No git hooks auto-setup detected (.envrc hooksPath, .husky/, or composer.json post-install-cmd)"
fi
}
check_pr_template() {
if [[ "$PLATFORM" == "forgejo" ]]; then
# Forgejo/Gitea honour PR templates under .forgejo/, .gitea/ or .github/
local f
for f in .forgejo/pull_request_template.md .gitea/pull_request_template.md \
.forgejo/PULL_REQUEST_TEMPLATE.md .gitea/PULL_REQUEST_TEMPLATE.md \
.github/pull_request_template.md; do
if [[ -f "$f" ]]; then
pass 3 "PR template exists ($f)"
return
fi
done
warn 3 "PR template missing (create .forgejo/pull_request_template.md)"
return
fi
if [[ "$PLATFORM" == "gitlab" ]]; then
if [[ -d ".gitlab/merge_request_templates" ]]; then
local tmpl_count
tmpl_count=$(find .gitlab/merge_request_templates -maxdepth 1 -type f -name '*.md' 2>/dev/null | wc -l)
if (( tmpl_count > 0 )); then
pass 3 "MR template exists (.gitlab/merge_request_templates/, ${tmpl_count} template(s))"
return
fi
fi
warn 3 "MR template missing (create .gitlab/merge_request_templates/Default.md)"
else
if [[ -f ".github/pull_request_template.md" ]]; then
pass 3 "PR template exists (repo-level)"
return
fi
if [[ -d ".github/PULL_REQUEST_TEMPLATE" ]]; then
pass 3 "PR template exists (directory form)"
return
fi
local org=""
org=$(git remote get-url origin 2>/dev/null | sed -n 's|.*github\.com[:/]\([^/]*\)/.*|\1|p')
if [[ -n "$org" ]]; then
local api_result=""
api_result=$(gh api "repos/${org}/.github/contents/pull_request_template.md" --jq '.name' 2>/dev/null || true)
if [[ "$api_result" == "pull_request_template.md" ]]; then
pass 3 "PR template exists (org-level via ${org}/.github)"
return
fi
fi
warn 3 "PR template missing (.github/pull_request_template.md or org-level)"
fi
}
check_drift() {
# Skip if git is not available
if ! command -v git &>/dev/null; then
pass 3 "Drift check skipped (git not available)"
return
fi
# Skip if not in a git repo
if ! git rev-parse --git-dir &>/dev/null 2>&1; then
pass 3 "Drift check skipped (not a git repository)"
return
fi
# Skip if no parent commit (initial commit)
if ! git rev-parse HEAD~1 &>/dev/null 2>&1; then
pass 3 "Drift check skipped (no parent commit)"
return
fi
# Check if build/CI files changed in last commit
local build_files_changed=false
local agents_changed=false
while IFS= read -r changed_file; do
case "$changed_file" in
Makefile|composer.json|package.json|.github/workflows/*|.gitlab-ci.yml|.forgejo/workflows/*|.gitea/workflows/*)
build_files_changed=true
;;
AGENTS.md)
agents_changed=true
;;
esac
done < <(git diff --name-only HEAD~1 HEAD 2>/dev/null || true)
if [[ "$build_files_changed" == true && "$agents_changed" == false ]]; then
warn 3 "Potential drift: build/CI files changed in last commit but AGENTS.md was not updated"
else
pass 3 "No drift detected"
fi
}
run_level3() {
check_hooks_autosetup
check_pr_template
check_drift
}
# ---------------------------------------------------------------------------
# Output rendering
# ---------------------------------------------------------------------------
render_text() {
echo "Agent Harness Verification"
echo "=========================="
echo ""
local current_level=0
local level_names=( [1]="Basic" [2]="Verified" [3]="Enforced" )
for line in "${OUTPUT_LINES[@]}"; do
local kind level msg
kind="${line%%|*}"
local rest="${line#*|}"
level="${rest%%|*}"
msg="${rest#*|}"
kind="${kind#"${kind%%[![:space:]]*}"}" # trim leading whitespace
# Print level header when level changes
if (( level != current_level )); then
if (( current_level != 0 )); then
echo ""
fi
echo "Level ${level} -- ${level_names[$level]}"
current_level=$level
fi
case "$kind" in
PASS) echo " ✓ ${msg}" ;;
FAIL) echo " ✗ ${msg}" ;;
WARN) echo " ! ${msg}" ;;
esac
done
echo ""
# Summary line
local maturity_level=0
for lvl in 1 2 3; do
if (( ${LEVEL_TOTAL[$lvl]} > 0 && ${LEVEL_PASS[$lvl]} == ${LEVEL_TOTAL[$lvl]} )); then
maturity_level=$lvl
else
break
fi
done
local status="COMPLETE"
if (( maturity_level == 0 )); then
if (( LEVEL_TOTAL[1] > 0 && LEVEL_PASS[1] > 0 )); then
status="PARTIAL"
else
status="NONE"
fi
maturity_level=1
elif (( maturity_level < 3 )); then
# Check if next level is partially done
local next_lvl=$(( maturity_level + 1 ))
if (( ${LEVEL_TOTAL[$next_lvl]} > 0 && ${LEVEL_PASS[$next_lvl]} < ${LEVEL_TOTAL[$next_lvl]} )); then
status="PARTIAL"
fi
fi
echo "Summary: Level ${maturity_level} ${status} | ${ERRORS} error(s), ${WARNINGS} warning(s)"
}
render_github() {
if (( ${#GITHUB_LINES[@]} > 0 )); then
for line in "${GITHUB_LINES[@]}"; do
echo "$line"
done
fi
}
render_gitlab() {
local ts
ts=$(date +%s)
echo -e "\e[0Ksection_start:${ts}:harness_verify[collapsed=false]\r\e[0KAgent Harness Verification"
if (( ${#GITLAB_LINES[@]} > 0 )); then
for line in "${GITLAB_LINES[@]}"; do
echo "$line"
done
fi
echo ""
echo "Summary: ${ERRORS} error(s), ${WARNINGS} warning(s)"
echo -e "\e[0Ksection_end:${ts}:harness_verify\r\e[0K"
}
render_status() {
# Determine highest fully-passing level
local maturity_level=0
local level_names=( [1]="Basic" [2]="Verified" [3]="Enforced" )
for lvl in 1 2 3; do
if (( ${LEVEL_TOTAL[$lvl]} > 0 && ${LEVEL_PASS[$lvl]} == ${LEVEL_TOTAL[$lvl]} )); then
maturity_level=$lvl
else
break
fi
done
local status
if (( maturity_level == 0 )); then
if (( LEVEL_TOTAL[1] > 0 && LEVEL_PASS[1] > 0 )); then
status="PARTIAL"
else
status="NONE"
fi
# Display as Level 1 when no level is fully complete
local display_level=1
echo "Harness Maturity: Level ${display_level} (${level_names[$display_level]}) -- ${status}"
else
echo "Harness Maturity: Level ${maturity_level} (${level_names[$maturity_level]}) -- COMPLETE"
fi
for lvl in 1 2 3; do
if (( ${LEVEL_TOTAL[$lvl]} > 0 )); then
echo " Level ${lvl}: ${LEVEL_PASS[$lvl]}/${LEVEL_TOTAL[$lvl]} checks pass"
fi
done
if [[ -n "$NEXT_STEP" ]]; then
echo "Next step: ${NEXT_STEP}"
fi
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--format=*)
FORMAT="${1#--format=}"
;;
--platform=*)
PLATFORM="${1#--platform=}"
if [[ ! "$PLATFORM" =~ ^(github|gitlab|forgejo)$ ]]; then
echo "Error: --platform must be 'github', 'gitlab' or 'forgejo'" >&2
exit 1
fi
;;
--level=*)
MAX_LEVEL="${1#--level=}"
if [[ ! "$MAX_LEVEL" =~ ^[123]$ ]]; then
echo "Error: --level must be 1, 2, or 3" >&2
exit 1
fi
;;
--check=*)
SINGLE_CHECK="${1#--check=}"
;;
--status)
STATUS_ONLY=true
;;
--help|-h)
usage
;;
*)
echo "Unknown option: $1" >&2
echo "Run with --help for usage info" >&2
exit 1
;;
esac
shift
done
detect_format
detect_platform
# Run single check category if requested
if [[ -n "$SINGLE_CHECK" ]]; then
case "$SINGLE_CHECK" in
refs) check_refs ;;
commands) check_commands ;;
drift) check_drift ;;
structure)
check_agents_md_exists
check_docs_exists
check_architecture_doc
check_ci_workflow
check_pr_template
;;
*)
echo "Unknown check: ${SINGLE_CHECK}" >&2
echo "Valid checks: refs, commands, drift, structure" >&2
exit 1
;;
esac
else
# Run all checks up to MAX_LEVEL
if (( MAX_LEVEL >= 1 )); then
run_level1
fi
if (( MAX_LEVEL >= 2 )); then
run_level2
fi
if (( MAX_LEVEL >= 3 )); then
run_level3
fi
fi
# Render output
if [[ "$STATUS_ONLY" == true ]]; then
render_status
elif [[ "$FORMAT" == "github" ]]; then
render_github
elif [[ "$FORMAT" == "gitlab" ]]; then
render_gitlab
else
render_text
fi
# Exit code
if (( ERRORS > 0 )); then
exit 1
elif (( WARNINGS > 0 )); then
exit 2
else
exit 0
fi
}
main "$@"
# {{PROJECT_NAME}}
<!-- This file is an INDEX, not an encyclopedia. Keep it under 150 lines.
Detail belongs in docs/. Agents read this every session — every line costs context. -->
## Repo Structure
- `src/` — Application source code
- `tests/` — Test suites
- `docs/` — Documentation (see [ARCHITECTURE.md](docs/ARCHITECTURE.md))
- `docs/exec-plans/` — Execution plans ([active](docs/exec-plans/active/), [completed](docs/exec-plans/completed/))
- `.github/workflows/` — CI/CD pipelines
## Commands
```bash
# Build
{{BUILD_COMMAND}}
# Test
{{TEST_COMMAND}}
# Lint
{{LINT_COMMAND}}
# Verify harness consistency
make verify-harness
```
## Rules
- **Commits:** Use [Conventional Commits](https://www.conventionalcommits.org/) format
- **Architecture:** See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for dependency rules
- **Plans:** Multi-file changes require an exec-plan in `docs/exec-plans/active/`
- **AGENTS.md:** This file is an index — details go in `docs/`
- **Updates:** Update this file when adding new commands or changing repo structure
## References
- [Architecture](docs/ARCHITECTURE.md)
- [Active Execution Plans](docs/exec-plans/active/)
- [Completed Plans](docs/exec-plans/completed/)
# Architecture
<!-- Keep this document current. It's referenced from AGENTS.md and read by agents
when they need to understand the system before making changes. -->
## System Overview
{{ONE_PARAGRAPH_DESCRIPTION}}
## Component Map
| Component | Responsibility | Key Files |
|---|---|---|
| {{COMPONENT_1}} | {{RESPONSIBILITY}} | `{{PATH}}` |
| {{COMPONENT_2}} | {{RESPONSIBILITY}} | `{{PATH}}` |
## Dependency Rules
<!-- Define what can import/depend on what. This prevents architectural drift. -->
{{DEPENDENCY_RULES}}
<!-- Example:
- `src/domain/` MUST NOT depend on `src/infrastructure/`
- `src/api/` may depend on `src/domain/` and `src/infrastructure/`
- `tests/` may depend on anything
-->
## Data Flow
{{DATA_FLOW_DESCRIPTION}}
## Key Decisions
<!-- Link to ADRs or summarise key architectural decisions -->
| Decision | Rationale | Date |
|---|---|---|
| {{DECISION}} | {{WHY}} | {{DATE}} |
# Agent Harness — automatic environment setup
# Requires direnv (https://direnv.net/)
# This file activates git hooks and adds project tools to PATH.
# Activate project git hooks
if [ -d .githooks ]; then
git config core.hooksPath .githooks
fi
# Add project-local binaries to PATH
PATH_add bin
PATH_add vendor/bin
PATH_add node_modules/.bin
# Optional: set project-specific environment
# export PROJECT_ENV=development
# Exec Plan: {{PLAN_TITLE}}
**Status:** Active | Completed
**Created:** {{DATE}}
**Author:** {{AUTHOR}}
## Goal
{{ONE_SENTENCE_GOAL}}
## Scope
**In scope:**
- {{ITEM}}
**Out of scope / Non-goals:**
- {{ITEM}}
## Affected Systems
- {{SYSTEM}} — {{HOW_AFFECTED}}
## Risks
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| {{RISK}} | Low/Medium/High | Low/Medium/High | {{MITIGATION}} |
## Steps
- [ ] {{STEP_1}}
- [ ] {{STEP_2}}
- [ ] {{STEP_3}}
## Verification
- [ ] {{VERIFICATION_STEP_1}}
- [ ] {{VERIFICATION_STEP_2}}
## Done Criteria
- {{CRITERION_1}}
- {{CRITERION_2}}
## Decisions Log
| Date | Decision | Rationale |
|---|---|---|
| {{DATE}} | {{DECISION}} | {{WHY}} |
# .forgejo/workflows/harness-verify.yml
name: Harness Verification
on:
pull_request:
branches: [ {{DEFAULT_BRANCH}} ]
jobs:
verify-harness:
name: Verify Harness Consistency
runs-on: ubuntu-latest
env:
# Forgejo/Gitea Actions export GITHUB_ACTIONS=true for compatibility;
# pin the platform so the script checks .forgejo/ artefacts, not .github/.
PLATFORM: forgejo
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2 # parent commit needed for drift detection
- name: Verify agent-harness integrity
# Exit 1 = errors (fail the build); exit 2 = advisory warnings
# only (e.g. drift heuristic) — informative, must not block CI.
run: |
bash scripts/verify-harness.sh || { code=$?; [ "$code" -eq 2 ] && exit 0; exit "$code"; }
# Agent Harness Verification job for GitLab CI
# Add this to your .gitlab-ci.yml or include it via !reference
harness-verify:
stage: test
image: alpine:latest
before_script:
- apk add --no-cache bash git coreutils grep
script:
- bash scripts/verify-harness.sh --level=2 --format=gitlab
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
allow_failure: false
name: Harness Verification
on:
pull_request:
branches: [{{DEFAULT_BRANCH}}]
permissions:
contents: read
jobs:
verify-harness:
name: Verify Harness Consistency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2 # Need parent commit for drift detection
- name: Verify AGENTS.md exists
run: |
if [ ! -f AGENTS.md ]; then
echo "::error::AGENTS.md is missing — create one using the agent-harness skill or manually"
exit 1
fi
- name: Verify AGENTS.md is index format
run: |
LINES=$(wc -l < AGENTS.md)
if [ "$LINES" -gt 150 ]; then
echo "::error::AGENTS.md is too long ($LINES lines). It should be a compact index (<150 lines). Move detail to docs/"
exit 1
fi
- name: Verify AGENTS.md references
run: |
ERRORS=0
while IFS= read -r ref; do
[[ "$ref" == http* ]] && continue
[[ "$ref" == \#* ]] && continue
ref="${ref%%#*}" # strip anchor
ref="${ref%%\?*}" # strip query
if [ ! -e "$ref" ]; then
echo "::error file=AGENTS.md::Dead reference: $ref"
ERRORS=$((ERRORS + 1))
fi
done < <(grep -oP '\[.*?\]\(\K[^)]+' AGENTS.md 2>/dev/null || true)
exit $ERRORS
- name: Verify documented commands
run: |
if [ -f Makefile ]; then
grep -oP '`make (\w[\w-]*)`' AGENTS.md 2>/dev/null | tr -d '`' | while read -r cmd; do
TARGET="${cmd#make }"
if ! grep -q "^${TARGET}:" Makefile; then
echo "::warning file=AGENTS.md::Documented command '$cmd' has no matching Makefile target"
fi
done
fi
if [ -f composer.json ]; then
grep -oP '`composer ([\w:.-]+)`' AGENTS.md 2>/dev/null | tr -d '`' | while read -r cmd; do
SCRIPT="${cmd#composer }"
if ! python3 -c "import json,sys; d=json.load(open('composer.json')); sys.exit(0 if '$SCRIPT' in d.get('scripts',{}) else 1)" 2>/dev/null; then
echo "::warning file=AGENTS.md::Documented command '$cmd' not found in composer.json scripts"
fi
done
fi
if [ -f package.json ]; then
grep -oP '`npm run ([\w:.-]+)`' AGENTS.md 2>/dev/null | tr -d '`' | while read -r cmd; do
SCRIPT="${cmd#npm run }"
if ! python3 -c "import json,sys; d=json.load(open('package.json')); sys.exit(0 if '$SCRIPT' in d.get('scripts',{}) else 1)" 2>/dev/null; then
echo "::warning file=AGENTS.md::Documented command '$cmd' not found in package.json scripts"
fi
done
fi
- name: Check for documentation drift
run: |
if git diff --name-only HEAD~1 2>/dev/null | grep -qE '(Makefile|composer\.json|package\.json|\.github/workflows/)'; then
if ! git diff --name-only HEAD~1 | grep -q 'AGENTS.md'; then
echo "::warning::Build/CI files changed but AGENTS.md was not updated — check for drift"
fi
fi
- name: Verify docs structure
run: |
if [ ! -f docs/ARCHITECTURE.md ]; then
echo "::warning::docs/ARCHITECTURE.md is missing — recommended for Level 2+ harness maturity"
fi
# --- Agent Harness Targets ---
# These targets support harness verification and bootstrapping.
# See AGENTS.md for available commands.
.PHONY: verify-harness harness-status
## Verify harness consistency (docs, references, commands)
verify-harness:
@bash scripts/verify-harness.sh --format=text
## Show current harness maturity level
harness-status:
@bash scripts/verify-harness.sh --format=text --status
## Summary
<!-- Brief description of changes -->
## Checklist
- [ ] AGENTS.md updated (if commands or repo structure changed)
- [ ] docs/ updated (if architecture or design changed)
- [ ] New subsystems/directories documented
- [ ] Exec plan created in `docs/exec-plans/active/` (if multi-file change)
## Retro
<!-- Did this change reveal a reusable pattern, missing rule, or skill instruction gap? -->
<!-- If yes, route via `/retro` to the correct destination (user-memory, project-rule, skill PR, checkpoint, harness-artefact). -->
- [ ] Reusable pattern detected? (N/A if purely local fix)
## Test Plan
<!-- How to verify these changes work -->
## Summary
<!-- Brief description of changes -->
## Checklist
- [ ] AGENTS.md updated (if commands or repo structure changed)
- [ ] docs/ updated (if architecture or design changed)
- [ ] New subsystems/directories documented
- [ ] Exec plan created in `docs/exec-plans/active/` (if multi-file change)
## Retro
<!-- Did this change reveal a reusable pattern, missing rule, or skill instruction gap? -->
<!-- If yes, route via `/retro` to the correct destination (user-memory, project-rule, skill PR, checkpoint, harness-artefact). -->
- [ ] Reusable pattern detected? (N/A if purely local fix)
## Test Plan
<!-- How to verify these changes work -->