# Harness Core

This document describes how the repo-native harness should behave during
spec-driven work. It does not restate HTML conversion, NGINX lifecycle, or FFI
semantics. Those stay in canonical docs and in `AGENTS.md`.

## Core Loop

1. Bind the current task to a concrete spec when possible.
2. Emit a short risk card before editing.
3. Route through the canonical manifest.
4. Pick one primary risk pack and any supporting packs.
5. Build a phased verification matrix before broad edits.
6. Execute, retry once on drift, then escalate or ask for outside voice if the
   work does not converge.
7. Record bounded reflection and promotion evidence in the user-local state
   carrier, not in repo truth files.

## Spec Resolver Contract

- Start from the current user task.
- If an active spec pointer exists, use it to refine the target.
- If multiple specs are in motion, explain why the current task binds to the
  chosen spec.
- If no spec can be bound confidently, degrade explicitly. Do not guess.

Use the repo helper when you want a concrete resolution pass:

Prefer explicit scoped checks tied to the files you changed, then run
`make harness-check` / `make harness-check-full` for repo-level validation.

```bash
python3 tools/harness/resolve_spec.py --hint "continue rollout observability work"
```

Optional local pointer files may refine local workflows, but they are advisory
and never required for public repository validation.

## Preflight Risk Card

The default card stays short:

- touched area
- likely primary pack
- supporting packs, if any
- minimum cheap blockers
- one-sentence risk note

Expand to a detailed card only when:

- routing confidence is low
- multiple high-risk surfaces overlap
- warnings keep repeating
- the diff starts to widen instead of converge

## Verification Matrix

Run checks in phases:

1. Cheap blockers
   - `make harness-check`
   - other low-cost docs or config checks for the touched area
2. Focused semantic checks
   - one or more pack-specific commands from the routing manifest
3. Coverage (when touching production source files)
   - C module changes: `make coverage-c` (advisory per-file thresholds logged but not blocking)
   - Rust converter changes: `make coverage-rust`
   - Aggregate 80% minimum as release-readiness advisory bar (logged, not CI-blocking)
   - Critical paths (auth, error handling, FFI boundary, conditional requests): 90% target
4. Broader umbrella checks
   - runtime smoke, replay-driven comparisons, or release-level checks

Verification may raise the effective risk level above the initial route. If it
does, the route changes. The initial guess does not get special authority.

The default path should stay cheap. Prefer a fast blocker-first flow and widen
only when the touched surface, warnings, or drift signals justify more cost.
Do not spend replay or history-scan budget on every task by default.

Warnings are not cleanup theater. Do not silence a warning by weakening checks,
shrinking coverage, or deleting behavior unless the warning itself proves the
behavior is invalid. Fix the underlying problem or escalate it explicitly.

## Status Semantics

- `PASS`: the check ran and matched the contract
- `FAIL`: the contract is broken and the task is blocked
- `SKIP_NOT_PRESENT`: optional local-only input was not present
- `WARN_NEEDS_AUTHOR_REVIEW`: the harness found a likely drift that should be
  reviewed by the author, but it is not a public-repo failure by itself

Harness tools must map malformed or unreadable inputs into these explicit
statuses whenever possible. Public manifests should fail clearly. Optional local
inputs and user-local state should degrade explicitly instead of crashing with a
raw traceback.

## Conflict Protocol

- The user task and bound spec set the goal.
- `AGENTS.md` and harness rules set correctness, safety, and engineering
  boundaries.
- If the goal appears to violate the contract, stop and explain the mismatch.
- Require human confirmation before proceeding with a contract-breaking path.

## Loop and Drift Rescue

On the first drift trigger:

1. shrink the diff
2. recompute route and verification
3. retry once

If the same pattern repeats, escalate or ask for outside voice. The harness
must not burn tokens pretending every retry is fresh work.

## History Analysis and Remediation

When a task asks for recent Git analysis plus actual harness or steering
remediation, split the work into two explicit phases:

