9.3 KiB
SUPERSEDED — HISTORICAL PROVENANCE ONLY (2026-07-25): The user-approved harness-free Mode B amendment supersedes this design. Retain the body as historical provenance; it is not executable instruction.
Harness Policy Engine Refactoring Design
- Date: 2026-07-20
- Status: Approved by user request
- Scope: repository-local development harness (
.harness,.agents,.claude,.codex, root/module guidance, Gradle module registry integration) - Source: user-provided “개발 하네스 분석·리뷰” plus repository evidence gathered on 2026-07-20
1. Problem Statement
The repository now has 19 nested Gradle leaf modules, but the write-time import gate, agent prompts, runner allowlist, and root guidance still contain parts of the previous flat module topology. Platform variants are copied manually, so commit policy and orchestration already differ between Claude, Codex, and Antigravity. Verdict validation checks a text summary but does not consistently require enum fields, non-negative counts, or arithmetic balance.
The harness must move from duplicated platform prompts to a small policy engine with one project manifest, deterministic renderers, strict validators, and platform adapters.
2. Goals
- Make the actual nested Gradle topology a single machine-readable source of truth.
- Resolve a touched file to its nearest owning leaf module without assuming
src/<module>. - Generate write-time import policy and focused Gradle task validation from that registry.
- Validate machine verdicts with required fields, non-negative integers, arithmetic rules, upstream evidence, revision identity, and TDD red evidence for behavior changes.
- Materialize validated evidence as JSON artifacts that platform hooks can share.
- Render Claude, Codex, and Antigravity agent variants from one canonical source and fail parity checks when generated files drift.
- Use one human-only commit policy on every platform.
- Replace file-count and exhaustive-report rules with risk and review profiles.
- Add mutation and cross-platform static parity tests.
3. Non-Goals
- This change does not run authenticated end-to-end golden tasks inside all three external products. It supplies the deterministic fixtures and validators those runs will consume.
- It does not add application features or alter production Java behavior.
- It does not require PyYAML, jsonschema, Pydantic, or another runtime dependency. Harness data files use JSON syntax, which is valid YAML, and validators use Python stdlib only.
- It does not make natural-language agent self-reports authoritative. Hooks convert accepted reports into evidence artifacts; validators remain authoritative.
4. Architecture
.harness/project/modules.yaml ──┬── Gradle settings/includes
├── Gradle dependency verification
├── owning-module resolver
├── import gate
└── Gradle command validator
.harness/agents/*.md + platforms.yaml
└── render_agents.py
├── .claude/agents/*.md
├── .codex/agents/*.toml
└── .agents/agents/*/agent.json
Claude hook ───────────────┐
Antigravity hook adapter ──┼── verdict validator ── evidence JSON
Codex validation command ──┘
4.1 Project registry
modules.yaml contains, per leaf module:
- stable module id
- repository-relative source path
- Gradle path
- role
- Java package roots (informational and import-policy lookup only)
- allowed project dependencies
- focused test command
- profiles/capabilities
- owning
CLAUDE.mdwhen present - an intentional mutation import used by gate tests
src/settings.gradle reads the registry to declare projects. The
verifyCleanArchitectureDependencies task reads the same registry instead of maintaining a
second dependency map.
4.2 Owning-module resolution
Owner selection uses the longest filesystem-boundary match among registered leaf source
paths. Package prefixes never decide ownership because support owns a broad
dev.caskeleton.adapter.outbound package and sample code mirrors production packages.
Instruction discovery walks upward from the touched file and returns the nearest
CLAUDE.md; if a leaf has none, root CLAUDE.md and AGENTS.md are the explicit fallback.
4.3 Import gate
The import gate first resolves the registered leaf module, then applies:
- dependency-derived sibling module isolation
- role-specific framework rules for domain, application, inbound, outbound, persistence, identifier, shared-contract, bootstrap, and sample roles
- global unsafe-pattern checks
All registered production modules receive a mutation test using their real nested source path. Sample-only exemptions are explicit registry data, not accidental regex misses.
4.4 Verdict and evidence
The canonical verdict schema requires agent, verdict, task_id, revision, and agent
specific evidence. Non-blocked verdicts require every declared field. Counts are non-negative.
Required equations include:
- spec totals balance
- Gradle
run = passed + failed + skipped - ready Gradle results include at least one command and no failed command
- behavior-changing implementation requires at least one observed red test
- quality-ready references validated architecture and spec artifacts
Claude's fenced ca-verdict remains a compatibility input, but its accepted form is converted
to the same JSON evidence model. Missing or malformed payloads for detected CA agents fail
closed. Evidence records include a source-message hash and current revision/diff identity.
4.5 Platform rendering and hook adapters
Canonical agent Markdown lives under .harness/agents/; platform metadata lives in
.harness/project/platforms.yaml. Generated files carry generated_from, source_hash,
generator_version, and do_not_edit metadata.
Antigravity gains a plugin hooks.json and a platform adapter using the documented camelCase
stdin/stdout contract. Claude keeps its native hook entry points but calls the common library.
Codex variants instruct the runner/reviewer to invoke the common validation command because
the repository has no equivalent local lifecycle-hook registration surface.
4.6 Risk and review profiles
Risk is determined by change surface, not file count:
- high: security, migration/schema, public contract, module dependency, architecture rule, transaction/concurrency, CI/deployment
- medium: behavior, multiple modules, external integration
- low: docs/comments, test fixture, local refactor protected by characterization tests
Review profiles:
review-lite: direct diff references; no saved report by defaultreview-standard: verify blocking citations; one report only when risk or findings justify itaudit-deep: verify all quotes and persist detailed findingsregulated: immutable evidence and full traceability
Option analysis uses a dependency DAG and at most 3–5 materially distinct alternatives. Counterarguments are required for judgment-dependent findings, not deterministic failures.
5. Commit Policy
All platforms use human-only. Implementers never stage or commit. Reviewers may inspect a
working-tree diff before commit or an explicit immutable range after the human commits.
6. Verification Strategy
- Stdlib unit tests for registry loading and owner resolution.
- Mutation tests for every registered production module path.
- Strict verdict negative tests: missing fields, negatives, arithmetic imbalance, missing upstream evidence, revision mismatch, and behavior change without red evidence.
- Golden renderer tests and
--checkparity validation. - JSON validation of generated Antigravity hook and agent files.
- Gradle
projects, architecture dependency verification, focused ArchUnit test, and fullcheckafter harness tests pass.
7. Migration and Compatibility
- Existing fenced verdicts remain parseable only when they satisfy the new required fields.
- Generated platform files are overwritten only by the renderer and documented as generated.
- Root and module guidance is updated to the registered nested topology.
- Actual external cross-platform golden executions remain a follow-up; static parity and seeded mutation coverage become mandatory in this change.
8. Acceptance Criteria
- A seeded forbidden import under every nested production module is rejected.
- No legacy flat adapter path remains in gate tests or agent task allowlists.
settings.gradle, dependency verification, import gate, and Gradle runner resolve the same 19 leaf modules frommodules.yaml.- Missing/negative/inconsistent ready verdicts fail validation.
- Claude and Antigravity adapters invoke the shared validator; accepted verdicts produce JSON evidence.
- Rendering followed by
--checkreports no platform drift. - Agent variants uniformly state human-only commit policy and risk-based orchestration.
N!enumeration, all-quote routine grep, file-count report splitting, and unconditional counterargument requirements are absent from active rules.- Harness tests and Gradle checks pass, or every unrun/failing command is reported with risk.