# APP-BUILDER HARNESS
## Autonomous Coding Agent Build Specification — V1
> Purpose: Give this entire specification to a coding agent.
>
> The agent must implement the project sequentially from M1 through M12.
>
> **ZERO clarification questions. ZERO unverified completion claims.**
---
# 0. OPERATING CONTRACT
You are an autonomous senior Python engineer.
Build the **App-Builder Harness** exactly according to this specification.
You MUST:
1. Work sequentially from **M1 → M12**.
2. Never ask the user for clarification.
3. Resolve ambiguity using the defaults defined here.
4. Run real tests and commands before declaring PASS.
5. Stop milestone progression whenever its acceptance tests are red.
6. Repair failures before proceeding.
7. Record evidence for every completed requirement.
8. Keep the implementation inside the V1 scope.
9. Never claim success based solely on LLM output.
10. Finish only when the complete V1 Final Gate passes.
---
# 1. PROJECT GOAL
Build a reliability-first autonomous software-engineering harness that transforms a natural-language application request into a working, tested, reviewed project.
Canonical pipeline:
```text
User Request
↓
Spec Agent
↓
Spec Validation
↓
Planner
↓
Task DAG
↓
Sequential Builder
↓
Real Verification
↓
Failure Classification
↓
Repair Loop
↓
Reverification
↓
Traceability Matrix
↓
Requirement Review
↓
Runtime Verification
↓
Final Deliverable
```
Example input:
```text
Build me a task management web app with authentication,
projects, tasks, and a dashboard.
```
---
# 2. CENTRAL INVARIANT — EVIDENCE OVER CLAIMS
Every requirement MUST be traceable through:
```text
REQ-ID
↓
TASK-ID
↓
FILE(S)
↓
TEST / COMMAND
↓
EXECUTION RESULT
↓
PASS EVIDENCE
```
A requirement is **not complete** merely because:
* an LLM generated code;
* a file exists;
* an agent says it is finished;
* static inspection looks correct.
A PASS requires real evidence.
Minimum PASS evidence:
```text
implementation file exists
+
verification command executed
+
exit_code == 0
+
result persisted
```
Never output:
```text
AI says finished
```
as completion evidence.
---
# 3. V1 SCOPE LOCK
## Harness runtime
* Python 3.11+
* Pydantic >= 2.0
* pytest >= 7.0
* Python standard library for infrastructure whenever possible
Allowed stdlib examples:
```text
argparse
asyncio
hashlib
json
logging
pathlib
shlex
socket
sqlite3
subprocess
time
urllib
uuid
```
## Harness architecture
Repository:
```text
app-builder/
└── src/harness/
```
State storage:
```text
SQLite / JSON files
```
Sandbox:
```text
LocalSandbox
```
Execution model:
```text
Sequential DAG only
```
LLM abstraction:
```text
LLMProvider
├── MockProvider
└── EnvOpenAICompatibleProvider
```
---
# 4. STRICT V1 NON-GOALS
DO NOT implement:
```text
PostgreSQL
Docker sandbox
production deployment
browser automation
Playwright
Selenium
visual canvas
web management UI
parallel builders
parallel DAG execution
file-conflict scheduler
multi-user support
long-term agent memory
internet research
distributed workers
```
A browser verification module may exist only as an explicit post-V1 stub.
---
# 5. DEPENDENCY BOUNDARY
The dependency restriction:
```text
pydantic>=2
pytest>=7
```
applies to the **App-Builder Harness itself**.
Generated applications may contain their own:
```text
requirements.txt
package.json
```
according to their inferred stack.
Do not silently add dependencies to the harness.
Whenever a new harness dependency is intentionally introduced, all of the following MUST be updated together:
```text
pyproject.toml
requirements.txt
tests
documentation
```
---
# 6. OFFLINE BEHAVIOR
"No API key" MUST never block the pipeline.
If:
```text
OPENAI_API_KEY
```
is unavailable:
```text
EnvOpenAICompatibleProvider
↓
MockProvider
↓
deterministic fallback implementation
```
The harness must therefore remain testable without an LLM connection.
"Offline" in this specification means:
```text
No external LLM/web call is required for harness correctness.
```
The Final Gate execution environment must already contain any runtime packages required to execute its generated reference application.
Do not make network availability a prerequisite for core harness unit tests.
---
# 7. DEFAULTS
When ambiguity exists, DO NOT ask.
Use these defaults.
## Stack inference
```text
"web app"
→ frontend=React
→ backend=FastAPI
→ db=SQLite
"API"
→ backend=FastAPI
→ db=SQLite
"todo"
→ FastAPI + SQLite + minimal HTML
unspecified
→ FastAPI + SQLite
```
## App defaults
```text
app_type = "web"
```
Infer pages from explicit nouns such as:
```text
dashboard
login
projects
tasks
settings
```
Infer data entities from domain nouns.
Every explicit feature noun becomes a `must_have` candidate.
Default non-goals:
```text
deployment
mobile-app
browser-automation
```
unless explicitly requested.
## Planning defaults
Small applications:
```text
5–12 tasks
```
Each task SHOULD:
```text
touch <= 5 files
have >= 1 requirement
have >= 1 verification command
```
## Timeouts
```text
sandbox command: 120 seconds
runtime startup: 15 seconds
repair attempts: maximum 3
```
---
# 8. IDENTIFIER CONTRACT
Use deterministic ID formats.
```text
REQ-001
REQ-002
TASK-001
TASK-002
TEST-001
TEST-002
run_XXXXXXXX
```
Requirement IDs and Task IDs must be sequential within a run.
Never reuse an ID for a different object.
---
# 9. RUN ARTIFACT CONTRACT
Each generated run lives under:
```text
runs/<run_id>/
```
Required final layout:
```text
runs/<run_id>/
├── state.json
├── spec.json
├── tasks.json
├── verification.json
├── review.json
├── events.log
├── checkpoints/
│ ├── 001-spec_created.json
│ ├── 002-plan_created.json
│ └── ...
└── workspace/
├── source code
└── tests
```
The canonical final deliverable for every run is:
```text
workspace/
spec.json
tasks.json
verification.json
review.json
events.log
state.json
```
---
# 10. EVENT CONTRACT
All meaningful state transitions append one JSON object to:
```text
runs/<run_id>/events.log
```
Required fields:
```text
run_id
trace_id
stage
agent
task_id
timestamp
duration_ms
model
tokens
tool
status
error
```
Optional values may be empty, but keys must exist.
---
# 11. STATUS CONTRACT
## TaskStatus
```text
PENDING
READY
RUNNING
COMPLETED
FAILED
TIMED_OUT
BLOCKED
```
`READY` may be computed by the DAG engine rather than persisted.
A persisted ready-but-not-started task may remain:
```text
PENDING
```
## RunStatus
```text
CREATED
SPEC_DONE
PLAN_DONE
BUILDING
VERIFYING
REPAIRING
REVIEW_DONE
PASS
FAIL
```
Preserve the distinction:
```text
FAILED != TIMED_OUT
```
---
# 12. BUILD ORDER
The exact milestone order is:
```text
M1 Infrastructure
M2 Specification
M3 Planning + DAG
M4 Building
M5 Verification
M6 Self-Repair
M7 Traceability
M8 Requirement Review
M9 Recovery
M10 Runtime Verification
M11 CLI + Benchmarks
M12 Final Gate
```
Do not reorder.
Do not start milestone `M(N+1)` while `M(N)` has failing acceptance tests.
Run:
```bash
pytest -q
```
after every milestone.
---
# M1 — INFRASTRUCTURE
## Goal
Create an installable repository containing:
* data models;
* run state;
* providers;
* local sandbox;
* event logging;
* deterministic IDs.
No agents yet.
## Required structure
```text
app-builder/
├── src/harness/__init__.py
├── src/harness/models/spec.py
├── src/harness/models/tasks.py
├── src/harness/models/results.py
├── src/harness/models/run.py
├── src/harness/state/store.py
├── src/harness/providers/base.py
├── src/harness/providers/mock.py
├── src/harness/providers/env.py
├── src/harness/sandbox/local.py
├── src/harness/utils/logging.py
├── src/harness/utils/ids.py
├── tests/
├── runs/
├── examples/
├── pyproject.toml
├── requirements.txt
├── README.md
└── .gitignore
```
---
## Core models
### Stack
```python
frontend: str = "FastAPI"
backend: str = "FastAPI"
db: str = "SQLite"
```
### Requirement
```python
id: str
text: str
must_have: bool = True
acceptance: str = ""
```
### AppSpec
```python
app_type: str
stack: Stack
pages: list[Page]
components: list[Component]
data_model: list[DataEntity]
requirements: list[Requirement]
must_have: list[str]
explicit_non_goals: list[str]
acceptance_criteria: list[str]
```
The source specification does not fully define the fields of `Page`, `Component`, and `DataEntity`.
Use minimal Pydantic models sufficient for the specified validation rules; do not add unrelated domain complexity.
### Task
```python
id: str
description: str
depends_on: list[str] = []
files_touched: list[str] = []
requirements: list[str] = []
verification: list[str] = []
status: TaskStatus = PENDING
```
### VerificationResult
```python
task_id: str
status: str
command: str
exit_code: int
stdout: str
stderr: str
duration_ms: int
failure_type: FailureType | None
```
### FailureType
```text
CODE_ERROR
TEST_FAILURE
TYPE_ERROR
DEPENDENCY_ERROR
CONFIG_ERROR
ENVIRONMENT_ERROR
TIMEOUT
UNKNOWN
```
### RequirementResult
```python
requirement_id: str
status: str
evidence: list[str] = []
missing: list[str] = []
```
### RunState
```python
run_id: str
trace_id: str
user_request: str
workspace: str
spec: AppSpec | None
plan: list[Task]
task_results: dict[str, Any]
verification_results: list[VerificationResult]
review: dict | None
checkpoints: list[str]
status: RunStatus
```
All models MUST use Pydantic v2 `BaseModel`.
All enums MUST derive from:
```python
str, Enum
```
---
## LocalSandbox
```python
LocalSandbox(root: Path)
```
Required methods:
```python
create_workspace(run_id) -> Path
write_file(rel, content) -> Path
read_file(rel) -> str
list_files(rel=".") -> list[str]
delete_file(rel)
execute(cmd, cwd=None, timeout_s=120) -> dict
```
Every path MUST be resolved against the configured sandbox root.
Reject:
```text
../
absolute paths
symlink escape
resolved paths outside root
```
Prefer command execution as:
```python
subprocess.run(list_args, shell=False)
```
Verification commands must be parsed with `shlex.split()`.
Do not use `shell=True` in V1.
Return:
```json
{
"exit_code": 0,
"stdout": "",
"stderr": "",
"duration_ms": 0
}
```
---
## RunStore
```python
RunStore(base=Path("runs"))
```
Methods:
```python
create_run(user_request) -> RunState
save(state)
load(run_id) -> RunState
checkpoint(state, event_name, payload)
list_runs() -> list[str]
resume(run_id) -> RunState
```
---
## LLMProvider
Abstract interface:
```python
generate(prompt: str, system: str = "") -> str
generate_structured(
prompt: str,
schema: type[BaseModel]
) -> BaseModel
stream(prompt: str) -> Iterator[str]
```
Agents depend ONLY on this abstraction.
### MockProvider
Must be:
```text
deterministic
offline-safe
test-friendly
```
### EnvOpenAICompatibleProvider
Read:
```text
OPENAI_API_KEY
OPENAI_BASE_URL
```
If API key is absent:
```text
delegate to MockProvider
```
---
## Acceptance
Must pass:
```bash
pip install -e .
pytest -q
```
Tests must include:
```text
AppSpec roundtrip
Task roundtrip
sandbox ../ rejection
sandbox absolute-path rejection
RunStore save/load
MockProvider deterministic behavior
```
No network required.
## Forbidden
Do not implement:
```text
SpecAgent
Planner
Builder
Verifier
DAG execution
```
---
# M2 — SPECIFICATION AGENT + VALIDATOR
## Goal
Transform:
```text
user request
```
into:
```text
validated spec.json
```
No application code generation yet.
## Files
```text
src/harness/agents/spec.py
src/harness/validation/spec_validator.py
tests/test_spec.py
examples/todo_spec.json
```
---
## SpecAgent
Interface:
```python
SpecAgent(llm: LLMProvider)
generate(user_request: str) -> AppSpec
```
System instruction:
```text
Output ONLY JSON matching AppSpec.
No prose.
Infer stack, pages, data model, requirements,
must-have features, explicit non-goals and acceptance criteria.
```
Post-processing MUST:
```text
assign REQ-001..N
ensure must_have is non-empty
ensure acceptance_criteria is non-empty
populate default explicit_non_goals when absent
```
If LLM output is invalid:
```text
use deterministic rule-based fallback
```
Fallback must understand at minimum:
```text
auth
projects
tasks
dashboard
todo
```
---
## SpecValidator
Return:
```python
list[str]
```
Empty list means PASS.
### Structural checks
Verify:
```text
app_type non-empty
stack fields non-empty
requirements >= 1
acceptance_criteria >= 1
REQ IDs unique
REQ IDs match ^REQ-\d{3}$
```
### Logical checks
Verify:
```text
page.entity references known data entity when entity is present
requirement does not conflict with explicit non-goal
backend is defined when requirement mentions API/backend
requirement text is unique case-insensitively
every must_have maps to >=1 requirement
```
---
## Pipeline stage
Implement:
```python
spec_stage(
store,
run_id,
llm,
max_attempts=2
)
```
Flow:
```text
generate
→ validate
→ if invalid: regenerate with validation feedback
→ maximum 2 generation attempts
→ persist spec
→ checkpoint spec_created
```
Persist:
```text
runs/<run_id>/spec.json
```
---
## Acceptance
Test:
```text
valid Todo request → PASS
conflicting login non-goal → FAIL
missing acceptance → FAIL
duplicate requirement → FAIL
first generation invalid + second valid → PASS
```
Create:
```text
examples/todo_spec.json
```
with four requirements.
## Forbidden
No planning.
No code generation.
---
# M3 — PLANNER + DAG ENGINE
## Goal
Transform:
```text
AppSpec
```
into:
```text
validated sequential Task DAG
```
Persist:
```text
tasks.json
```
## Files
```text
src/harness/agents/planner.py
src/harness/orchestration/dag.py
src/harness/orchestration/runner.py
tests/test_planner.py
tests/test_dag.py
```
---
## Planner rules
Enforce these in code.
Do NOT rely only on the LLM prompt.
### Ordering
1. DB/schema before dependent application logic.
2. Shared components before pages.
3. Auth infrastructure before authenticated routes.
### Coverage
Every:
```text
REQ
```
must map to at least one Task.
Every Task must contain:
```text
>=1 requirement
>=1 file
>=1 verification command
```
### IDs
Generate:
```text
TASK-001
TASK-002
...
```
Dependencies may reference only earlier tasks.
If LLM output violates ordering:
```text
repair deterministically
```
### Paths
Every `files_touched` path must be:
```text
relative
POSIX-style
inside workspace
without ..
```
---
## Fallback planner
If LLM planning fails, generate deterministic tasks roughly covering:
```text
project/schema setup
auth if required
core entity CRUD
API/pages
tests/verification
```
For small apps:
```text
5–12 tasks
```
---
## DagEngine
Required behavior:
```python
get_ready()
mark(task_id, status)
is_done()
blocked_propagation()
topological_order()
```
A task is READY iff:
```text
status == PENDING
AND
all dependencies == COMPLETED
```
If dependency becomes:
```text
FAILED
TIMED_OUT
```
dependent tasks become:
```text
BLOCKED
```
Cycles must raise an explicit error.
---
## PlanValidator
Detect:
```text
duplicate task IDs
unknown dependency
cycle
orphan requirement
task without verification
task without files
task without requirements
invalid paths
```
Overlapping files:
```text
WARNING only in V1
```
---
## Acceptance
Todo spec with four requirements:
```text
→ 5–8 tasks
```
Tests:
```text
all requirements covered
dependency ordering valid
cycle rejected
TASK-001 failure blocks dependent task
tasks.json persisted
plan_created checkpoint persisted
```
## Forbidden
No Builder execution.
No concurrency.
---
# M4 — BUILDER + SANDBOX-GATED FILE TOOLS
## Goal
Transform one Task into real files.
## Files
```text
src/harness/agents/builder.py
src/harness/tools/files.py
tests/test_builder.py
```
---
## Builder context
Provide ONLY:
```text
current Task
requirements referenced by Task
small spec summary
dependency verification results
allowed files
verification commands
```
Do NOT dump the full run history.
Example input:
```python
task
requirements
spec_summary = {
"app_type": ...,
"stack": ...,
"data_model": ...
}
dependency_results
allowed_files
verification
```
---
## Builder output
LLM must produce:
```json
{
"relative/path.py": "full file contents"
}
```
No prose.
No markdown fences.
---
## Write restrictions
Builder may write ONLY:
```text
task.files_touched
```
Any attempted write outside the allowlist:
```text
PermissionError
+
event log
+
task failure
+
CONFIG_ERROR
```
Builder may use only sandboxed:
```text
read_file
write_file
list_files
```
Builder may NOT execute subprocesses.
---
## Deterministic fallback
If LLM output cannot be parsed, use a deterministic implementation for the current task.
The fallback MUST obey the same `files_touched` allowlist.
The planner fallback therefore MUST ensure any deterministic scaffold files are explicitly listed in the relevant task.
Reference generated application may include:
```text
src/main.py
src/models.py
requirements.txt
tests/test_health.py
```
Do not create files outside the current Task's declared set.
---
## Acceptance
Test:
```text
allowed file write succeeds
outside-allowlist write fails
../ escape fails
MockProvider creates deterministic output
checkpoint created after task
```
After milestone:
```bash
pytest -q
```
must pass.
## Forbidden
No verification execution inside Builder.
No repair.
---
# M5 — REAL VERIFICATION + FAILURE CLASSIFICATION
## Goal
Execute real verification commands and persist structured evidence.
## Files
```text
src/harness/verification/verifier.py
src/harness/verification/classifier.py
tests/test_verifier.py
tests/test_classifier.py
```
---
## Verifier
Implement:
```python
verify_task(
task: Task,
workspace: Path
) -> list[VerificationResult]
```
For every verification command:
```text
shlex.split(command)
→ LocalSandbox.execute(...)
```
Default when missing:
```bash
pytest -q
```
Capture:
```text
exit_code
stdout[-4000:]
stderr[-4000:]
duration_ms
```
PASS:
```text
exit_code == 0
```
FAIL:
```text
exit_code != 0
```
Timeout:
```text
Task status = TIMED_OUT
FailureType = TIMEOUT
```
Static inspection alone can never count as verification.
---
## Workspace verification
Provide helper:
```python
verify_workspace(workspace)
```
It may include project-level checks appropriate to files actually present.
Do not blindly require external network installation as part of offline harness unit tests.
---
## Failure classifier precedence
Classification MUST be deterministic.
Use precedence:
```text
1. TIMEOUT
2. ENVIRONMENT_ERROR
3. DEPENDENCY_ERROR
4. TYPE_ERROR
5. CODE_ERROR
6. CONFIG_ERROR
7. TEST_FAILURE
8. UNKNOWN
```
The precedence matters.
For example, a pytest session containing a Python `SyntaxError` must classify as:
```text
CODE_ERROR
```
not merely `TEST_FAILURE`.
### TIMEOUT
Patterns:
```text
timed out
TimeoutExpired
duration >= configured timeout
```
### ENVIRONMENT_ERROR
Patterns:
```text
EAI_AGAIN
ENOTFOUND
registry unavailable
Network is unreachable
HTTP 503
Could not fetch
```
### DEPENDENCY_ERROR
Patterns:
```text
ModuleNotFoundError
ImportError
No module named
Could not resolve dependency
npm ERR 404
```
### TYPE_ERROR
Patterns:
```text
mypy
Pydantic ValidationError
TypeError ... expected
TS2322
Property ... does not exist
```
### CODE_ERROR
Patterns:
```text
SyntaxError
IndentationError
NameError
ReferenceError
```
### CONFIG_ERROR
Patterns:
```text
missing configuration
missing pyproject
requirements file not found
port already in use
invalid path configuration
```
### TEST_FAILURE
Patterns:
```text
AssertionError
FAILED
1 failed
FAIL tests/
```
Only after higher-priority categories have been excluded.
---
## Acceptance
Tests:
```text
SyntaxError → CODE_ERROR
ModuleNotFoundError → DEPENDENCY_ERROR
AssertionError → TEST_FAILURE
network unavailable → ENVIRONMENT_ERROR
timeout → TIMEOUT
working scaffold → PASS
```
Persist verification evidence.
## Forbidden
No automatic repair yet.
---
# M6 — REPAIR LOOP + LOOP DETECTION
## Goal
Implement:
```text
FAIL
→ classify
→ repair
→ verify
```
with bounded retries.
## Files
```text
src/harness/orchestration/repair.py
src/harness/agents/repair_agent.py
tests/test_repair.py
```
---
## Loop signature
```python
sha256(
command
+ exit_code
+ normalize(stderr[-2000:])
)
```
Normalization:
```text
lowercase
strip changing timestamps
strip volatile numeric values
normalize paths
collapse whitespace
```
Track:
```python
seen[signature] += 1
```
If the same normalized failure signature occurs three times:
```text
ESCALATE
FAILED
BLOCK dependents
```
Total repair attempts MUST NEVER exceed:
```text
3
```
---
## Repair strategy
### ENVIRONMENT_ERROR
```text
Do not rewrite application code.
Retry once.
If still failing → FAILED.
```
### DEPENDENCY_ERROR
Repair only dependency/config files that are already allowed by the Task or explicitly listed as verification hints.
### TYPE_ERROR
Patch relevant code only.
### CODE_ERROR
Patch relevant code only.
### TEST_FAILURE
Patch implementation or tests only when justified by requirement evidence.
Do not simply weaken tests to obtain PASS.
### CONFIG_ERROR
Patch configuration files only.
### TIMEOUT
Allow one bounded adjustment/retry.
Do not create an unbounded timeout.
---
## RepairAgent context
Provide:
```text
Task
relevant requirement slice
failing VerificationResult
FailureType
allowed files
current relevant file contents
```
Truncate large source context around:
```text
8000 chars per repair context
```
Output:
```json
{
"relative/path": "full corrected contents"
}
```
---
## Acceptance
Tests:
```text
repair SyntaxError → PASS within <=3 attempts
same failure 3 times → ESCALATE
dependents become BLOCKED
ENVIRONMENT_ERROR does not modify code
files outside allowlist cannot be repaired
```
---
# M7 — TRACEABILITY MATRIX
## Goal
Construct mechanical evidence:
```text
Requirement
→ Tasks
→ Files
→ Verification
→ Result
```
## Files
```text
src/harness/trace/matrix.py
tests/test_trace.py
```
---
## Matrix structure
For every requirement:
```json
{
"REQ-001": {
"tasks": [],
"files": [],
"tests": [],
"evidence": [],
"status": "PASS|FAIL",
"missing": []
}
}
```
Compute:
```text
tasks
= tasks referencing REQ
files
= union(task.files_touched)
tests
= union(task.verification)
evidence
= existing files
+ successful verification commands
```
PASS only if:
```text
>=1 expected implementation file exists
AND
>=1 relevant verification result PASS
```
No evidence:
```text
FAIL
```
Prose can never substitute for evidence.
---
## Acceptance
Todo reference run:
```text
4/4 requirements traced
```
Delete an implementation file:
```text
associated requirement becomes FAIL
```
---
# M8 — REQUIREMENT REVIEW
## Goal
Perform the final requirement-level audit.
## Files
```text
src/harness/agents/reviewer.py
tests/test_review.py
```
---
## ReviewAgent
Default authority:
```text
rule-based evidence
```
LLM review is optional and explanatory only.
An LLM MAY:
```text
add rationale
summarize evidence
identify concerns
```
An LLM MUST NOT:
```text
turn evidence-based FAIL into PASS
```
---
## Output
Persist:
```text
runs/<run_id>/review.json
```
Shape:
```json
{
"requirements": [
{
"id": "REQ-001",
"status": "PASS",
"evidence": [],
"missing": []
}
],
"overall_status": "PASS"
}
```
Overall PASS only if:
```text
every requirement == PASS
```
---
## Acceptance
Tests:
```text
complete evidence → PASS
missing implementation file → FAIL
missing successful verification → FAIL
LLM cannot override FAIL
review JSON validates
```
---
# M9 — CHECKPOINTING + CRASH RECOVERY
## Goal
Resume interrupted runs without repeating completed work.
## Files
```text
src/harness/state/checkpoints.py
src/harness/orchestration/pipeline.py
tests/test_recovery.py
```
---
## Required checkpoint events
```text
spec_created
plan_created
task_started
task_completed
verification_completed
repair_started
review_completed
```
Filename convention:
```text
checkpoints/<sequence>-<event>-<optional-task>.json
```
Example:
```text
001-spec_created.json
002-plan_created.json
003-task_started-TASK-001.json
004-task_completed-TASK-001.json
```
---
## Resume algorithm
```text
load state.json
↓
validate state
↓
load latest checkpoint state
↓
reconstruct task statuses
↓
keep COMPLETED
keep FAILED
keep BLOCKED
convert interrupted RUNNING → PENDING
convert READY → PENDING
↓
continue unfinished pipeline
```
Completed tasks MUST NOT execute again.
Use file hashes where appropriate to prove completed output was not rewritten during resume.
---
## Corruption handling
Corrupt:
```text
state.json
checkpoint JSON
```
must produce a clear explicit error.
Never silently restart the run from scratch.
---
## Acceptance
Simulate crash after:
```text
TASK-002
```
Resume must:
```text
finish remaining tasks
not rerun TASK-001
not alter completed file hashes
```
Test checkpoint sequencing.
---
# M10 — RUNTIME VERIFICATION
## Goal
Prove that the generated application actually starts and responds.
Static tests alone are insufficient.
## Files
```text
src/harness/verification/runtime.py
src/harness/verification/browser.py
tests/test_runtime.py
```
---
## RuntimeVerifier
### Entry detection
Recognize at minimum:
```text
src/main.py:app
app.py:app
package.json
```
No recognized entry:
```text
FAIL
CONFIG_ERROR
```
### Start
FastAPI:
```bash
python -m uvicorn src.main:app --port <free_port>
```
Node fallback:
```bash
npm run dev -- --port <free_port>
```
Use an OS-assigned/free local port.
Start process with:
```python
subprocess.Popen
```
with:
```text
cwd jailed inside workspace
shell=False
```
The verification layer may own process execution; application-building agents may not.
### Startup timeout
```text
15 seconds
```
### Checks
Verify:
```text
process remains alive
TCP port accepts connection
GET /health OR / returns 2xx
GET /docs or /api/health when available
SQLite DB can be opened when expected
```
### Cleanup
Always terminate spawned process.
Use `finally` cleanup.
Never leave orphan development servers.
### Result
Return structured:
```json
{
"status": "PASS",
"checks": [
{
"name": "health",
"ok": true,
"detail": "HTTP 200"
}
],
"evidence": []
}
```
Capture useful log snippets.
---
## Browser V1 stub
Implement only:
```python
def verify_acceptance(...):
raise NotImplementedError(
"Browser verification deferred post-V1"
)
```
Test that the browser verifier remains explicitly deferred.
Do NOT install Playwright or Selenium.
---
## Acceptance
Reference application:
```text
starts
port opens
health endpoint returns 200
runtime verifier PASS
```
Broken startup:
```text
FAIL
diagnostics captured
repair hint available
```
---
# M11 — CLI + BENCHMARKS
## Goal
Expose the entire harness through a deterministic command-line interface and provide a quick regression benchmark.
## Files
```text
src/harness/cli.py
src/harness/orchestration/pipeline.py
src/harness/benchmarks.py
tests/test_cli.py
tests/test_benchmarks.py
```
Add console entrypoint:
```toml
[project.scripts]
builder = "harness.cli:main"
```
Use:
```text
argparse only
```
No Click/Typer dependency.
---
## CLI commands
### New run
```bash
builder new "Build a Todo app"
```
Equivalent module form:
```bash
python -m harness.cli new "Build a Todo app"
```
It must execute the full pipeline.
### Resume
```bash
builder resume <run_id>
```
### Logs
```bash
builder logs <run_id>
```
Print or tail the run's structured event log in readable form.
### Benchmark
```bash
builder bench --quick
```
---
## Progress output
`builder new` must emit five user-facing high-level stages:
```text
[1/5] SPEC
[2/5] PLAN
[3/5] BUILD
[4/5] VERIFY
[5/5] REVIEW
```
Detailed internal milestones remain M1–M12; the five-stage CLI view is only presentation.
On success:
```text
BUILD COMPLETE
```
On failure:
```text
BUILD FAILED
```
and return non-zero exit status.
---
## Quick benchmark
`builder bench --quick` runs a deterministic small Todo scenario.
It must validate at minimum:
```text
spec generated
plan generated
files written
verification executed
runtime checked
review produced
required artifacts exist
```
Return:
```text
0 → PASS
non-zero → FAIL
```
---
## Acceptance
Must pass:
```bash
builder new "Build a Todo app"
builder bench --quick
```
Offline LLM fallback must still function.
Verify:
```text
all required artifacts exist
five-stage output matches expected format
events.log contains required keys
quick benchmark passes
```
## Forbidden
No Web UI.
No production Docker environment.
---
# M12 — FINAL GATE
## Goal
Prove V1 reliability before declaring completion.
All gates are mandatory.
---
## Gate 1 — Vertical Slice
Run:
```bash
builder new "Build a Simple Todo App with add/list/complete"
```
Expected pipeline:
```text
SPEC
→ >=3 REQs
→ PLAN
→ >=3 tasks
→ BUILD
→ real files
→ VERIFY
→ pytest PASS
→ RUNTIME
→ PASS
→ REVIEW
→ PASS
```
Save a stable demonstration run under:
```text
runs/demo_todo/
```
If any stage fails:
```text
fix the harness
rerun
do not proceed
```
---
## Gate 2 — Failure Injection
Inject:
```python
SyntaxError
```
into:
```text
workspace/src/main.py
```
The harness must:
```text
DETECT
→ FAIL
CLASSIFY
→ CODE_ERROR
LOCALIZE
→ TASK-ID
CAPTURE
→ diagnostics
REPAIR
→ relevant file only
REVERIFY
→ PASS
```
Then simulate identical failure repeatedly using a no-op repair implementation.
Expected:
```text
same signature x3
→ LOOP DETECTED
→ ESCALATE
→ task FAILED
→ dependents BLOCKED
```
---
## Gate 3 — V1 Capability Checklist
All MUST be ✓:
```text
[ ] valid spec generated
[ ] spec validated
[ ] valid DAG generated
[ ] sequential execution
[ ] real files created
[ ] real verification executed
[ ] failures localized
[ ] failures classified
[ ] failures repaired
[ ] repair bounded <=3
[ ] loop detection works
[ ] checkpoints written
[ ] crash resume works
[ ] completed tasks not rerun
[ ] traceability matrix generated
[ ] requirement review generated
[ ] runtime verified
[ ] final working project retained
```
---
## Gate 4 — Documentation
README must document:
```text
quickstart
builder new
builder resume
builder logs
builder bench --quick
architecture
evidence principle
failure handling
checkpoint recovery
```
Include an ASCII architecture diagram.
Create:
```text
examples/todo_run/
├── spec.json
├── tasks.json
├── verification.json
└── review.json
```
---
## Gate 5 — Full Test Suite
Run:
```bash
pytest -q
builder bench --quick
```
Both must pass.
---
## V1 Forbidden-Feature Audit
Assert the implementation does NOT contain functional implementations for:
```text
docker/
web_ui/
parallel workers
parallel DAG scheduler
Playwright
Selenium
PostgreSQL backend
web research
```
The browser verification stub is allowed.
---
# FINAL DEFINITION OF DONE
V1 is complete only when:
```text
M1 PASS
M2 PASS
M3 PASS
M4 PASS
M5 PASS
M6 PASS
M7 PASS
M8 PASS
M9 PASS
M10 PASS
M11 PASS
M12 PASS
```
Every bug fix MUST include a regression test.
Every new module MUST have tests.
Keep source files focused.
Prefer:
```text
<400 lines per file
```
Split larger files when practical.
Never store:
```text
API keys
secrets
absolute host-specific paths
```
Never delete historical checkpoints to hide failures.
---
# FINAL RUN SUMMARY FORMAT
At the end of every run, print a requirement-level summary.
Example:
```text
REQ-001
Implemented: YES
Tested: YES
Runtime: YES
Evidence:
- src/main.py
- pytest -q → exit_code 0
Status: PASS
REQ-002
Implemented: YES
Tested: NO
Runtime: NO
Missing:
- successful verification result
Status: FAIL
```
Final status:
```text
PASS
```
only when every requirement has evidence-backed PASS status.
Never use:
```text
"AI says finished"
```
as evidence.
---
# EXECUTION COMMAND
Start now.
Implement:
```text
M1
```
Run its tests.
If green, continue to:
```text
M2
```
Continue sequentially until M12.
Do not ask questions.
Do not stop at intermediate milestones.
Do not skip failed gates.
Do not declare V1 complete until the Final Gate is green.# APP-BUILDER HARNESS
## 自主编码智能体构建规范 — V1
> 目的:将本规范整体交给编码智能体。
>
> 智能体必须按顺序依次实现 M1 到 M12。
>
> **零澄清问题。零未经核实的完成声明。**
---
# 0. 运行契约
你是一名自主高级 Python 工程师。
严格按照本规范构建 **App-Builder Harness**。
你必须:
1. 按顺序从 **M1 → M12** 推进。
2. 绝不向用户提出澄清问题。
3. 遇到歧义时使用此处定义的默认值来解决。
4. 在声明 PASS 之前运行真实的测试和命令。
5. 任何里程碑的验收测试为红时,立即停止里程碑推进。
6. 在继续之前修复所有失败。
7. 为每一项已完成的需求记录证据。
8. 实现范围严格保持在 V1 之内。
9. 绝不只基于 LLM 的输出就声称成功。
10. 仅当完整的 V1 最终关卡通过后才算完成。
---
# 1. 项目目标
构建一个以可靠性为先的自主软件工程框架(harness),将自然语言的应用需求转换为可运行、经过测试、并经过评审的项目。
标准流水线:
```text
用户请求
↓
Spec Agent
↓
Spec Validation
↓
Planner
↓
Task DAG
↓
Sequential Builder
↓
Real Verification
↓
Failure Classification
↓
Repair Loop
↓
Reverification
↓
Traceability Matrix
↓
Requirement Review
↓
Runtime Verification
↓
Final Deliverable
```
输入示例:
```text
Build me a task management web app with authentication,
projects, tasks, and a dashboard.
```
---
# 2. 核心不变量——证据优于声明
每一项需求都必须可追溯:
```text
REQ-ID
↓
TASK-ID
↓
FILE(S)
↓
TEST / COMMAND
↓
EXECUTION RESULT
↓
PASS EVIDENCE
```
仅在以下情况下,需求**不算完成**:
* LLM 生成了代码;
* 文件存在;
* 智能体声称已完成;
* 静态检查看起来正确。
PASS 必须有真实证据。
最低 PASS 证据:
```text
implementation file exists
+
verification command executed
+
exit_code == 0
+
result persisted
```
绝不允许输出:
```text
AI says finished
```
作为完成证据。
---
# 3. V1 范围锁定
## Harness 运行时
* Python 3.11+
* Pydantic >= 2.0
* pytest >= 7.0
* 基础设施优先使用 Python 标准库
允许使用的 stdlib 示例:
```text
argparse
asyncio
hashlib
json
logging
pathlib
shlex
socket
sqlite3
subprocess
time
urllib
uuid
```
## Harness 架构
代码仓库:
```text
app-builder/
└── src/harness/
```
状态存储:
```text
SQLite / JSON 文件
```
沙箱:
```text
LocalSandbox
```
执行模型:
```text
仅顺序 DAG
```
LLM 抽象:
```text
LLMProvider
├── MockProvider
└── EnvOpenAICompatibleProvider
```
---
# 4. 严格的 V1 非目标
不要实现:
```text
PostgreSQL
Docker sandbox
production deployment
browser automation
Playwright
Selenium
visual canvas
web management UI
parallel builders
parallel DAG execution
file-conflict scheduler
multi-user support
long-term agent memory
internet research
distributed workers
```
浏览器验证模块只能作为明确的 post-V1 占位符存在。
---
# 5. 依赖边界
以下依赖限制:
```text
pydantic>=2
pytest>=7
```
适用于 **App-Builder Harness 自身**。
被生成的应用可以包含各自的:
```text
requirements.txt
package.json
```
依其推断的技术栈而定。
不要在 harness 中静默添加依赖。
凡是有意新增 harness 依赖时,以下文件必须同步更新:
```text
pyproject.toml
requirements.txt
tests
documentation
```
---
# 6. 离线行为
"无 API key" 绝不能阻塞流水线。
如果:
```text
OPENAI_API_KEY
```
不可用:
```text
EnvOpenAICompatibleProvider
↓
MockProvider
↓
deterministic fallback implementation
```
因此 harness 必须在没有 LLM 连接的情况下也能被测试。
本规范中的"离线"意味着:
```text
No external LLM/web call is required for harness correctness.
```
最终关卡的执行环境必须已经包含运行其生成的参考应用所需的全部运行时包。
不要把网络可用性作为核心 harness 单元测试的前置条件。
---
# 7. 默认值
遇到歧义时,不要提问。
使用以下默认值。
## 技术栈推断
```text
"web app"
→ frontend=React
→ backend=FastAPI
→ db=SQLite
"API"
→ backend=FastAPI
→ db=SQLite
"todo"
→ FastAPI + SQLite + minimal HTML
unspecified
→ FastAPI + SQLite
```
## 应用默认值
```text
app_type = "web"
```
从以下显式名词中推断页面:
```text
dashboard
login
projects
tasks
settings
```
从领域名词推断数据实体。
每一个显式的功能名词都成为 `must_have` 候选。
默认的非目标:
```text
deployment
mobile-app
browser-automation
```
除非显式要求。
## 规划默认值
小型应用:
```text
5–12 个任务
```
每个任务应当:
```text
触及 <= 5 个文件
至少包含 1 项需求
至少包含 1 条验证命令
```
## 超时
```text
sandbox command: 120 seconds
runtime startup: 15 seconds
repair attempts: maximum 3
```
---
# 8. 标识符契约
使用确定性的 ID 格式。
```text
REQ-001
REQ-002
TASK-001
TASK-002
TEST-001
TEST-002
run_XXXXXXXX
```
需求 ID 与任务 ID 在同一次运行内必须保持递增。
不得将同一 ID 复用于不同的对象。
---
# 9. 运行产物契约
每次生成的运行位于:
```text
runs/<run_id>/
```
必需的最末布局:
```text
runs/<run_id>/
├── state.json
├── spec.json
├── tasks.json
├── verification.json
├── review.json
├── events.log
├── checkpoints/
│ ├── 001-spec_created.json
│ ├── 002-plan_created.json
│ └── ...
└── workspace/
├── source code
└── tests
```
每次运行的标准最末交付物是:
```text
workspace/
spec.json
tasks.json
verification.json
review.json
events.log
state.json
```
---
# 10. 事件契约
所有有意义的状态转换都会向以下文件追加一条 JSON 对象:
```text
runs/<run_id>/events.log
```
必需字段:
```text
run_id
trace_id
stage
agent
task_id
timestamp
duration_ms
model
tokens
tool
status
error
```
可选值可以为空,但键必须存在。
---
# 11. 状态契约
## TaskStatus
```text
PENDING
READY
RUNNING
COMPLETED
FAILED
TIMED_OUT
BLOCKED
```
`READY` 可由 DAG 引擎计算得出,无需持久化。
已持久化的 ready-but-not-started 任务可以保持:
```text
PENDING
```
## RunStatus
```text
CREATED
SPEC_DONE
PLAN_DONE
BUILDING
VERIFYING
REPAIRING
REVIEW_DONE
PASS
FAIL
```
保留以下区别:
```text
FAILED != TIMED_OUT
```
---
# 12. 构建顺序
严格的里程碑顺序为:
```text
M1 Infrastructure
M2 Specification
M3 Planning + DAG
M4 Building
M5 Verification
M6 Self-Repair
M7 Traceability
M8 Requirement Review
M9 Recovery
M10 Runtime Verification
M11 CLI + Benchmarks
M12 Final Gate
```
不得重新排序。
当 `M(N)` 的验收测试未全部通过时,不得开始里程碑 `M(N+1)`。
每个里程碑完成后运行:
```bash
pytest -q
```
---
# M1 — 基础设施
## 目标
创建一个可安装的代码仓库,包含:
* 数据模型;
* 运行状态;
* providers;
* 本地沙箱;
* 事件日志;
* 确定性 ID。
暂不实现智能体。
## 必需结构
```text
app-builder/
├── src/harness/__init__.py
├── src/harness/models/spec.py
├── src/harness/models/tasks.py
├── src/harness/models/results.py
├── src/harness/models/run.py
├── src/harness/state/store.py
├── src/harness/providers/base.py
├── src/harness/providers/mock.py
├── src/harness/providers/env.py
├── src/harness/sandbox/local.py
├── src/harness/utils/logging.py
├── src/harness/utils/ids.py
├── tests/
├── runs/
├── examples/
├── pyproject.toml
├── requirements.txt
├── README.md
└── .gitignore
```
---
## 核心模型
### Stack
```python
frontend: str = "FastAPI"
backend: str = "FastAPI"
db: str = "SQLite"
```
### Requirement
```python
id: str
text: str
must_have: bool = True
acceptance: str = ""
```
### AppSpec
```python
app_type: str
stack: Stack
pages: list[Page]
components: list[Component]
data_model: list[DataEntity]
requirements: list[Requirement]
must_have: list[str]
explicit_non_goals: list[str]
acceptance_criteria: list[str]
```
源规范并未完整定义 `Page`、`Component` 与 `DataEntity` 的字段。
使用满足所规定验证规则的最小 Pydantic 模型即可;不要添加无关的领域复杂性。
### Task
```python
id: str
description: str
depends_on: list[str] = []
files_touched: list[str] = []
requirements: list[str] = []
verification: list[str] = []
status: TaskStatus = PENDING
```
### VerificationResult
```python
task_id: str
status: str
command: str
exit_code: int
stdout: str
stderr: str
duration_ms: int
failure_type: FailureType | None
```
### FailureType
```text
CODE_ERROR
TEST_FAILURE
TYPE_ERROR
DEPENDENCY_ERROR
CONFIG_ERROR
ENVIRONMENT_ERROR
TIMEOUT
UNKNOWN
```
### RequirementResult
```python
requirement_id: str
status: str
evidence: list[str] = []
missing: list[str] = []
```
### RunState
```python
run_id: str
trace_id: str
user_request: str
workspace: str
spec: AppSpec | None
plan: list[Task]
task_results: dict[str, Any]
verification_results: list[VerificationResult]
review: dict | None
checkpoints: list[str]
status: RunStatus
```
所有模型必须使用 Pydantic v2 的 `BaseModel`。
所有枚举必须派生自:
```python
str, Enum
```
---
## LocalSandbox
```python
LocalSandbox(root: Path)
```
必需方法:
```python
create_workspace(run_id) -> Path
write_file(rel, content) -> Path
read_file(rel) -> str
list_files(rel=".") -> list[str]
delete_file(rel)
execute(cmd, cwd=None, timeout_s=120) -> dict
```
所有路径都必须相对于配置的沙箱根目录解析。
拒绝:
```text
../
absolute paths
symlink escape
resolved paths outside root
```
命令执行优先采用:
```python
subprocess.run(list_args, shell=False)
```
验证命令必须用 `shlex.split()` 解析。
V1 中不得使用 `shell=True`。
返回:
```json
{
"exit_code": 0,
"stdout": "",
"stderr": "",
"duration_ms": 0
}
```
---
## RunStore
```python
RunStore(base=Path("runs"))
```
方法:
```python
create_run(user_request) -> RunState
save(state)
load(run_id) -> RunState
checkpoint(state, event_name, payload)
list_runs() -> list[str]
resume(run_id) -> RunState
```
---
## LLMProvider
抽象接口:
```python
generate(prompt: str, system: str = "") -> str
generate_structured(
prompt: str,
schema: type[BaseModel]
) -> BaseModel
stream(prompt: str) -> Iterator[str]
```
智能体仅依赖该抽象。
### MockProvider
必须满足:
```text
deterministic
offline-safe
test-friendly
```
### EnvOpenAICompatibleProvider
读取:
```text
OPENAI_API_KEY
OPENAI_BASE_URL
```
若 API key 缺失:
```text
delegate to MockProvider
```
---
## 验收
必须通过:
```bash
pip install -e .
pytest -q
```
测试必须覆盖:
```text
AppSpec roundtrip
Task roundtrip
sandbox ../ rejection
sandbox absolute-path rejection
RunStore save/load
MockProvider deterministic behavior
```
无需网络。
## 禁止
不要实现:
```text
SpecAgent
Planner
Builder
Verifier
DAG execution
```
---
# M2 — 规范智能体 + 校验器
## 目标
将:
```text
user request
```
转换为:
```text
validated spec.json
```
暂不生成应用代码。
## 文件
```text
src/harness/agents/spec.py
src/harness/validation/spec_validator.py
tests/test_spec.py
examples/todo_spec.json
```
---
## SpecAgent
接口:
```python
SpecAgent(llm: LLMProvider)
generate(user_request: str) -> AppSpec
```
系统指令:
```text
Output ONLY JSON matching AppSpec.
No prose.
Infer stack, pages, data model, requirements,
must-have features, explicit non-goals and acceptance criteria.
```
后处理必须:分配REQ-001..N
确保 must_have 非空
确保 acceptance_criteria 非空
在缺失时填充默认的 explicit_non_goals
```
如果 LLM 输出无效:
```text
使用确定性的基于规则的回退
```
回退必须至少理解:
```text
auth
projects
tasks
dashboard
todo
```
---
## SpecValidator
返回:
```python
list[str]
```
空列表表示通过。
### 结构检查
校验:
```text
app_type 非空
stack 字段非空
requirements >= 1
acceptance_criteria >= 1
REQ ID 唯一
REQ ID 匹配 ^REQ-\d{3}$
```
### 逻辑检查
校验:
```text
page.entity 在 entity 存在时引用已知的数据实体
requirement 不与显式 non-goal 冲突
当 requirement 提到 API/backend 时 backend 已定义
requirement 文本大小写不敏感地唯一
每个 must_have 映射到 >=1 个 requirement
```
---
## 流水线阶段
实现:
```python
spec_stage(
store,
run_id,
llm,
max_attempts=2
)
```
流程:
```text
生成
→ 校验
→ 若无效:基于校验反馈重新生成
→ 最多 2 次生成尝试
→ 持久化 spec
→ 检查点 spec_created
```
持久化:
```text
runs/<run_id>/spec.json
```
---
## 验收
测试:
```text
有效的 Todo 请求 → PASS
冲突的 login non-goal → FAIL
缺失 acceptance → FAIL
重复的 requirement → FAIL
首次生成无效 + 第二次有效 → PASS
```
创建:
```text
examples/todo_spec.json
```
包含四个 requirement。
## 禁止
不进行规划。
不生成代码。
---
# M3 — PLANNER + DAG 引擎
## 目标
将:
```text
AppSpec
```
转换为:
```text
经过校验的顺序 Task DAG
```
持久化:
```text
tasks.json
```
## 文件
```text
src/harness/agents/planner.py
src/harness/orchestration/dag.py
src/harness/orchestration/runner.py
tests/test_planner.py
tests/test_dag.py
```
---
## Planner 规则
在代码中强制执行以下规则。
不要仅依赖 LLM 提示词。
### 顺序
1. DB/schema 在依赖它的应用逻辑之前。
2. 共享组件在页面之前。
3. Auth 基础设施在已鉴权路由之前。
### 覆盖
每个:
```text
REQ
```
必须至少映射到一个 Task。
每个 Task 必须包含:
```text
>=1 个 requirement
>=1 个文件
>=1 个 verification 命令
```
### ID
生成:
```text
TASK-001
TASK-002
...
```
依赖只能引用更早的任务。
如果 LLM 输出违反顺序:
```text
以确定性方式修复
```
### 路径
每个 `files_touched` 路径必须是:
```text
相对路径
POSIX 风格
位于 workspace 之内
不包含 ..
```
---
## 回退 Planner
如果 LLM 规划失败,则生成大致覆盖以下内容的确定性任务:
```text
project/schema setup
auth if required
core entity CRUD
API/pages
tests/verification
```
对于小型应用:
```text
5–12 个任务
```
---
## DagEngine
必需行为:
```python
get_ready()
mark(task_id, status)
is_done()
blocked_propagation()
topological_order()
```
任务处于 READY 当且仅当:
```text
status == PENDING
且
所有依赖 == COMPLETED
```
如果依赖变为:
```text
FAILED
TIMED_OUT
```
则依赖它的任务变为:
```text
BLOCKED
```
循环必须显式抛出错误。
---
## PlanValidator
检测:
```text
重复的 task ID
未知的依赖
循环
孤儿 requirement
没有 verification 的 task
没有文件的 task
没有 requirement 的 task
无效路径
```
重叠文件:
```text
在 V1 中仅作为 WARNING
```
---
## 验收
具有四个 requirement 的 Todo spec:
```text
→ 5–8 个任务
```
测试:
```text
所有 requirement 被覆盖
依赖顺序有效
循环被拒绝
TASK-001 失败会阻塞依赖它的任务
tasks.json 已持久化
plan_created 检查点已持久化
```
## 禁止
不进行 Builder 执行。
无并发。
---
# M4 — BUILDER + 沙箱受限的文件工具
## 目标
将一个 Task 转换为真实文件。
## 文件
```text
src/harness/agents/builder.py
src/harness/tools/files.py
tests/test_builder.py
```
---
## Builder 上下文
仅提供:
```text
当前 Task
Task 引用的 requirement
简短的 spec 摘要
依赖的 verification 结果
允许的文件
verification 命令
```
不要转储完整的 run 历史。
输入示例:
```python
task
requirements
spec_summary = {
"app_type": ...,
"stack": ...,
"data_model": ...
}
dependency_results
allowed_files
verification
```
---
## Builder 输出
LLM 必须生成:
```json
{
"relative/path.py": "完整文件内容"
}
```
无散文。
无 Markdown 代码围栏。
---
## 写入限制
Builder 只能写入:
```text
task.files_touched
```
任何尝试写入允许列表之外的文件:
```text
PermissionError
+
事件日志
+
task 失败
+
CONFIG_ERROR
```
Builder 只能使用沙箱化的:
```text
read_file
write_file
list_files
```
Builder 不得执行子进程。
---
## 确定性回退
如果 LLM 输出无法解析,则为当前 task 使用确定性实现。
回退必须遵守相同的 `files_touched` 允许列表。
因此 Planner 回退必须确保任何确定性脚手架文件都被显式列在相关 task 中。
生成的参考应用可以包括:
```text
src/main.py
src/models.py
requirements.txt
tests/test_health.py
```
不要在当前 Task 声明的文件集合之外创建文件。
---
## 验收
测试:
```text
允许的文件写入成功
写入允许列表之外失败
../ 转义失败
MockProvider 创建确定性输出
在 task 之后创建检查点
```
里程碑之后:
```bash
pytest -q
```
必须通过。
## 禁止
Builder 内不执行 verification。
不进行修复。
---
# M5 — 真实 verification + 失败分类
## 目标
执行真实的 verification 命令并持久化结构化证据。
## 文件
```text
src/harness/verification/verifier.py
src/harness/verification/classifier.py
tests/test_verifier.py
tests/test_classifier.py
```
---
## Verifier
实现:
```python
verify_task(
task: Task,
workspace: Path
) -> list[VerificationResult]
```
对于每个 verification 命令:
```text
shlex.split(command)
→ LocalSandbox.execute(...)
```
缺失时的默认值:
```bash
pytest -q
```
捕获:
```text
exit_code
stdout[-4000:]
stderr[-4000:]
duration_ms
```
PASS:
```text
exit_code == 0
```
FAIL:
```text
exit_code != 0
```
超时:
```text
Task status = TIMED_OUT
FailureType = TIMEOUT
```
仅靠静态检查永远不能算作 verification。
---
## Workspace 校验
提供辅助函数:
```python
verify_workspace(workspace)
```
它可以包含与实际存在的文件相匹配的项目级检查。
不要在离线 harness 单元测试中盲目要求外部网络安装。
---
## 失败分类器优先级
分类必须是确定性的。
使用以下优先级:
```text
1. TIMEOUT
2. ENVIRONMENT_ERROR
3. DEPENDENCY_ERROR
4. TYPE_ERROR
5. CODE_ERROR
6. CONFIG_ERROR
7. TEST_FAILURE
8. UNKNOWN
```
优先级很重要。
例如,包含 Python `SyntaxError` 的 pytest 会话必须归类为:
```text
CODE_ERROR
```
而不仅仅是 `TEST_FAILURE`。
### TIMEOUT
模式:
```text
timed out
TimeoutExpired
duration >= configured timeout
```
### ENVIRONMENT_ERROR
模式:
```text
EAI_AGAIN
ENOTFOUND
registry unavailable
Network is unreachable
HTTP 503
Could not fetch
```
### DEPENDENCY_ERROR
模式:
```text
ModuleNotFoundError
ImportError
No module named
Could not resolve dependency
npm ERR 404
```
### TYPE_ERROR
模式:
```text
mypy
Pydantic ValidationError
TypeError ... expected
TS2322
Property ... does not exist
```
### CODE_ERROR
模式:
```text
SyntaxError
IndentationError
NameError
ReferenceError
```
### CONFIG_ERROR
模式:
```text
missing configuration
missing pyproject
requirements file not found
port already in use
invalid path configuration
```
### TEST_FAILURE
模式:
```text
AssertionError
FAILED
1 failed
FAIL tests/
```
仅在排除更高优先级类别之后使用。
---
## 验收
测试:
```text
SyntaxError → CODE_ERROR
ModuleNotFoundError → DEPENDENCY_ERROR
AssertionError → TEST_FAILURE
network unavailable → ENVIRONMENT_ERROR
timeout → TIMEOUT
可工作的脚手架 → PASS
```
持久化 verification 证据。
## 禁止
尚不进行自动修复。
---
# M6 — 修复循环 + 循环检测
## 目标
实现:
```text
FAIL
→ repair
→ verify
```
带有有界重试。
## 文件
```text
src/harness/orchestration/repair.py
src/harness/agents/repair_agent.py
tests/test_repair.py
```
---
## 循环签名
```python
sha256(
command
+ exit_code
+ normalize(stderr[-2000:])
)
```
归一化:
```text
小写
strip changing timestamps
strip volatile numeric values
归一化路径
折叠空白
```
追踪:
```python
seen[signature] += 1
```
如果相同的归一化失败签名出现三次:
```text
ESCALATE
FAILED
阻塞 dependents
```
总修复尝试次数绝不得超过:
```text
3
```
---
## 修复策略
### ENVIRONMENT_ERROR
```text
不要重写应用代码。
重试一次。
如果仍然失败 → FAILED。
```
### DEPENDENCY_ERROR
仅修复已被 Task 允许或被显式列为 verification 提示的依赖/配置文件。
### TYPE_ERROR
仅修补相关代码。
### CODE_ERROR
仅修补相关代码。
### TEST_FAILURE
仅在有 requirement 证据支撑时修补实现或测试。
不要简单地弱化测试以获得 PASS。
### CONFIG_ERROR
仅修补配置文件。
### TIMEOUT
允许一次有界调整/重试。
不要创建无界超时。
---
## RepairAgent 上下文
提供:
```text
Task
相关的 requirement 片段
失败的 VerificationResult
FailureType
允许的文件
当前相关文件的内容
```
在以下位置截断大型源码上下文:
```text
每次修复上下文 8000 字符
```
输出:
```json
{
"relative/path": "完整修正后的内容"
}
```
---
## 验收
测试:
```text
修复 SyntaxError → 在 <=3 次尝试内 PASS
同一失败出现 3 次 → ESCALATE
dependents 变为 BLOCKED
ENVIRONMENT_ERROR 不会修改代码
允许列表之外的文件无法被修复
```
---
# M7 — 可追溯性矩阵
## 目标
构建机械证据:
```text
Requirement
→ Tasks
→ Files
→ Verification
→ Result
```
## 文件
```text
src/harness/trace/matrix.py
tests/test_trace.py
```
---
## 矩阵结构
对于每个 requirement:
```json
{
"REQ-001": {
"tasks": [],
"files": [],
"tests": [],
"evidence": [],
"status": "PASS|FAIL",
"missing": []
}
}
```
计算:
```text
tasks
= 引用该 REQ 的任务
files
= 所有 task.files_touched 的并集
tests
= 所有 task.verification 的并集
evidence
= 已存在的文件
+ 成功的 verification 命令
```
仅当:
```text
>=1 个预期的实现文件存在
且
>=1 个相关的 verification 结果为 PASS
```
才为 PASS。
没有证据:
```text
FAIL
```
散文不能替代证据。
---
## 验收
Todo 参考运行:
```text
4/4 个 requirement 被追溯
```
删除一个实现文件:
```text
关联的 requirement 变为 FAIL
```
---
# M8 — REQUIREMENT 审查
## 目标
执行最终的 requirement 级别审计。
## 文件
```text
src/harness/agents/reviewer.py
tests/test_review.py
```
---
## ReviewAgent
默认权威:
```text
基于规则的证据
```
LLM 审查是可选的,仅用于解释说明。
LLM 可以:
```text
添加理由
总结证据
指出问题
```
LLM 不得:
```text
将基于证据的 FAIL 转为 PASS
```
---
## 输出
持久化:
```text
runs/<run_id>/review.json
```
结构:
```json
{
"requirements": [
{
"id": "REQ-001",
"status": "PASS",
"evidence": [],
"missing": []
}
],
"overall_status": "PASS"
}
```
仅当以下条件全部满足时整体才为 PASS:
```text
每个 requirement == PASS
```
---
## 验收
测试:
```text
完整证据 → PASS
缺失实现文件 → FAIL
缺失成功的 verification → FAIL
LLM 无法覆盖 FAIL
review JSON 通过校验
```
---
# M9 — 检查点 + 崩溃恢复
## 目标在不重复已完成工作的前提下,恢复被中断的运行。
## 文件
```text
src/harness/state/checkpoints.py
src/harness/orchestration/pipeline.py
tests/test_recovery.py
```
---
## 必需的检查点事件
```text
spec_created
plan_created
task_started
task_completed
verification_completed
repair_started
review_completed
```
文件名约定:
```text
checkpoints/<sequence>-<event>-<optional-task>.json
```
示例:
```text
001-spec_created.json
002-plan_created.json
003-task_started-TASK-001.json
004-task_completed-TASK-001.json
```
---
## 恢复算法
```text
load state.json
↓
validate state
↓
load latest checkpoint state
↓
reconstruct task statuses
↓
keep COMPLETED
keep FAILED
keep BLOCKED
convert interrupted RUNNING → PENDING
convert READY → PENDING
↓
continue unfinished pipeline
```
已完成的任务绝对不能再次执行。
在合适的位置使用文件哈希,以证明已完成的输出在恢复过程中没有被重写。
---
## 损坏处理
损坏:
```text
state.json
checkpoint JSON
```
必须产生清晰明确的错误。
绝不静默地从零重新开始运行。
---
## 验收
在以下节点之后模拟崩溃:
```text
TASK-002
```
恢复时必须:
```text
finish remaining tasks
not rerun TASK-001
not alter completed file hashes
```
测试检查点的顺序。
---
# M10 — 运行时验证
## 目标
证明生成的应用确实能够启动并响应请求。
仅靠静态测试是不够的。
## 文件
```text
src/harness/verification/runtime.py
src/harness/verification/browser.py
tests/test_runtime.py
```
---
## RuntimeVerifier
### 入口检测
至少识别:
```text
src/main.py:app
app.py:app
package.json
```
未识别到入口:
```text
FAIL
CONFIG_ERROR
```
### 启动
FastAPI:
```bash
python -m uvicorn src.main:app --port <free_port>
```
Node 后备方案:
```bash
npm run dev -- --port <free_port>
```
使用操作系统分配的/空闲的本地端口。
使用以下方式启动进程:
```python
subprocess.Popen
```
配合:
```text
cwd jailed inside workspace
shell=False
```
验证层可以拥有进程执行权;应用构建代理不得拥有。
### 启动超时
```text
15 秒
```
### 检查项
验证:
```text
process remains alive
TCP port accepts connection
GET /health OR / returns 2xx
GET /docs or /api/health when available
SQLite DB can be opened when expected
```
### 清理
始终终止派生的进程。
使用 `finally` 进行清理。
绝不留存孤立的开发服务器。
### 结果
返回结构化的:
```json
{
"status": "PASS",
"checks": [
{
"name": "health",
"ok": true,
"detail": "HTTP 200"
}
],
"evidence": []
}
```
捕获有用的日志片段。
---
## Browser V1 桩
仅实现:
```python
def verify_acceptance(...):
raise NotImplementedError(
"Browser verification deferred post-V1"
)
```
测试浏览器验证器保持显式延后。
禁止安装 Playwright 或 Selenium。
---
## 验收
参考应用:
```text
starts
port opens
health endpoint returns 200
runtime verifier PASS
```
启动失败:
```text
FAIL
diagnostics captured
repair hint available
```
---
# M11 — CLI 与基准测试
## 目标
通过确定性的命令行界面暴露整个 harness,并提供快速回归基准。
## 文件
```text
src/harness/cli.py
src/harness/orchestration/pipeline.py
src/harness/benchmarks.py
tests/test_cli.py
tests/test_benchmarks.py
```
添加控制台入口:
```toml
[project.scripts]
builder = "harness.cli:main"
```
使用:
```text
argparse only
```
不依赖 Click/Typer。
---
## CLI 命令
### New 运行
```bash
builder new "Build a Todo app"
```
等价的模块形式:
```bash
python -m harness.cli new "Build a Todo app"
```
它必须执行完整的流水线。
### Resume
```bash
builder resume <run_id>
```
### Logs
```bash
builder logs <run_id>
```
以可读形式打印或 tail 该运行的结构化事件日志。
### Benchmark
```bash
builder bench --quick
```
---
## 进度输出
`builder new` 必须输出五个面向用户的高级阶段:
```text
[1/5] SPEC
[2/5] PLAN
[3/5] BUILD
[4/5] VERIFY
[5/5] REVIEW
```
详细的内部里程碑仍属于 M1–M12;五阶段 CLI 视图仅用于呈现。
成功时:
```text
BUILD COMPLETE
```
失败时:
```text
BUILD FAILED
```
并返回非零退出状态。
---
## 快速基准
`builder bench --quick` 运行确定性的简单 Todo 场景。
它必须至少验证:
```text
spec generated
plan generated
files written
verification executed
runtime checked
review produced
required artifacts exist
```
返回:
```text
0 → PASS
non-zero → FAIL
```
---
## 验收
必须通过:
```bash
builder new "Build a Todo app"
builder bench --quick
```
离线 LLM 回退必须仍然可用。
验证:
```text
all required artifacts exist
five-stage output matches expected format
events.log contains required keys
quick benchmark passes
```
## 禁止
无 Web UI。
无生产 Docker 环境。
---
# M12 — 最终关卡
## 目标
在宣告完成之前证明 V1 的可靠性。
所有关卡都是强制性的。
---
## 关卡 1 — 纵向切片
运行:
```bash
builder new "Build a Simple Todo App with add/list/complete"
```
预期的流水线:
```text
SPEC
→ >=3 REQs
→ PLAN
→ >=3 tasks
→ BUILD
→ real files
→ VERIFY
→ pytest PASS
→ RUNTIME
→ PASS
→ REVIEW
→ PASS
```
在以下位置保存一个稳定的演示运行:
```text
runs/demo_todo/
```
如果任何阶段失败:
```text
fix the harness
rerun
do not proceed
```
---
## 关卡 2 — 故障注入
注入:
```python
SyntaxError
```
到:
```text
workspace/src/main.py
```
harness 必须:
```text
DETECT
→ FAIL
CLASSIFY
→ CODE_ERROR
LOCALIZE
→ TASK-ID
CAPTURE
→ diagnostics
REPAIR
→ relevant file only
REVERIFY
→ PASS
```
然后使用 no-op 修复实现反复模拟相同的故障。
预期:
```text
same signature x3
→ LOOP DETECTED
→ ESCALATE
→ task FAILED
→ dependents BLOCKED
```
---
## 关卡 3 — V1 能力检查清单
所有项都必须为 ✓:
```text
[ ] valid spec generated
[ ] spec validated
[ ] valid DAG generated
[ ] sequential execution
[ ] real files created
[ ] real verification executed
[ ] failures localized
[ ] failures classified
[ ] failures repaired
[ ] repair bounded <=3
[ ] loop detection works
[ ] checkpoints written
[ ] crash resume works
[ ] completed tasks not rerun
[ ] traceability matrix generated
[ ] requirement review generated
[ ] runtime verified
[ ] final working project retained
```
---
## 关卡 4 — 文档
README 必须记录:
```text
quickstart
builder new
builder resume
builder logs
builder bench --quick
architecture
evidence principle
failure handling
checkpoint recovery
```
包含一张 ASCII 架构图。
创建:
```text
examples/todo_run/
├── spec.json
├── tasks.json
├── verification.json
└── review.json
```
---
## 关卡 5 — 完整测试套件
运行:
```bash
pytest -q
builder bench --quick
```
两者都必须通过。
---
## V1 禁用特性审计
断言实现中不包含以下功能实现:
```text
docker/
web_ui/
parallel workers
parallel DAG scheduler
Playwright
Selenium
PostgreSQL backend
web research
```
浏览器验证桩是被允许的。
---
# 最终完成定义
仅当以下全部满足时,V1 才算完成:
```text
M1 PASS
M2 PASS
M3 PASS
M4 PASS
M5 PASS
M6 PASS
M7 PASS
M8 PASS
M9 PASS
M10 PASS
M11 PASS
M12 PASS
```
每个 bug 修复都必须包含回归测试。
每个新模块都必须有测试。
保持源文件聚焦。
优先采用:
```text
<400 行/文件
```
必要时拆分更大的文件。
绝不存储:
```text
API keys
secrets
absolute host-specific paths
```
绝不删除历史检查点以掩盖失败。
---
# 最终运行摘要格式
在每次运行结束时,按需求层级打印一份摘要。
示例:
```text
REQ-001
Implemented: YES
Tested: YES
Runtime: YES
Evidence:
- src/main.py
- pytest -q → exit_code 0
Status: PASS
REQ-002
Implemented: YES
Tested: NO
Runtime: NO
Missing:
- successful verification result
Status: FAIL
```
最终状态:
```text
PASS
```
仅在每条需求都拥有证据支撑的 PASS 状态时才会出现。
绝不将:
```text
"AI says finished"
```
作为证据使用。
---
# 执行命令
立即开始。
实现:
```text
M1
```
运行其测试。
若全绿,则继续:
```text
M2
```
按顺序依次推进至 M12。
不要提问。
不要在中间里程碑处停止。
不要跳过失败关卡。
在最终关卡全绿之前不要宣告 V1 完成。相关资源
按类型、任务、场景与标签加权推荐
Superset Mobile
React · Native · 移动开发 · 开源工具 · 调试 · Expo
同时运行多个代理,无需上下文切换开销 - 将每个任务隔离在独立的沙箱中,避免代理之间相互干扰 - 在一个位置监控所有代理,并在需要关注时收到通知 - 使用内置的差异查看器和编辑器快速查看更改 减少等待,提高交付效率。
Jev
AI代理 · 类型安全 · 开发工具 · 工作流 · SDK
Jev 是 TypeSafe AI 的 System One 前沿模型:输入非结构化状态,输出类型化的概率决策。Jev 不会生成文本,而是返回 Choice、Score 和 Noul 三种答案,并附带经过校准的概率,供您的代码执行。
Mastra Factory
AI代理 · 工作流 · 开源框架 · TypeScript · LLM编排
Mastra 由 Gatsby 团队开发,是一个用于构建 AI 应用和代理的框架,它支持工作流、内存管理、流式处理、评估、追踪以及 Studio(一个用于开发和测试的交互式 UI)。
BrionetAI
AI代理 · 企业自动化 · 多模型编排 · 私有化部署 · 工作流引擎
将问题转化为互动式学习体验。你可以获取动画讲解、多语言语音旁白、AI 生成的模拟考试、自动生成的闪卡,以及个性化的分步学习路径。
Tuanjie AI
AI编程 · 代码生成 · 开发者工具 · 智能问答
AI赋能代码生成、调试、重构,智能代码索引与深度分析,支持VS Code/Visual Studio/JetBrains/Unity Tools,让游戏开发效率翻倍
Harden
AI代理 · 安全加固 · 完整性 · 开发工具 · 代码审查
Harden AIF 是一款免费的本地 AI 编码代理安全工具。它采用后训练模型,利用您的请求和会话上下文,在工具调用运行前对其进行检查。在关键的代理安全基准测试中,它超越了前沿模型,同时将您的代码库和工具输出保留在您的本地计算机上。