1. Phase 1 analysis: collect local and remote commits in the requested window,
   deduplicate by SHA, classify by subject and touched surface, and deep-check
   high-risk diffs before proposing rule changes.
2. Phase 2 remediation: implement every P0/P1 finding first, then complete all
   worthwhile P2/P3 improvements or record why they are intentionally deferred.

The closeout artifact must include stable finding IDs, final status, changed
files, and verification evidence.  Use `harness-remediation` as the primary
risk pack for this work.  If a report matching
`docs/project/recent-git-harness-steering-analysis-*.md` exists, `make
harness-check` validates that findings are traceable through remediation.

## Proving Grounds

When validating harness evolution across broad scenarios, keep the first proving
ground on runtime-risk surfaces and add static-quality proving grounds second.
This preserves the priority order from the design reviews: correctness and
safety on the real request path first, quality-discipline expansion second.

## Outside Voice

Use CLI-based outside voice when:

- the route keeps flipping
- warnings recur without narrowing
- loop/drift triggers more than once
- the harness cannot decide between safety-preserving options

Prefer a different model family than the current driver:

- Codex driver -> `qwen` or Claude Code
- Qwen driver -> Codex or Claude Code
- Claude Code driver -> Codex or `qwen`

## State Carrier

Keep short-lived state outside repo truth files. The user-local state carrier is
for:

- retry and drift counts
- bounded reflection summaries
- evidence that a small mistake has repeated enough to justify a rule upgrade

Repo-owned docs keep durable truth. The state carrier keeps execution memory.

## Coverage Standards

- **Minimum**: 80% aggregate line coverage for both the C module and the Rust converter
- **Target**: 90% aggregate line coverage
- **Critical paths** (auth, error handling, FFI boundary, conditional requests): 90% line coverage for new code
- Coverage is collected via `make coverage-c` (C module E2E + gcov/lcov) and `make coverage-rust` (Rust `cargo llvm-cov`)
- Advisory per-file thresholds are logged by the coverage script but are not CI-blocking gates
- The lcov report is always produced regardless of coverage level, ensuring SonarCloud trends remain visible

## Spec Template Convention

When a new spec is created for a feature or bugfix that touches C module or Rust converter production code, the spec's tasks document SHALL include a coverage verification checkpoint as a required (non-optional) task. This is enforced by convention in this harness documentation, not by tooling.

## Naming and Documentation Standards

All code in the repository — C, Rust, Python, shell, and test code — must follow
these naming and documentation principles:

- **Meaningful names**: functions, variables, types, and constants use descriptive
  names that convey intent. Avoid single-letter names outside of short loop
  counters and well-established NGINX conventions (`r`, `cf`, `ctx`, `cl`).
- **Function documentation**: every non-trivial function has a block comment
  describing purpose, parameters, return values, and side effects. Use the
  language-appropriate format: `/* */` for C (NGINX style), `///` for Rust,
  docstrings for Python, `#` blocks for shell.
- **Inline comments**: complex or non-obvious logic has comments explaining
  *why*, not *what*. Invariants, trade-offs, and edge-case reasoning are
  documented at the point of use.
- **Type documentation**: struct and enum definitions include comments describing
  the purpose of the type and the meaning of each field or variant.
- **Framework conventions preserved**: NGINX numbered macros (`ngx_log_debug0`
  through `ngx_log_debug8`) are framework conventions where the trailing digit
  indicates argument count. These must not be renamed.
- **Test divergence documentation**: when a test reimplements production logic
  (because the production function cannot be linked), the test must document
  the divergence risk and the semantic contract it mirrors.

This standard is codified as AGENTS.md Rule 26 and enforced through the
pre-output checklist.

## Document Updates

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.5.0 | 2026-04-21 | docs-standardization | Added update tracking section |
| 0.6.2 | 2026-05-08 | Kang | Unified version narrative to 0.6.2 current release line |
