Orchestrata Ultimate › Plans › harness-iteration-0
Harness Iteration 0: Automated Porting Pipeline
Source: plans/harness-iteration-0.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-04-11 · 859 lines.
Prose pending.
Plan text
Harness Iteration 0: Automated Porting Pipeline
Reviewed: 4 rounds of Sonnet subagent review. 71 gaps found, all addressed.
Review History
Round 1 — 3 Sonnet agents (Porter gaps, Testing gaps, Workflow gaps)
| # | Gap | Severity | Fix |
|---|---|---|---|
| P1 | Symbol rename table missing from prompt | HIGH | Added Table 1 (20 entries) injected in every prompt |
| P2 | No forward-type/circular dependency resolution guide | HIGH | Added Table 6 (TYPE_CHECKING vs lazy vs conditional criteria) |
| P3 | @traces decorator keep/translate instruction missing | MEDIUM | Added Rule 1 in Table 5 |
| P4 | Exception hierarchy mapping missing | MEDIUM | Added Rule 3 in Table 5 |
| P5 | Only 5 env vars, 24 exist | HIGH | Added Table 2 (24 keys with defaults) |
| P6 | No knowledge of which modules ported | HIGH | Added available_modules + unavailable_imports in StepContext |
| P7 | Dynamic string imports not flagged per-file | MEDIUM | Added Table 7 (6 files enumerated) + has_dynamic_imports flag |
| P8 | Architecture layer rules not injected | MEDIUM | Added Table 8 (10 layers with forbidden imports) |
| P9 | Pydantic **data super().init rule missing | HIGH | Added Rule 2 in Table 5 |
| P10 | Class-to-file rename mapping missing | MEDIUM | Added Table 4 (volk_registry -> agent_registry) |
| P11 | gRPC skip list not injected | MEDIUM | Added Rule 6 in Table 5 |
| P12 | NEW FILE vs APPEND annotation missing | MEDIUM | Added Table 9 (3 file status types) |
| T1 | Constructor instantiation knowledge missing | HIGH | Added constructor section in Tester prompt |
| T2 | External service dependency map per method | HIGH | Added service_deps heuristic grep |
| T3 | Async mode not confirmed | LOW | Added in Tester system prompt |
| T5 | Side effect inventory missing | HIGH | Replaced with method body injection |
| T6 | Available fixtures incomplete | HIGH | Added full catalog + gap fixtures with creation code |
| T7 | Test file placement/naming missing | MEDIUM | Added TEST FILE NAMING section |
| T9 | ClassVar isolation missing | MEDIUM | Added ClassVar reset note in Tester prompt |
| T11 | Pydantic validator descriptions missing | HIGH | Replaced with validator_source (raw body) |
| T13 | Import paths for types missing | MEDIUM | Added per-type import path section |
| T14 | Dynamic port allocation missing | MEDIUM | Added in Tester system prompt |
| T15 | Prolog fixture status missing | MEDIUM | Added with pytest.importorskip pattern |
| W1 | Truncation threshold too permissive | HIGH | Set 85% for >200 lines, 50% for <=200 |
| W2 | depends_on parsed but never enforced | HIGH | Added dependency check in orchestration loop |
| W3 | Shared file handling (Steps 2+3) | HIGH | Step 2 merges first, Step 3 branches from HEAD |
| W4 | No pre-step shell commands | HIGH | Added pre_commands field + execution in loop |
| W5 | Multi-file steps only read primary file | HIGH | StepContext reads ALL step.files |
| W6 | Source files only read first | HIGH | StepContext reads ALL step.source_files |
| W7 | No git commit before merge | BLOCKER | Added commit() step: git add + commit before merge |
| W8 | Deletion steps have no model | MEDIUM | Added delete step type with safety check |
| W9 | Gate steps don't assert prior steps | HIGH | Added assertion in gate logic |
| W10 | Pytest baseline comparison missing | HIGH | Added baseline recording in harness init |
| W11 | Test count regression unchecked | HIGH | Added collected count comparison |
| W12 | Unported dependency scan missing | MEDIUM | Added available_modules scan in context_builder |
| W13 | No rollback strategy | HIGH | Added rollback CLI command with git revert |
| W14 | String literal imports not checked | HIGH | Added validation check 4 |
| W15 | No diagram/design phase | MEDIUM | Added scaffold step type with diagram2code |
| W17 | Range continues past failures | HIGH | Added --stop-on-failure default |
| W18 | Fixer sees corrupted state | HIGH | Fixer now gets original + errors only |
| W19 | No targeted test runs | MEDIUM | Added validation check 8 (module-specific tests) |
| W20 | Retry keeps stale worktree | HIGH | create() always discards stale first |
Round 2 — 1 Sonnet agent (verification of Round 1 fixes)
| # | Gap | Status | Fix |
|---|---|---|---|
| P2 | TYPE_CHECKING resolution criteria undefined | PARTIAL | Added Table 6 with 3 resolution patterns |
| P7 | 6 dynamic import files not enumerated | PARTIAL | Added Table 7 with all 6 files listed |
| P8 | Layer hierarchy not defined | PARTIAL | Added Table 8 with 10 layers |
| P12 | APPEND vs MODIFY distinction | PARTIAL | Added Table 9 with APPEND_TO_EXISTING |
| W15 | Scaffold workflow not detailed | PARTIAL | Added step 5b in orchestration loop |
| W19 | Targeted test runs not in pipeline | MISSING | Added validation check 8 |
Round 3 — 2 Sonnet agents (hostile execution simulation + prompt placeholder audit)
| # | Gap | Severity | Fix |
|---|---|---|---|
| H1 | init.py import chain breaks ALL verify cmds | BLOCKER | Added PREREQUISITE Step 0 |
| H2 | Gate passes vacuously with 0 tests collected | BLOCKER | harness init records error count, gate checks errors |
| H3 | Step 3 wrong method name + sync/await mismatch | BLOCKER | Added PREREQUISITE table (5 execution plan corrections) |
| H4 | Step 5 references nonexistent _completed_tasks | HIGH | In PREREQUISITE table |
| H5 | Step 9 identifies nonexistent bug | HIGH | In PREREQUISITE table |
| H6 | Step 6 verify missing required field | HIGH | In PREREQUISITE table |
| H7 | Output truncation for 861-line files | HIGH | Set max_tokens=16384 in dispatcher |
| H8 | $ULT shell var not expanded at runtime | HIGH | Expand at parse time |
| H9 | Nested fences confuse applicator regex | MEDIUM | Regex requires .py path suffix |
| H10 | Worktree branches entire workspace (61 dirs) | MEDIUM | git add uses explicit paths, not -A |
| H11 | Step 8 references nonexistent metric variable | LOW | In PREREQUISITE table |
| TP1 | needs_creation pairs: methods_to_add empty | CRITICAL | context_builder branches on readiness |
| TP2 | constructor_side_effects unsourced | MISSING | Replaced with constructor body injection |
| TP3 | side_effects unsourced | MISSING | Replaced with method body injection |
| TP4 | validator_descriptions unsourced | MISSING | Replaced with validator_source (raw body) |
| TP5 | service_deps unsourced | MISSING | Heuristic grep on method body |
| TP6 | orchestrata_test_contents no lookup | MISSING | context_builder path lookup added |
| TP7 | Reviewer prompt completely empty | GAP | Added full Reviewer system + user prompts |
| TP8 | Fixer broken state contamination risk | DESIGN | Removed broken state from Fixer prompt |
Cumulative Stats
| Round | Gaps Found | Fixed | Carried Forward |
|---|---|---|---|
| Round 1 | 48 | 48 | 0 |
| Round 2 | 6 | 6 | 0 |
| Round 3 | 18 | 18 | 0 |
| Total | 72 | 72 | 0 |
PREREQUISITE: Fix Broken Import Chain (Step 0)
BLOCKER: Every python -c "from orchestrata_ultimate.X import ..." fails because:
__init__.pyimportscore.orchestrator->core/tracing/__init__.py->core.traceability_utilswhich DOES NOT EXIST
Before running ANY harness step, fix this:
- Either add a stub
src/orchestrata_ultimate/core/traceability_utils.pythat re-exports fromcore.tracing - Or fix
core/tracing/__init__.pyto not importtraceability_utils - Or change
__init__.pyto lazy-importUltimateOrchestrator
This must be done MANUALLY before harness init. The harness cannot fix it because it's a prerequisite for all verification commands.
Also: pytest currently has ~25 collection errors from the same root cause. harness init must record these as the baseline error count. Gate checks must fail if error count INCREASES, not just if passed count decreases.
PREREQUISITE: Fix Execution Plan Steps with Wrong Information
These steps describe code that doesn't match reality. Fix BEFORE running harness:
| Step | Plan Says | Actual Code | Fix |
|---|---|---|---|
| 3 | self._transition_to_open() |
_record() (local async nested def). Also record_success/record_failure are sync, not async. |
Correct method name. Note sync->async change needed. |
| 5 | self._completed_tasks |
No such attribute. Real structure is self._tasks: dict[str, ThreadPoolTask] |
Fix to reference self._tasks, filter by completed status |
| 6 | Verify: Node(name='test') |
node_type is required (no default). Fails with ValidationError. |
Fix verify: Node(node_type='TestNode', name='test') |
| 8 | metric.observe(duration) |
No metric variable. Use record_request_metrics(..., duration_seconds=duration) |
Fix to use correct API |
| 9 | def stop(): pass stub at lines 304-307 |
No such stub. _stop_system_metrics_collection is intentional no-op for daemon threads. |
Remove or redefine the bug |
These execution plan corrections must be applied to plans/execution-plan.md before the harness runs Steps 1-11.
Goal
A host-side harness that picks steps from execution-plan.md, generates rich context from AST data + diagrams + source code, dispatches to cheap models (DeepSeek/Qwen via OpenRouter), validates with the 20 existing scripts + AST re-comparison, and merges via git worktrees.
Iteration 0 scope: Phase 0 Steps 1-11 (bug fixes). If it works, extend to porting steps.
Architecture
scripts/harness/
__init__.py
__main__.py # python -m scripts.harness
cli.py # Typer CLI: run, status, retry, report, validate, init, rollback
config.py # All paths, models, API keys, static tables
plan_parser.py # Parse execution-plan.md -> Step dataclasses
context_builder.py # Build rich context per step from AST + files + diagrams
worktree.py # Git worktree create/commit/merge/discard
dispatcher.py # OpenRouter API client (httpx async)
applicator.py # Parse model output -> file writes
validator.py # 8-stage validation pipeline
reporter.py # State persistence + dashboard
volks.py # Volk definitions: role, model, static context
prompts/
__init__.py
porter.py # Porter system/user templates
reviewer.py # Reviewer templates
fixer.py # Fixer templates
tester.py # Testing volk templates
Step Types
Each step in the execution plan has a type that determines its workflow:
| Type | Description | Model Dispatch? | Example |
|---|---|---|---|
| bug_fix | Modify existing file to fix a bug | Yes (Porter) | Steps 1-3, 5-10 |
| port | Copy from orchestrata + translate | Yes (Porter) | Steps 12-26, 40-44 |
| scaffold | Generate skeleton from diagram | diagram2code tool | Step 77 |
| shell_only | mkdir, cp, touch - no model needed | No | Steps 39, 48, 63, 79 |
| delete | Remove stub files (with safety check) | No | Steps 59, 96, 185 |
| gate | Validation-only, no file changes | No | Steps 11, 27, 38, 97 |
| skip | Verified as not needed | No | Step 4 |
| multi_file | Port multiple files in one step | Yes (Porter, multi-fence) | Steps 42, 80-82 |
| test_gen | Generate tests for ported code | Yes (Tester) | Steps 96b, 173b |
The parser detects type from step content:
- is_skip: body contains "NOT A BUG" or "Skip this step"
- is_gate: contains the door emoji
- shell_only: actions contain only mkdir, cp, touch, for loops - no model-level code changes
- delete: actions contain "Delete" + file path
- multi_file: step.files has >1 entry
- scaffold: step title contains "Create" + "merge" or "skeleton"
- test_gen: step title contains "Port.*test" or step number ends in "b"
Data Structures
@dataclass
class Step:
number: str # "1", "44b", "96b"
title: str # "Fix wrong import path in logging_config.py"
goal: str # Text after **Goal:**
step_type: str # bug_fix, port, scaffold, shell_only, delete, gate, skip, multi_file, test_gen
files: list[str] # ALL resolved target paths from **File:**/**Destination:**
source_files: list[str] # ALL resolved paths from **Source:** (porting steps)
deleted_files: list[str] # Files to delete (delete steps)
pre_commands: list[str] # Shell commands to run before model dispatch
actions: str # Full text between **Actions:** and **Verify:**
verify_command: str # Content of bash fence after **Verify:**
expected_output: str # Text after **Expect:**
failure_hint: str # Text after **If it fails:**
is_gate: bool
is_skip: bool
phase: str # "Phase 0", "Tier 1"
sub_phase: str # "0.1", "1.1"
depends_on: list[str] # Inferred from sub_phase ordering
@dataclass
class StepContext:
step: Step
target_contents: dict[str, str] # {path: contents} for ALL step.files
source_contents: dict[str, str] # {path: contents} for ALL step.source_files
original_contents: dict[str, str] # Snapshot at worktree creation (for Fixer)
pair: dict | None # The class pair from ast-deep-comparison.json
methods_to_add: list[dict] # method_diff.only_in_orchestrata
methods_to_fix: list[dict] # shared methods with signature mismatches
vars_to_add: list[dict] # var_diff.only_orchestrata
readiness_before: str # stub/partial/needs_creation
available_modules: set[str] # Ultimate modules that exist on disk RIGHT NOW
unavailable_imports: list[str] # Translated imports pointing to non-existent modules
import_resolution: dict[str, str] # For each unavailable: TYPE_CHECKING/lazy/conditional
layer_rules: str # "Layer: X. Cannot import: [Y, Z]"
has_dynamic_imports: bool # Is this file in the 6-file dynamic imports list?
file_status: str # "NEW_FILE" or "MODIFY_EXISTING"
@dataclass
class StepResult:
step_number: str
status: str # passed, failed, skipped, blocked
attempts: int
model_used: str
merged_sha: str | None # For rollback
validation: dict # Per-check pass/fail
tokens_used: dict # {input: N, output: M}
cost_usd: float
ast_delta: dict | None # Methods added, signatures matched
test_coverage: float | None
errors: list[str]
Static Context Tables (injected into EVERY prompt)
Table 1: Symbol Rename Map (20 entries)
VolkRuntime -> AgentRuntime
VolkPool -> AgentPool
VolkRegistry -> AgentRegistry
VolkCoordinator -> AgentCoordinator
BaseVolk -> BaseAgent
BaseEntity -> DomainEntity
AnalystVolk -> AnalystAgent
SeniorDevVolk -> SeniorDevAgent
JuniorVolk -> JuniorAgent
CodeDirectorVolk -> CodeDirectorAgent
QaVolk -> QualityAssuranceAgent
ArchitectVolk -> ArchitectAgent
UXVolk -> UserExperienceAgent
PMVolk -> ProjectManagerAgent
ConciergeVolk -> ConciergeAgent
ComplianceVolk -> ComplianceAgent
OrchestrationKernel -> OrchestrataKernel
Orchestrator -> UltimateOrchestrator
PolicyEngine -> GovernanceEngine
Neo4jClient -> Neo4jGraph
WebSocketGateway -> VizIntWebUI
Plus regex rule: Any I
Table 2: Complete Environment Variable Defaults (24 keys)
REDIS_HOST = "localhost"
REDIS_PORT = "6379"
REDIS_URL = "redis://localhost:6379"
REDIS_DB = "0"
NEO4J_URI = "bolt://localhost:7687"
NEO4J_USERNAME = "neo4j"
NEO4J_PASSWORD = ""
LOG_LEVEL = "INFO"
PROLOG_STACK_LIMIT = "4000000000"
ORCHESTRATA_ENV = "development"
ORCHESTRATA_WORKSPACE = ""
ORCHESTRATA_LLM_PROVIDER = "anthropic"
ORCHESTRATA_TRACE = "false"
ANTHROPIC_API_KEY = ""
DEEPSEEK_API_KEY = ""
OPENROUTER_API_KEY = ""
KIMI_API_KEY = ""
OLLAMA_BASE_URL = "http://localhost:11434"
AIDER_MODEL = ""
PROJECT_ROOT = ""
PROJECT_NAME = ""
GOVERNANCE_STRICT_MODE = "false"
POSTMAN_PORT = "8080"
POSTMAN_MAX_MESSAGE_SIZE = "10000000"
Table 3: Import Translation (top entries + full appendix reference)
from orchestrata.core.interfaces -> from orchestrata_ultimate.core.protocols
from orchestrata.core.traceability -> from orchestrata_ultimate.core.tracing.traceability
from orchestrata.core.traceability_utils -> from orchestrata_ultimate.core.tracing.traceability
from orchestrata.core.infra_config -> from orchestrata_ultimate.core.config.infra
from orchestrata.core.base.entity -> from orchestrata_ultimate.core.domain.domain_entity
from orchestrata.core.base -> from orchestrata_ultimate.core.domain
from orchestrata.core.redis_factory -> from orchestrata_ultimate.core.redis
from orchestrata.core.lru_cache -> from orchestrata_ultimate.core.cache
from orchestrata.core.monitoring -> from orchestrata_ultimate.core.metrics
from orchestrata.volks.<role> -> from orchestrata_ultimate.agents.volks.<role>
from orchestrata.agents.volks.<role> -> from orchestrata_ultimate.agents.volks.<role>
from orchestrata.provider -> from orchestrata_ultimate.providers
from orchestrata.knowledge -> from orchestrata_ultimate.knowledge_graph
from orchestrata.kernel.volk_registry -> from orchestrata_ultimate.kernel.agent_registry
(full 240 translations in ast-deep-comparison.json import_audit section)
Table 4: File-Level Renames
orchestrata.kernel.volk_registry -> orchestrata_ultimate.kernel.agent_registry
(all others keep same filename within translated module path)
Table 5: Rules
1. Preserve @traces(...) decorators exactly as in orchestrata source. Import already translated.
2. Any class inheriting BaseAgent must call super().__init__(**data) (Pydantic keyword propagation).
3. BaseError -> UltimateBaseError. Drop error_code parameter on exception constructors.
4. Factory pattern: Redis, Neo4j, Prolog - always provide in-memory fallback. Guard with try/except ImportError.
5. For TYPE_CHECKING imports of not-yet-ported modules: use from __future__ import annotations + TYPE_CHECKING block.
6. gRPC files (grpc_client.py, grpc_server.py, binary_serializer.py, proto/) are SKIPPED. Wrap gRPC imports in try/except ImportError.
7. No relative imports. Absolute only.
8. No mocking. Real implementations only.
Table 6: Forward Reference Resolution Criteria
When context_builder finds an import pointing to a module that doesn't exist yet on disk:
| Condition | Resolution | Example |
|---|---|---|
| Type used ONLY in annotations (param types, return types) | TYPE_CHECKING |
AgentRegistry in a type hint |
| Type used in runtime code (instantiation, isinstance, method calls) | lazy (import inside the function that uses it) |
from orchestrata_ultimate.kernel.agent_registry import AgentRegistry inside register() |
| Optional service (Redis, Neo4j, Prolog, gRPC) | conditional (try/except ImportError with None fallback) |
try: from neo4j import GraphDatabase except ImportError: GraphDatabase = None |
Table 7: Dynamic String Import Files (6 files)
agents/task_executor.py — 9 string module refs ("orchestrata.volks.<name>.volk")
governance/constitutional.py — 1 __import__() call ("orchestrata.core.enums")
plugin/loader.py — 1 string prefix ("orchestrata.plugins.")
plugin/config.py — 2 string prefixes ("orchestrata.plugins.", "orchestrata_plugin_")
plugin/context.py — 1 f-string logger name
kernel/cli.py — 1 logging name (non-functional but should still be translated)
Table 8: Architecture Layer Hierarchy
| Layer | Modules | Cannot Import From |
|---|---|---|
domain |
core/domain/, exceptions/ | redis, neo4j, httpx, fastapi, anthropic, pyswip, websockets |
core |
core/logging/, core/metrics/, core/tracing/, core/threading/, core/patterns/, core/config/ | agents, kernel, orchestrator, postman, governance, session, gateway, plugin |
protocol |
cxp/, core/protocols.py | agents (runtime), kernel, orchestrator, governance |
providers |
providers/, llm/, drivers/ | kernel, orchestrator, postman, governance, session |
agents |
agents/ (volks only, not infra) | kernel, orchestrator (use TYPE_CHECKING for forward refs) |
agents_infra |
agents/ (runtime, pool, coordinator) | (can import from kernel, orchestrator — these are Tier 2) |
coordination |
kernel/, orchestrator/, postman/, governance/ | gateway, plugin, session (except via interfaces) |
knowledge |
knowledge_graph/ | gateway, plugin |
persistence |
session/, memory/ | gateway, plugin |
surface |
gateway/, plugin/, integrations/ | (can import from anything) |
Table 9: Step File Status Types
| Status | Meaning | Applicator Behavior |
|---|---|---|
NEW_FILE |
File doesn't exist in ultimate yet | Model creates full file. No truncation check. |
MODIFY_EXISTING |
File exists, model replaces entire content | Truncation check applies (85%/50% thresholds). |
APPEND_TO_EXISTING |
File exists, model adds to it (multi-class consolidation) | Model output must include ALL existing content plus additions. Truncation check uses original length as baseline. |
Porter Volk Prompt
System Prompt
You are a Python engineer executing a specific porting step for orchestrata-ultimate.
Python >=3.14. Absolute imports only. No mocking. No relative imports.
OUTPUT FORMAT:
- One ```python <file_path> fence per modified file
- Output the COMPLETE file - never truncate, never use "... rest of file ..."
- If multiple files, output multiple fences
RULES:
{TABLE_5_RULES}
SYMBOL RENAMES (apply to all class references, imports, type annotations):
{TABLE_1_SYMBOL_RENAMES}
ENVIRONMENT VARIABLES (replace os.environ["X"] with os.environ.get("X", default)):
{TABLE_2_ENV_VARS}
User Prompt (bug_fix steps)
## Step {number}: {title}
### Goal
{goal}
### Actions
{actions}
### File: `{file_path}` ({line_count} lines)
```python
{file_contents}
Verification
{verify_command}
Expected: {expected_output}
Output the complete modified file.
#### User Prompt (port steps)
Step {number}: {title}
Goal
{goal}
Actions
{actions}
Destination file: {dest_path} (currently {line_count} lines, status: {file_status})
{target_contents}
Source file: {source_path} ({source_lines} lines)
{source_contents}
{FOR EACH additional source file:}
Source file: {source_path_N}
{source_contents_N}
{END FOR}
AST Analysis - Methods to add:
{FOR EACH method in methods_to_add:}
{"async " if is_async}def {name}({params}) -> {return_type}{decorators} {END FOR}
AST Analysis - Signature mismatches to fix:
{FOR EACH method in methods_to_fix:}
{name}: param diff: {param_diffs}, return: {return_a} vs {return_b} {END FOR}
Import translations for this file:
{FILTERED translations appearing in this source file}
Forward references (modules not yet ported - use TYPE_CHECKING):
{FOR EACH unavailable_import:}
{import_path}-> resolution: {TYPE_CHECKING|lazy|conditional} {END FOR}
Layer rules
{layer_rules}
{IF has_dynamic_imports:}
WARNING: Dynamic string imports
This file contains string-based module references. Translate ALL string literals containing 'orchestrata.' to 'orchestrata_ultimate.' and apply symbol renames. {END IF}
Verification
{verify_command}
Output the complete file(s).
---
### Testing Volk Prompt
#### System Prompt
You are a Python test engineer writing tests for orchestrata-ultimate. Target: 99% line coverage on the module under test. Python >=3.14. pytest with asyncio_mode = "auto" (no @pytest.mark.asyncio needed).
RULES:
- No mocking (no unittest.mock, no MagicMock, no @patch)
- Use monkeypatch.setenv() for ALL environment variable changes
- Use function-scope fixtures only (no module/class scope)
- Use isolation fixture for file/DB/queue resources
- Use test_id fixture for UUID-prefixed resource names
- All tests must pass with pytest -n auto (parallel safe)
- Dynamic port allocation: socket.bind(("", 0)) - never hardcode ports
- Output one ```python <test_file_path> fence with the complete test file
AVAILABLE FIXTURES (from conftest.py):
- isolation - auto-cleanup resource manager
- test_id - UUID string unique per test
- temp_test_dir - temporary Path (auto-cleaned)
- monkeypatch - pytest builtin for env vars
- isolate_logging - saves/restores logging config
- project_root_path - Path to project root (session scope, read-only)
FIXTURES NOT YET IN CONFTEST (create inline if needed):
- redis_client: use pytest.importorskip("redis") + redis.Redis(host=os.environ.get("REDIS_HOST", "localhost"))
- neo4j_session: use pytest.importorskip("neo4j") + GraphDatabase.driver(uri).session()
- prolog_engine: use pytest.importorskip("pyswip") + Prolog() All three: pytest.skip() if service unavailable.
TEST FILE NAMING:
- Place in tests/
/ matching src/ / - Name: test_<source_module_name>.py
- These are authoritative tests, not generated stubs
SYMBOL RENAMES: {TABLE_1}
#### User Prompt
Generate tests for: {module_path}
Implementation ({line_count} lines):
{implemented_code}
Class: {class_name}
SOURCE for these fields: context_builder derives them from AST + source code reading:
class_name: from AST pairultimate_nameor from StepContext.pairrequired_fields/optional_fields: from ASTclass_vars+parameterson__init__. Required = no default. Optional = has default.validator_source: context_builder reads the BODY of each@field_validator/@validatormethod from source (AST gives decorator name, then we extract the function body text). Shows raw validator code, not a description.constructor_body: context_builder extracts the__init__method body from source. The model reads it to infer side effects (network calls, thread spawning, global mutations). We don't guess side effects — we show the code.class_vars: from ASTclass_varslist. Flag anyClassVar[dict]orClassVar[list]as "accumulates across tests — reset in fixture".service_deps: context_builder runs heuristic grep on method body: containsredis-> redis, containsneo4j-> neo4j, containspyswip/Prolog-> prolog, containscall_llm/httpx/anthropic-> llm. If none -> none. If multiple -> multi.
Constructor:
- Required params: {required_fields}
- Optional params with defaults: {optional_fields}
- Validators (source code): {validator_source}
- Constructor body (read this to understand side effects):
{constructor_body}
- ClassVar state that accumulates: {class_vars} <- RESET between tests
Methods to test: {FOR EACH method:}
{"async " if is_async}def {name}({params}) -> {return_type}Abstract: {is_abstract} | Decorators: {decorators} Service deps: {service_deps} (none|redis|neo4j|prolog|llm|multi) — heuristic from method body grep Method body ({body_line_count} lines):
{method_body}
{END FOR}
Import paths for types in signatures:
{FOR EACH type:}
{TypeName}->from orchestrata_ultimate.{module} import {TypeName}{END FOR}
Reference tests from orchestrata:
SOURCE: context_builder looks up orchestrata/tests/<matching_dir>/test_<module_name>.py. If no match found, this section is "No reference tests available — generate from scratch."
{orchestrata_test_contents_or_empty}
Coverage target: 99% line coverage on {module_path}
Output the complete test file.
---
### Fixer Volk Prompt
#### System Prompt
Same as Porter system prompt, plus:
You are fixing a failed porting step. You receive the ORIGINAL file and the validation errors. Apply the step's required changes to the ORIGINAL file while avoiding the errors. Output the complete corrected file in a ```python fence.
#### User Prompt
Fixing Step {number}: {title}
Original file (the ONLY starting point — apply changes to THIS):
{original_contents}
What the step requires:
{actions}
Validation errors from the previous attempt (avoid these mistakes):
{error_output}
Apply the step's changes to the original file. Avoid the listed errors. Output the complete corrected file.
**Design decision:** The broken state is NOT included. Including it causes model contamination — the model mixes correct and broken code unpredictably. Instead, the Fixer gets: original (clean starting point) + step actions (what to do) + error output (what to avoid). This produces cleaner results.
---
### Reviewer Volk Prompt
#### System Prompt
You are reviewing a code diff from an automated porting step. Output ONLY one of:
- "APPROVED" — if the diff correctly implements the step
- "ISSUES:\n" followed by one issue per line: FILE:LINE DESCRIPTION
Check for:
- Remaining
from orchestrata.imports (must be orchestrata_ultimate) - Bare os.environ["X"] reads (must use .get())
- Missed symbol renames (Volk->Agent, BaseEntity->DomainEntity, etc.)
- Relative imports (must be absolute)
- Mocking (unittest.mock, MagicMock, @patch)
- Truncated methods (pass/... where implementation should be)
- Correct base class (BaseAgent subclasses use Pydantic, not dataclass)
#### User Prompt
Review Step {number}: {title}
Diff:
{git_diff}
AST expectations:
- Methods that should exist: {expected_methods}
- Readiness target: {readiness_before} -> mostly_complete
Verdict?
**When used:** Optionally after Porter pass + validation pass, before merge. Adds confidence but costs one extra API call. Configurable via `config.run_reviewer = True/False`.
---
### Context Builder (context_builder.py)
Assembles StepContext from multiple sources. Runs BEFORE model dispatch.
Key operations:
1. Read ALL target files from worktree (not repo root)
2. Read ALL source files from orchestrata
3. Snapshot originals at worktree creation time (stored in .harness/step-N/original/)
4. Find AST pair from ast-deep-comparison.json by matching class names in step title/files
5. **For `needs_creation` pairs** (ultimate_exists=false): populate `methods_to_add` from `pair['orchestrata_methods']` (ALL methods), not from `method_diff.only_in_orchestrata` (which doesn't exist for these pairs). Set `readiness_before = "needs_creation"` and include it in the prompt so the model knows it's creating from scratch.
6. Scan disk for available_modules (which ultimate modules exist NOW)
6. For each source import, translate and check if dest module exists -> unavailable list
7. Determine layer rules from file path
8. Check if file is in the 6-file dynamic imports list
9. Determine NEW_FILE vs MODIFY_EXISTING
---
### Worktree Manager
Key operations:
- create(): Always fresh. Removes stale worktree/branch from previous attempt first.
- commit(): `git add orchestrata-ultimate/src orchestrata-ultimate/tests` (NOT -A — repo root is workspace with 61 subdirs). Then `git commit` in worktree. MUST be called before merge.
- merge(): git merge --no-ff, returns SHA. Then discards worktree.
- discard(): Force remove worktree + delete branch.
- rollback(sha): git revert <sha> on main.
**CRITICAL:** The git root is `/home/mohamed/workspace` (not orchestrata-ultimate). Worktrees branch the ENTIRE workspace. `git add -A` would capture changes from all 61 projects. Always use explicit paths: `git add orchestrata-ultimate/src/ orchestrata-ultimate/tests/ orchestrata-ultimate/plans/`.
---
### Validation Pipeline (8 checks)
| # | Check | Severity | Stop? |
|---|-------|----------|-------|
| 1 | Syntax (py_compile) | CRITICAL | Yes |
| 2 | Step verify command | CRITICAL | Yes |
| 3 | Import grep (from orchestrata. without _ultimate) | ERROR | No |
| 4 | String literal imports ("orchestrata." in non-import lines) | ERROR | No |
| 5 | Bare os.environ["X"] grep | ERROR | No |
| 6 | Architecture checker | WARNING | No |
| 7 | AST signature comparison (port steps only) | ERROR | No |
| 8 | Targeted module tests (tests/<module>/test_<file>.py) | CRITICAL | Yes |
| 9 | Full pytest (compare against baseline, new failures only) | CRITICAL | Yes |
Check 8 (targeted tests): Auto-detected from file path. If step modifies `src/orchestrata_ultimate/core/logging/logging_config.py`, run `pytest tests/test_logging.py tests/core/ -x -q`. Fast (~2s). Catches regressions in the specific module. Runs BEFORE the full suite.
Check 9 (full pytest): Baseline recorded by `harness init` using `--continue-on-collection-errors`. Baseline records: `collected`, `passed`, `failed`, `errors` (collection errors). Pre-existing failures AND pre-existing collection errors are ignored. Only NEW failures or NEW errors are CRITICAL. Test count regression: if collected < baseline_collected, flag as ERROR (model deleted a test). Error count regression: if errors > baseline_errors, flag as ERROR.
**Dispatcher max_tokens:** Set `max_tokens=16384` in all OpenRouter requests. DeepSeek V3 default is 8192 which truncates files >600 lines. thread_pool.py (861 lines) needs ~7.6K output tokens — 8192 is too tight. 16384 gives safe headroom.
---
### Orchestration Loop
For each step in range:
1. Skip check (is_skip -> mark skipped, continue)
2. Dependency check (all depends_on must be passed/skipped, else mark blocked, stop if --stop-on-failure)
3. Gate check (no model, just run validation against repo root, assert all prior steps passed)
4. Shell-only (run pre_commands, mark passed)
5. Delete (safety check imports, git rm, mark passed)
5b. **Scaffold** (design phase for scaffold step_type):
a. Generate destination class diagram from AST pair data (Mermaid)
b. Run `diagram_generator.py diagram2code --diagram <mermaid> --output-dir <worktree>`
c. The skeleton has correct signatures, empty bodies
d. Then continue to step 8 (model dispatch) — Porter fills in bodies from orchestrata source
e. This is the DESIGN -> SCAFFOLD -> IMPLEMENT flow
6. Create worktree (fresh, discards stale)
7. Run pre_commands in worktree
8. Build StepContext from AST + files + disk state
9. Attempt loop (max 3):
- Attempt 1: Porter (DeepSeek)
- Attempt 2: Fixer (Sonnet) with original + broken + errors
- Attempt 3: Porter fallback (Qwen)
- Each: dispatch -> apply -> validate -> pass or collect errors
10. If passed: commit in worktree, merge to main, record SHA, discard worktree
11. If failed: preserve worktree, record errors, stop if --stop-on-failure
---
### Applicator
Parses model output fences:
- Regex: `` ```python\s+(\S+\.py)\n(.*?)``` `` (DOTALL) — fence info string MUST end in `.py` to be treated as a file path. This prevents matching code examples inside model explanatory text (e.g., `` ```python\n# Before:\n... `` which has no file path).
- Fallback: if one file and no `.py` path in fence, use step's primary file
- Reject truncated: check for "... rest of" markers
- Reject too-short: >200 line files must be >=85% of original, <=200 line files >=50%
- Write to worktree path, creating parent dirs as needed
---
### State Tracking (.harness/state.json)
Atomic writes (write to .tmp then rename).
Contains:
- baseline: pytest counts recorded at init
- steps: per-step status, attempts, model, merged_sha, validation, tokens, cost, errors
- summary: total/passed/failed/skipped/blocked counts, total cost
---
### CLI Commands
```bash
python -m scripts.harness init # Record pytest baseline
python -m scripts.harness run --step 1 # Run single step
python -m scripts.harness run --steps 1-11 # Run range (stops on failure)
python -m scripts.harness run --steps 1-11 --no-stop # Continue past failures
python -m scripts.harness status # Show step statuses
python -m scripts.harness retry --step 5 # Retry (fresh worktree)
python -m scripts.harness retry --step 5 --model qwen/qwen-2.5-coder-32b-instruct
python -m scripts.harness rollback --step 3 # git revert merged SHA
python -m scripts.harness validate --step 1 # Validation only, no model
python -m scripts.harness report # Full dashboard
python -m scripts.harness coverage # Re-run AST comparison, show delta
Iteration 0: Steps 1-11
| Step | Type | File (lines) | Tokens | Notes |
|---|---|---|---|---|
| 1 | bug_fix | logging_config.py (251) | ~2.5K | Import path fix |
| 2 | bug_fix | error_handling.py (728) | ~7K | 7x iscoroutinefunction |
| 3 | bug_fix | error_handling.py (728) | ~7K | Await circuit breaker. Reads Step 2 output. |
| 4 | skip | - | 0 | Not a bug |
| 5 | bug_fix | thread_pool.py (861) | ~8K | Memory leak cleanup |
| 6 | bug_fix | node.py (110) | ~1.5K | Pydantic v1->v2 |
| 7 | bug_fix | domain_entity.py (88) | ~1.2K | .dict()->.model_dump() |
| 8 | bug_fix | decorators.py (314) | ~3.5K | Record duration |
| 9 | bug_fix | metrics_config.py (424) | ~4K | Implement stop() |
| 10 | bug_fix | audit.py (445) | ~5K | Real after_state |
| 11 | gate | - | 0 | Full pytest run |
Steps 2->3 share error_handling.py. Step 2 merges first. Step 3 worktree branches from HEAD (includes Step 2). No conflict.
Cost: ~$0.01 | Time: ~5 minutes
Success Criteria
- Steps 1-3, 5-10: pass all 8 validation checks
- Step 4: skipped
- Step 11: gate passes (pytest count >= baseline)
- .harness/state.json: 8 passed, 1 skipped, 1 gate
- No worktrees left behind
- git log shows 8 merge commits
File List for Builder
| File | LOC | Key |
|---|---|---|
| init.py | 5 | Package |
| main.py | 5 | Entry |
| config.py | 120 | Config, env, static tables |
| plan_parser.py | 250 | Regex parser, Step, variable expansion, type detection |
| context_builder.py | 200 | StepContext from AST + files + disk |
| worktree.py | 100 | Create/commit/merge/discard |
| dispatcher.py | 130 | httpx async, OpenRouter, tokens, errors |
| applicator.py | 120 | Fence parsing, truncation detect, write |
| validator.py | 250 | 8-check pipeline, baseline, AST sig |
| reporter.py | 150 | State persistence, dashboard |
| volks.py | 50 | Porter/Reviewer/Fixer/Tester |
| prompts/init.py | 5 | - |
| prompts/porter.py | 120 | System + user with all context slots |
| prompts/reviewer.py | 60 | Review templates |
| prompts/fixer.py | 80 | Original + broken + errors |
| prompts/tester.py | 120 | Fixtures, coverage target |
| cli.py | 250 | init/run/status/retry/rollback/validate/report/coverage |
| Total | ~2,015 |