Orchestrata Ultimate / Specs / 029-codedirector-volk
029-codedirector-volk: CodeDirector Volk (U:Cd)
U:Cd is the CodeDirector volk — a thin senior-engineer coordinator that bridges architecture design to working code. It receives implementation requests from U:Ar (Architect), generates deterministic project skeletons, decides whether to fan out to a parallel junior swarm or route to a single J:Junior, runs a self-review loop against the generated output, and handles QA fix requests delegated back from U:Qa.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/029-codedirector-volk/ |
| Status line in the spec | Implemented |
| Requirement IDs defined | 75 |
With a @traces citation in src/ |
73 (97.3%) |
With a @traces citation in tests/ |
0 (0.0%) |
| Tracked files | 6 |
| RTM page | 029-codedirector-volk |
Reading this spec
U:Cd, the CodeDirector Volk, is a thin senior-engineer coordinator that bridges architecture design to working code. It receives implementation requests from the Architect, generates deterministic project skeletons, decides whether to fan out to a parallel junior swarm or to route to a single J:Junior, runs a self-review loop on the result, and handles fix requests coming back from QA.
The scope is seven user stories: skeleton-first implementation (critical), swarm parallel coding, serial junior delegation, a self-review quality gate and the QA fix loop (high), and fallback when there are no design docs and passthrough of Kimi-style code blocks (medium). Requirement IDs use the REQ-029- prefix.
The key decisions follow the flow in the overview. U:Cd receives an implement CXP packet from U:Ar and extracts the design docs (file tree, API spec, requirements, architecture, class diagram). The skeleton is generated deterministically with no LLM: directory structure, project files and class and method stubs with correct signatures and NotImplementedError bodies. The fan-out decision is gated by Prolog, with a Python fallback: a swarm of parallel juniors when there are at least two source files, otherwise the serial path to one J:Junior. On implementation_complete it runs the self-review loop up to MAX_SELF_REVIEW_CYCLES, and on fix_issues from U:Qa it prepares a fix delegation back to the junior. The reasons given are that skeletons stop juniors re-inventing decided structure, that governance must limit parallelism, and that self-review reduces the need for a full QA cycle for minor defects.
In the code, the package is orchestrata_ultimate/agents/volks/codedirector. The largest tracers are orchestrata_ultimate/agents/volks/codedirector/volk, orchestrata_ultimate/agents/volks/codedirector/implementation, orchestrata_ultimate/agents/volks/codedirector/scaffold/parser, orchestrata_ultimate/agents/volks/codedirector/review and orchestrata_ultimate/agents/volks/codedirector/scaffold/generator. The per-requirement view is on the RTM page.
The spec's status line reads Implemented. It tracks 6 files and defines 75 requirement IDs. The full text follows below.
Measured coverage is 73 of 75 requirements cited by at least one @traces in src/ (97.3%), spread over 6 modules; the module citing the most of them is orchestrata_ultimate/agents/volks/codedirector/volk (28 requirements). In tests/, 0 requirements are cited by a test-side @traces.
Coverage gaps: 2 requirements have no citing symbol. The largest untraced groups are REQ-029-* (2). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (0 against 73).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-029-001 |
no | CodeDirectorVolk sets alias = "U:Cd" and role = "CodeDirector (Coder)" as class-level attributes. |
1 |
REQ-029-002 |
no | process() routes packets with subject "implement" to _handle_implement(). |
1 |
REQ-029-003 |
no | process() routes packets with subject "implementation_complete" to _handle_junior_complete(). |
1 |
REQ-029-004 |
no | process() routes packets with subject "fix_issues" to _handle_fix_issues(). |
1 |
REQ-029-005 |
no | process() returns None for unrecognised subjects without raising an exception. |
1 |
REQ-029-006 |
no | escalation_target is set to "U:Qa" during __init__. |
1 |
REQ-029-007 |
no | _handle_implement() calls _init_from_packet() which sets self.status = WorkStatus.IN_PROGRESS. |
2 |
REQ-029-008 |
no | _init_from_packet() reads task_summary from pkt.payload and stores it on the instance. |
1 |
REQ-029-009 |
no | _init_from_packet() reads original_intent from pkt.payload and stores it on the instance. |
1 |
REQ-029-010 |
no | _init_from_packet() reads project_dir from pkt.payload and overrides self.workspace when non-empty. |
1 |
REQ-029-011 |
no | _init_from_packet() sets self.current_thread to pkt.thread_id. |
1 |
REQ-029-012 |
no | _handle_implement() calls extract_design_docs(pkt) to produce the design docs dict before skeleton generation. |
1 |
REQ-029-013 |
no | extract_design_docs() returns a dict with exactly these keys: file_tree, api_spec, requirements, architecture, class_diagram. |
1 |
REQ-029-014 |
no | extract_design_docs() returns empty string for any key absent from the packet payload (no KeyError raised). |
1 |
REQ-029-015 |
no | extract_design_docs() reads values only from packet.payload without side effects on the packet. |
1 |
REQ-029-016 |
no | generate_skeleton_files() returns an empty list when both file_tree and api_spec are empty strings. |
1 |
REQ-029-017 |
no | generate_skeleton_files() calls generate_skeleton(workspace, design_docs, task_summary) when design docs are non-empty. |
1 |
REQ-029-018 |
no | ScaffoldGenerator creates the mandatory directories tests/, tests/unit/, tests/integration/, docs/, and requirements/ for every project. |
1 |
REQ-029-019 |
no | ScaffoldGenerator writes __init__.py for tests/, tests/unit/, and tests/integration/ directories. |
1 |
REQ-029-020 |
no | ScaffoldGenerator generates pyproject.toml from pyproject.toml.j2 template with all parsed dependencies. |
2 |
REQ-029-021 |
no | ScaffoldGenerator writes context.json at the project root if it does not already exist, with status: "scaffold_complete". |
1 |
REQ-029-022 |
no | ScaffoldGenerator runs uv sync --python 3.14t --all-extras after pyproject.toml creation, logging a warning if uv is not found. |
1 |
REQ-029-023 |
no | parse_file_tree() correctly strips tree-drawing characters (├──, └──, │, ─) from input lines. |
1 |
REQ-029-024 |
no | parse_file_tree() reconstructs nested file paths by tracking a directory stack based on indent level. |
1 |
REQ-029-025 |
no | parse_file_tree() handles directory entries ending with / by pushing them onto the directory stack without emitting a file path. |
1 |
REQ-029-026 |
no | parse_file_tree() returns an empty list for empty or whitespace-only input without raising an exception. |
1 |
REQ-029-027 |
no | parse_api_spec() recognises Module: path.py headers and creates a new ModuleSpec for each. |
5 |
REQ-029-028 |
no | parse_api_spec() extracts Imports: section lines that start with from or import and attaches them to the current module. |
4 |
REQ-029-029 |
no | parse_api_spec() parses class headers matching ClassName: or ClassName(Base): patterns into ClassSpec objects. |
4 |
REQ-029-030 |
no | parse_api_spec() parses method definitions matching def name(params) -> ReturnType: or async def name(params) -> ReturnType: patterns into MethodSpec objects. |
3 |
REQ-029-031 |
no | parse_api_spec() attaches methods to the current class when a class is active, and to the module's function list otherwise. |
1 |
REQ-029-032 |
no | parse_api_spec() correctly handles Raises: ExceptionType lines by appending the exception name to the current method's raises list. |
1 |
REQ-029-033 |
no | parse_code_blocks() extracts complete code from **Module: \pkg.module`**` Kimi-style headers followed by fenced code blocks. |
4 |
REQ-029-034 |
no | parse_code_blocks() normalises dotted module paths to src/pkg/module.py file paths, correcting src/src/ double-nesting. |
2 |
REQ-029-035 |
no | parse_code_blocks() handles **src/pkg/module.py** path-style headers and extracts the following code block. |
5 |
REQ-029-036 |
no | _parse_single_block() handles a single fenced block containing multiple modules separated by # pkg.module comment lines. |
3 |
REQ-029-037 |
no | get_fan_out_decision() calls prolog.fan_out_decision(slug, file_count) when a Prolog engine with that method is available. |
1 |
REQ-029-038 |
no | get_fan_out_decision() returns the Python fallback dict with allowed=True when file_count >= 2 and no Prolog engine is available. |
1 |
REQ-029-039 |
no | get_fan_out_decision() returns allowed=False for file_count < 2 in the Python fallback path. |
1 |
REQ-029-040 |
no | get_fan_out_decision() caps max_shards at min(file_count, 10) in the Python fallback. |
1 |
REQ-029-041 |
no | _handle_implement() chooses the swarm path only when decision["allowed"] == True AND self._postman is not None. |
none |
REQ-029-042 |
no | execute_swarm_path() instantiates SwarmCoordinator with workspace, task_summary, api_spec, and original_intent. |
1 |
REQ-029-043 |
no | execute_swarm_path() calls coordinator.execute_swarm(skeleton_files=skeleton_files) and awaits the result. |
1 |
REQ-029-044 |
no | _swarm_path() appends a formatted swarm artifact string to self.output_artifacts. |
2 |
REQ-029-045 |
no | _swarm_path() runs _run_self_review() on the aggregated files when files_created is non-empty after swarm execution. |
2 |
REQ-029-046 |
no | _serial_path() dispatches a CXP packet with to_agent="J:Junior", subject="implement", and skeleton_files in the payload. |
1 |
REQ-029-047 |
no | build_skeleton_prompt() produces a prompt containing "SKELETON FILES TO IMPLEMENT" and the full content of each .py skeleton file (excluding test files). |
2 |
REQ-029-048 |
no | build_skeleton_prompt() instructs the junior not to create new files, not to change imports/class names/signatures, and to replace NotImplementedError with real implementation. |
1 |
REQ-029-049 |
no | build_fallback_prompt() includes the workspace path, task_summary, and requirements in the prompt, even when architecture fields are absent. |
1 |
REQ-029-050 |
no | append_prompt_extras() appends CODING_STANDARDS to every aider prompt. |
1 |
REQ-029-051 |
no | append_prompt_extras() appends the original_intent under "ORIGINAL SPEC" heading when non-empty. |
1 |
REQ-029-052 |
no | append_prompt_extras() appends monorepo_src_section under "CRITICAL — EXISTING API SOURCES" heading when non-empty. |
1 |
REQ-029-053 |
no | _handle_junior_complete() reads files_created and output from the incoming packet payload. |
1 |
REQ-029-054 |
no | _handle_junior_complete() checks self._pending_fix and routes to handle_fix_return() when a fix is pending, bypassing the normal self-review loop. |
4 |
REQ-029-055 |
no | _handle_junior_complete() runs _run_self_review() when files_created is non-empty and no fix is pending. |
2 |
REQ-029-056 |
no | _handle_junior_complete() returns _make_ready_packet(pkt, full_output=True) on the normal (non-fix) path. |
1 |
REQ-029-057 |
no | _log_junior_output() appends the raw junior output and files list to self.output_artifacts. |
1 |
REQ-029-058 |
no | _handle_fix_issues() reads issues, project_dir, and review_cycle from the incoming packet payload. |
1 |
REQ-029-059 |
no | _handle_fix_issues() overrides self.workspace with project_dir from the packet when non-empty. |
1 |
REQ-029-060 |
no | _handle_fix_issues() calls prepare_fix_delegation(pkt, workspace) and stores the pending context in self._pending_fix. |
3 |
REQ-029-061 |
no | _handle_fix_issues() returns the delegated J:Junior packet directly, not _make_ready_packet. |
1 |
REQ-029-062 |
no | self_review_loop() calls run_deterministic_review() before each LLM review pass. |
none |
REQ-029-063 |
no | self_review_loop() exits the loop immediately when the LLM returns REVIEW_VERDICT: PASS. |
4 |
REQ-029-064 |
no | self_review_loop() exits after MAX_SELF_REVIEW_CYCLES iterations even when the verdict is never PASS. |
1 |
REQ-029-065 |
no | self_review_loop() returns the updated files_created list after each fix application. |
3 |
REQ-029-066 |
no | self_review_loop() passes graph_context to the LLM review when it is provided. |
2 |
REQ-029-067 |
no | Deterministic check SYNTAX runs ast.parse() on each Python file and produces an issue when a SyntaxError is raised. |
1 |
REQ-029-068 |
no | Deterministic check IMPORTS flags any third-party import not found in pyproject.toml dependencies using _get_pyproject_deps(). |
2 |
REQ-029-069 |
no | _make_ready_packet() always includes files_created, task_summary, and project_dir in the payload. |
1 |
REQ-029-070 |
no | _make_ready_packet(swarm=True) adds swarm: True to the payload. |
1 |
REQ-029-071 |
no | _make_ready_packet(full_output=True) adds plan and junior_output to the payload. |
1 |
REQ-029-072 |
no | _make_ready_packet() sets to_agent="HUMAN", subject="implementation_ready", and work_status=WorkStatus.IN_PROGRESS. |
1 |
REQ-029-073 |
no | scan_workspace() returns a sorted list of relative file paths, excluding hidden directories, __pycache__, and directories starting with "Module:". |
1 |
REQ-029-074 |
no | scan_workspace() returns an empty list when the workspace directory does not exist. |
1 |
REQ-029-075 |
no | read_file_contents() returns a concatenated source listing with === filename === separators, skipping files that cannot be read. |
2 |
Code that traces this spec
Checklists
checklists/constitutional.md
Constitutional Checklist — SPEC-029: CodeDirector Volk (U:Cd)
Security (CONST-029-001 to 005)
- [ ] CONST-029-001:
generate_skeleton()never executes code from the architect's API_SPEC or FILE_TREE; all extracted content is treated as data and written as literal text to template-rendered files only. - [ ] CONST-029-002: The
uv syncsubprocess in ScaffoldGenerator uses a fixed command with no user-controlled arguments; it never executes arbitrary shell commands derived from packet payload fields. - [ ] CONST-029-003: The
git commitsubprocess in ScaffoldGenerator uses a hardcoded commit message ("Scaffold: initial project structure") and never interpolates payload values into shell arguments. - [ ] CONST-029-004:
append_prompt_extras()treatsoriginal_intentandmonorepo_src_sectionas plain text appended to the prompt; these values are never eval'd, exec'd, or passed to a shell. - [ ] CONST-029-005: File paths produced by
parse_file_tree()andparse_code_blocks()are resolved relative to the project_dir argument and never allow traversal outside it (no..components in parsed paths reach the filesystem write call).
Reliability (CONST-029-006 to 009)
- [ ] CONST-029-006: All subprocess calls in ScaffoldGenerator (
uv sync,git) are wrapped in try/except forFileNotFoundErrorandsubprocess.TimeoutExpired; failure of either subprocess does not abort skeleton generation. - [ ] CONST-029-007:
self_review_loop()is guaranteed to terminate: thefor cycle in range(1, MAX_SELF_REVIEW_CYCLES + 1)loop has a finite upper bound and the loop body cannot callcontinuepast the bound. - [ ] CONST-029-008:
process()never raises an unhandled exception for an unknown subject; it returnsNonefor all unrecognised CXP subjects. - [ ] CONST-029-009: OSError during file reads in
_read_skeleton_contents(),read_file_contents(), and deterministic check file parsing is caught and logged at DEBUG level; no file read failure propagates as an unhandled exception.
Correctness (CONST-029-010 to 012)
- [ ] CONST-029-010:
_handle_junior_complete()clearsself._pending_fiximmediately upon entering the fix-return path to prevent the pending context from being applied twice if the method is called again. - [ ] CONST-029-011: Fan-out decision reads
_is_source_file()fromorchestrata.agents.swarm.coordinatorto determine which skeleton files are shardable; the same predicate used by SwarmCoordinator is used here so the shard lists are consistent. - [ ] CONST-029-012:
build_project_spec()always populatespython_versionwith a valid3.xstring: it falls back to"3.11"when no version is found in the requirements text rather than leaving the field empty.
Performance (CONST-029-013 to 015)
- [ ] CONST-029-013:
parse_file_tree()andparse_api_spec()are single-pass O(n) algorithms over the input text; they do not perform repeated full-string searches, nested loops over all lines, or regex operations whose complexity exceeds O(n) on input length. - [ ] CONST-029-014:
_get_pyproject_deps()readspyproject.tomlfrom disk at most once perrun_deterministic_review()call by caching the result in a local variable; it does not re-read the file for each import statement checked. - [ ] CONST-029-015:
_read_skeleton_contents()skips non-Python files (those not ending with.py) and test files (those whose basename starts withtest_) without opening them, keeping the skeleton prompt compact.
checklists/requirements.md
The requirement list above comes from this file; 0 of 75 checkbox items are ticked.
checklists/testing.md
Testing Checklist — SPEC-029: CodeDirector Volk (U:Cd)
Each item maps 1:1 to a requirement in requirements.md.
Volk Identity and Routing Tests
- [ ] TEST-029-001: Test that
CodeDirectorVolk.alias == "U:Cd"andCodeDirectorVolk.role == "CodeDirector (Coder)"are set at class level. - [ ] TEST-029-002: Test that
process()calls_handle_implementfor a packet withsubject="implement"and returns its result. - [ ] TEST-029-003: Test that
process()calls_handle_junior_completefor a packet withsubject="implementation_complete"and returns its result. - [ ] TEST-029-004: Test that
process()calls_handle_fix_issuesfor a packet withsubject="fix_issues"and returns its result. - [ ] TEST-029-005: Test that
process()returnsNonefor a packet withsubject="unknown_subject"without raising. - [ ] TEST-029-006: Test that
CodeDirectorVolk().__init__setsself.escalation_target == "U:Qa".
Implement Handler — Initialisation Tests
- [ ] TEST-029-007: Test that
_init_from_packet()setsself.status = WorkStatus.IN_PROGRESS. - [ ] TEST-029-008: Test that
_init_from_packet()setsself.task_summaryfrompkt.payload["task_summary"]. - [ ] TEST-029-009: Test that
_init_from_packet()setsself._original_intentfrompkt.payload["original_intent"]. - [ ] TEST-029-010: Test that
_init_from_packet()overridesself.workspacewithpkt.payload["project_dir"]when that field is non-empty, and does not change workspace when it is empty. - [ ] TEST-029-011: Test that
_init_from_packet()setsself.current_thread = pkt.thread_id. - [ ] TEST-029-012: Test that
_handle_implement()callsextract_design_docs(pkt)and passes the returned dict togenerate_skeleton_files().
Design Doc Extraction Tests
- [ ] TEST-029-013: Test that
extract_design_docs()returns a dict with exactly the keysfile_tree,api_spec,requirements,architecture,class_diagram. - [ ] TEST-029-014: Test that
extract_design_docs()returns""for a key absent from the packet payload without raisingKeyError. - [ ] TEST-029-015: Test that
extract_design_docs()returns the actual payload values for all five keys when all are present.
Skeleton Generation Tests
- [ ] TEST-029-016: Test that
generate_skeleton_files()returns[]when bothfile_treeandapi_specare"". - [ ] TEST-029-017: Test that
generate_skeleton_files()callsgenerate_skeleton()when file_tree is non-empty. - [ ] TEST-029-018: Test that
generate_skeleton()createstests/,tests/unit/,tests/integration/,docs/, andrequirements/directories in the project_dir (use a real temp directory). - [ ] TEST-029-019: Test that
generate_skeleton()writes__init__.pyinsidetests/,tests/unit/, andtests/integration/directories. - [ ] TEST-029-020: Test that
generate_skeleton()createspyproject.tomlcontaining the parsed dependency names from the API_SPEC. - [ ] TEST-029-021: Test that
generate_skeleton()writescontext.jsonat project root withstate.status == "scaffold_complete"when the file does not exist beforehand. - [ ] TEST-029-022: Test that when
uvis not installed (FileNotFoundError),generate_skeleton()continues without raising and the generated file list is non-empty.
Scaffold Parser — File Tree Tests
- [ ] TEST-029-023: Test that
parse_file_tree()strips├──,└──,│, and─characters and returns correct relative paths. - [ ] TEST-029-024: Test that
parse_file_tree()reconstructs nested paths: givensrc/\n pkg/\n core.pyit returns["src/pkg/core.py"]. - [ ] TEST-029-025: Test that
parse_file_tree()treats lines ending with/as directory markers and does not emit them as file paths. - [ ] TEST-029-026: Test that
parse_file_tree()returns[]for""and" \n "inputs.
Scaffold Parser — API Spec Tests
- [ ] TEST-029-027: Test that
parse_api_spec()creates aModuleSpecwithpath="src/pkg/core.py"for aModule: src/pkg/core.pyheader line. - [ ] TEST-029-028: Test that
parse_api_spec()adds import lines starting withfromorimporttomodule.importsand ignores prose lines. - [ ] TEST-029-029: Test that
parse_api_spec()creates aClassSpecwith correctnameandbasesfor aClassName(Base):header. - [ ] TEST-029-030: Test that
parse_api_spec()creates aMethodSpecwithis_async=Truefor anasync def method(...) -> ReturnType:line. - [ ] TEST-029-031: Test that
parse_api_spec()attaches a method to the activeClassSpecwhen a class is open, and tomodule.functionswhen no class is open. - [ ] TEST-029-032: Test that
parse_api_spec()appends"ValueError"to the last method'sraiseslist for aRaises: ValueError when xline.
Scaffold Parser — Code Block Tests
- [ ] TEST-029-033: Test that
parse_code_blocks()extracts code content from**Module: \pkg.sub.module`**followed by a fenced Python block, returning key"src/pkg/sub/module.py"`. - [ ] TEST-029-034: Test that
parse_code_blocks()correctssrc/src/pkg/module.pydouble-nesting tosrc/pkg/module.py. - [ ] TEST-029-035: Test that
parse_code_blocks()extracts code from**src/pkg/module.py**path-style header. - [ ] TEST-029-036: Test that
_parse_single_block()extracts two modules from a single fenced block with# pkg.module_aand# pkg.module_bcomment separators.
Fan-Out Decision Tests
- [ ] TEST-029-037: Test that
get_fan_out_decision()callsprolog.fan_out_decision(slug, file_count)when a Prolog object with that method is provided, and returns its result. - [ ] TEST-029-038: Test that
get_fan_out_decision()returnsallowed=Truewhenprolog=Noneandlen(source_files) == 2. - [ ] TEST-029-039: Test that
get_fan_out_decision()returnsallowed=Falsewhenprolog=Noneandlen(source_files) == 1, andallowed=Falsefor an empty list. - [ ] TEST-029-040: Test that the Python fallback sets
max_shards = min(file_count, 10), specifically that 15 source files producesmax_shards=10. - [ ] TEST-029-041: Test that
_handle_implement()uses the serial path whendecision["allowed"]=Truebutself._postman is None.
Swarm Path Tests
- [ ] TEST-029-042: Test that
execute_swarm_path()constructs aSwarmCoordinatorwith the correctworkspace,task_summary,api_spec, andoriginal_intentarguments. - [ ] TEST-029-043: Test that
execute_swarm_path()awaitscoordinator.execute_swarm(skeleton_files=skeleton_files)and returns the aggregated files list. - [ ] TEST-029-044: Test that
_swarm_path()appends a string containing "SWARM RESULTS" toself.output_artifacts. - [ ] TEST-029-045: Test that
_swarm_path()calls_run_self_review()whenfiles_createdis non-empty, and skips it when empty.
Serial Path and Prompt Construction Tests
- [ ] TEST-029-046: Test that
_serial_path()returns aCXPPacketwithto_agent="J:Junior",subject="implement", andpayload["skeleton_files"]set to the input skeleton list. - [ ] TEST-029-047: Test that
build_skeleton_prompt()returns a string containing"SKELETON FILES TO IMPLEMENT"and the contents of the.pyskeleton files (not test files). - [ ] TEST-029-048: Test that
build_skeleton_prompt()instructs the junior not to create new files (asserts "Do NOT create new files" substring in prompt). - [ ] TEST-029-049: Test that
build_fallback_prompt()returns a string starting with"Create the following project in"followed by the workspace path, even when architecture fields are empty strings. - [ ] TEST-029-050: Test that
append_prompt_extras()appends theCODING_STANDARDSstring to the end of any input prompt. - [ ] TEST-029-051: Test that
append_prompt_extras()appends"ORIGINAL SPEC"heading and the intent text whenoriginal_intentis non-empty, and does not append it when empty. - [ ] TEST-029-052: Test that
append_prompt_extras()appends"CRITICAL — EXISTING API SOURCES"heading whenmonorepo_src_sectionis non-empty, and does not append it when empty.
Junior Complete Handler Tests
- [ ] TEST-029-053: Test that
_handle_junior_complete()storespkt.payload["files_created"]inself.files_createdandpkt.payload["output"]inself.junior_output. - [ ] TEST-029-054: Test that
_handle_junior_complete()callshandle_fix_return()whenself._pending_fixis set, and clears_pending_fixtoNoneafterwards. - [ ] TEST-029-055: Test that
_handle_junior_complete()calls_run_self_review()whenfiles_createdis non-empty and_pending_fixis None. - [ ] TEST-029-056: Test that
_handle_junior_complete()returns a packet withsubject="implementation_ready"andto_agent="HUMAN"on the normal path. - [ ] TEST-029-057: Test that
_log_junior_output()appends two artifacts: one containing"JUNIOR VOLK OUTPUT"and one containing"FILES CREATED".
Fix Issues Handler Tests
- [ ] TEST-029-058: Test that
_handle_fix_issues()extractsissues,project_dir, andreview_cyclefrom the packet payload. - [ ] TEST-029-059: Test that
_handle_fix_issues()setsself.workspace = project_dirwhenproject_diris non-empty, and leaves workspace unchanged when it is empty. - [ ] TEST-029-060: Test that
_handle_fix_issues()stores the pending context fromprepare_fix_delegation()inself._pending_fix. - [ ] TEST-029-061: Test that
_handle_fix_issues()returns the J:Junior delegation packet (not a_make_ready_packetresult).
Self-Review Loop Tests
- [ ] TEST-029-062: Test that
self_review_loop()callsrun_deterministic_review()on each iteration before the LLM call. - [ ] TEST-029-063: Test that
self_review_loop()exits after exactly 1 cycle when the first LLM call returnsREVIEW_VERDICT: PASS. - [ ] TEST-029-064: Test that
self_review_loop()exits after exactlyMAX_SELF_REVIEW_CYCLESiterations when the LLM always returnsREVIEW_VERDICT: FAIL. - [ ] TEST-029-065: Test that
self_review_loop()returns the updated files list after each fix cycle (not the original list). - [ ] TEST-029-066: Test that when
graph_contextis provided, the LLM prompt includes the graph_context string. - [ ] TEST-029-067: Test that
run_deterministic_review()produces a("SYNTAX", filepath, ...)issue tuple for a file containing a deliberateSyntaxError. - [ ] TEST-029-068: Test that
run_deterministic_review()produces a("DEPENDENCY_DECLARED", filepath, ...)issue for a file importing a package not in pyproject.toml.
Ready Packet Construction Tests
- [ ] TEST-029-069: Test that
_make_ready_packet()payload containsfiles_created,task_summary, andproject_dirin all call modes. - [ ] TEST-029-070: Test that
_make_ready_packet(swarm=True)addspayload["swarm"] == True. - [ ] TEST-029-071: Test that
_make_ready_packet(full_output=True)adds bothpayload["plan"]andpayload["junior_output"]. - [ ] TEST-029-072: Test that
_make_ready_packet()setsto_agent="HUMAN",subject="implementation_ready", andwork_status=WorkStatus.IN_PROGRESS.
Workspace Scanning Tests
- [ ] TEST-029-073: Test that
scan_workspace()excludes__pycache__directories, hidden directories (starting with.), and directories starting with"Module:"from the returned list. - [ ] TEST-029-074: Test that
scan_workspace()returns[]for a path that does not exist on disk. - [ ] TEST-029-075: Test that
read_file_contents()returns a string containing"=== filename ==="separators and skips files that raiseOSErroron open.
Other tracked files
specs/029-codedirector-volk/README.mdspecs/029-codedirector-volk/compliance-audit.md
Full spec text
Verbatim from specs/029-codedirector-volk/spec.md; headings are pushed down two levels.
SPEC-029: CodeDirector Volk (U:Cd)
Metadata
- Spec ID: 029-codedirector-volk
- Title: CodeDirector Volk — Senior Implementation Coordinator
- Author: Mohamed
- Status: Implemented
- Created: 2026-04-04
- Last Updated: 2026-04-04
- Priority: P1
- Version: 1.0.0
- Components: CodeDirectorVolk, ScaffoldGenerator, ScaffoldParser, SelfReviewLoop, DeterministicReviewChecks
- Dependencies: Python 3.14t, orchestrata-core, orchestrata-agents, orchestrata-cxp, orchestrata-drivers, orchestrata-governance (Prolog gate)
Overview
What
U:Cd is the CodeDirector volk — a thin senior-engineer coordinator that bridges architecture design to working code. It receives implementation requests from U:Ar (Architect), generates deterministic project skeletons, decides whether to fan out to a parallel junior swarm or route to a single J:Junior, runs a self-review loop against the generated output, and handles QA fix requests delegated back from U:Qa.
Why
- Architecture artifacts (file trees, API specs) must be translated into file skeletons before any junior coding begins, preventing blanket re-invention of already-decided structure
- Fan-out decisions must be governance-gated (Prolog) to prevent unconstrained parallelism
- Self-review closes the gap between what a junior produces and what passes review, without requiring a full QA cycle for minor defects
- QA fix delegation keeps the fix loop within the implementation lane, not the design lane
How
- Receives
implementCXP packet from U:Ar - Extracts design docs (file_tree, api_spec, requirements, architecture, class_diagram)
- Generates skeleton files via ScaffoldGenerator (deterministic — no LLM)
- Queries Prolog (or Python fallback) for swarm fan-out decision
- Swarm path: delegates to SwarmCoordinator with multiple J:Junior instances in parallel
- Serial path: builds aider prompt and delegates to a single J:Junior
- On
implementation_completefrom J:Junior: runs self-review loop (up to MAX_SELF_REVIEW_CYCLES) - On
fix_issuesfrom U:Qa: prepares fix delegation back to J:Junior
Terminology
| Term | Definition |
|---|---|
| U:Cd | CodeDirector volk alias. The implementation coordination agent in Orchestrata. |
| J:Junior | Junior Developer volk. The code-writing agent that U:Cd delegates to. |
| SwarmCoordinator | Component that spawns multiple J:Junior instances in parallel across file shards. |
| Skeleton | Deterministically generated project scaffold: directory structure, pyproject.toml, init.py, class/method stubs with correct signatures but NotImplementedError bodies. |
| Fan-out Decision | Prolog-gated binary choice: swarm (parallel juniors, ≥2 source files) vs serial (single junior). |
| Swarm Path | Code generation path where SwarmCoordinator dispatches shards to parallel J:Junior instances. |
| Serial Path | Code generation path where a single J:Junior receives the full aider prompt. |
| Self-Review Loop | Iterative LLM-driven review cycle where U:Cd reviews junior output and requests fixes without escalating to U:Qa. |
| Deterministic Review | AST/regex-based code checks (syntax, imports, lint, traceability) that run before the LLM reviewer. |
| aider_prompt | The natural language prompt given to J:Junior instructing what code to implement. |
| Kimi-style | A code block format where the architect's API_SPEC contains complete implementation code in fenced blocks keyed by filename, rather than pseudo-code stubs. |
| MAX_SELF_REVIEW_CYCLES | Module constant in prompts.py controlling maximum self-review iterations (current value: 99). |
| MAX_SELF_REVIEW_ISSUES | Module constant limiting how many issues are surfaced per review cycle (current value: 5). |
| ScaffoldParser | Module (scaffold/parser.py) that parses architect file_tree and API_SPEC into structured data types. |
| ScaffoldGenerator | Module (scaffold/generator.py) that converts parsed specs into physical files using Jinja2 templates. |
| ProjectSpec | Root data type holding all parsed design information for a project. |
| ModuleSpec | Parsed representation of a single Python module from the API_SPEC. |
| ClassSpec | Parsed class definition including fields, methods, bases, and docstring. |
| MethodSpec | Parsed method/function signature including parameters, return type, async flag, and raises list. |
| CODEDIRECTOR_SYSTEM_PROMPT | System prompt given to U:Cd when operating as an LLM-driven planner. |
| SELF_REVIEW_PROMPT | System prompt for the cross-context code review pass during self-review loop. |
| implementation_plan | Instance variable holding the aider prompt generated during the serial path. |
| pending_fix | Transient state stored on the volk instance between fix delegation and fix return. |
| escalation_target | Hard-coded to U:Qa — the volk that receives escalated implementation issues. |
| graph_context | Optional Neo4j knowledge graph context injected into the self-review loop for traceability checks. |
| context.json | Mandatory project file written by ScaffoldGenerator to track project state. |
| _is_source_file | Predicate imported from SwarmCoordinator that filters non-source files (tests, configs) from the shard list. |
Architecture
Pipeline Position
U:Ar (Architect)
↓ implement (CXP)
U:Cd (CodeDirector) ←── fix_issues (CXP) ── U:Qa (QA Engineer)
│
├── [Skeleton Generation] ── ScaffoldParser → ScaffoldGenerator
│
├── [Fan-out Decision] ── Prolog gate (or Python fallback)
│
├── [Swarm Path] ── SwarmCoordinator → parallel J:Junior × N
│
└── [Serial Path] ── J:Junior (single)
↓ implementation_complete (CXP)
U:Cd ← self_review_loop
↓ implementation_ready (CXP)
HUMAN
Class Structure
BaseVolk (orchestrata-agents)
└── CodeDirectorVolk (volk.py)
alias = "U:Cd"
role = "CodeDirector (Coder)"
│
├── process(packet) → routes on subject
├── _handle_implement(pkt) → skeleton + fan-out
├── _handle_junior_complete(pkt) → review loop
├── _handle_fix_issues(pkt) → fix delegation
├── _swarm_path(pkt, ...) → SwarmCoordinator
├── _serial_path(pkt, ...) → J:Junior delegation
├── _build_aider_prompt(pkt, ...) → prompt construction
├── _make_ready_packet(pkt, ...) → HUMAN notification
├── _run_self_review() → self_review_loop()
└── _get_junior_driver() → driver_factory.get_driver()
implementation.py (helpers)
extract_design_docs(packet) → Dict
generate_skeleton_files(workspace, docs, summary) → List[str]
get_fan_out_decision(files, prolog, summary) → Dict
execute_swarm_path(...) → Tuple[List[str], str]
build_skeleton_prompt(files, workspace, summary) → str
build_fallback_prompt(...) → str
append_prompt_extras(prompt, intent, monorepo) → str
scan_workspace(workspace) → List[str]
read_file_contents(workspace, files) → str
scaffold/
types.py — MethodSpec, ClassSpec, ModuleSpec, ProjectSpec
parser.py — parse_file_tree, parse_api_spec, parse_code_blocks, build_project_spec
generator.py — generate_skeleton (top-level entry point)
review.py
self_review_loop(task_summary, files, workspace, ...) → List[str]
handle_fix_return(pkt, pending, workspace) → Tuple
prepare_fix_delegation(pkt, workspace) → Tuple[CXPPacket, dict]
review_checks.py
run_deterministic_review(workspace, files) → List[Issue]
(Checks: SYNTAX, IMPORTS, ENTRY_POINT, LINE_LENGTH, NO_PLACEHOLDER,
DEPENDENCY_DECLARED, TRACEABILITY, LINT via ruff subprocess)
prompts.py
CODEDIRECTOR_SYSTEM_PROMPT
SELF_REVIEW_PROMPT
MAX_SELF_REVIEW_CYCLES = 99
MAX_SELF_REVIEW_ISSUES = 5
CXP Protocol
Inbound Packets
Subject: implement
Sent by U:Ar to trigger implementation planning and junior delegation.
| Payload Field | Type | Required | Description |
|---|---|---|---|
task_summary |
str | Yes | Short human-readable task description |
file_tree |
str | No | Architect's proposed directory and file layout |
api_spec |
str | No | Function/class signatures or complete code blocks |
requirements |
str | No | Feature requirements text |
architecture |
str | No | Architecture narrative |
class_diagram |
str | No | Class relationship diagram |
project_dir |
str | No | Override workspace path (uses WORKSPACE_DIR if absent) |
original_intent |
str | No | Original user intent for prompt inclusion |
monorepo_src_section |
str | No | Existing monorepo API sources for context |
Subject: implementation_complete
Sent by J:Junior when code generation finishes.
| Payload Field | Type | Required | Description |
|---|---|---|---|
files_created |
List[str] | Yes | Relative paths of generated files |
output |
str | No | Raw driver backend output text |
success |
bool | No | Whether driver reported success |
dependency_issues |
List[str] | No | Undeclared dependency violations |
Subject: fix_issues
Sent by U:Qa to request code fixes.
| Payload Field | Type | Required | Description |
|---|---|---|---|
issues |
List[str] | Yes | List of issue descriptions to fix |
project_dir |
str | No | Override workspace path |
review_cycle |
int | No | Fix cycle number (for logging) |
files_to_fix |
List[str] | No | Specific files requiring attention |
Outbound Packets
Subject: implement → J:Junior (serial path)
| Payload Field | Type | Description |
|---|---|---|
aider_prompt |
str | Full implementation prompt for the junior driver |
project_dir |
str | Workspace path |
task_summary |
str | Short task description |
skeleton_files |
List[str] | Pre-generated skeleton file paths |
Subject: implementation_ready → HUMAN
| Payload Field | Type | Description |
|---|---|---|
files_created |
List[str] | Final list of created file paths |
task_summary |
str | Short task description |
project_dir |
str | Workspace path |
swarm |
bool | Present and True when swarm path was used |
plan |
str | Implementation plan (serial path only) |
junior_output |
str | Raw junior output (serial path only) |
Subject: implement → J:Junior (fix path)
Same schema as serial path implement, with fix-specific aider_prompt.
Skeleton Generation
Entry Point
generate_skeleton(project_dir, design_docs, project_name) → List[str]
Generation Pipeline
1. build_project_spec(name, dir, design_docs)
parse_file_tree(file_tree) → List[str]
parse_api_spec(api_spec) → List[ModuleSpec]
parse_dependencies(api_spec) → List[str]
extract_package_name(file_paths) → str
→ ProjectSpec
2. _create_directories(spec, project_dir)
- Mandatory: tests/, tests/unit/, tests/integration/, docs/, requirements/
- Per-module test subdirs under tests/unit/
- __init__.py for all test packages
3. _generate_pyproject(env, spec, project_dir)
- Jinja2 template: pyproject.toml.j2
4. _generate_conftest(env, spec, project_dir)
- Jinja2 template: conftest.py.j2
5. _generate_init_files(env, spec, project_dir)
- One __init__.py per package directory
6. parse_code_blocks(api_spec, file_tree) → Dict[str, str]
IF code_blocks is populated (Kimi-style):
_write_code_blocks(code_blocks, project_dir)
ELSE (standard stubs):
_generate_modules(env, spec, project_dir)
7. Write context.json if absent
8. uv sync --python 3.14t --all-extras (if pyproject.toml exists)
9. git add -A && git commit "Scaffold: initial project structure" (if .git exists)
Parser Formats
The parser handles four architect output styles:
| Format | Identifier | Description |
|---|---|---|
| Standard | Module: path.py header + pseudo-code |
Classic Orchestrata architect output |
| Kimi-style full blocks | **Module: \pkg.module`**` + fenced code |
Complete implementations in API_SPEC |
| Kimi-style paths | **src/pkg/module.py** + fenced code |
Path-keyed complete code blocks |
| Single-block | One fenced block with # pkg.module comment separators |
Compact multi-module format |
Fan-Out Decision
Decision Logic
get_fan_out_decision(source_files, prolog, task_summary) → Dict
# Prolog path (when prolog engine is available):
slug = task_summary[:50].replace(" ", "-").lower()
result = prolog.fan_out_decision(slug, file_count)
# Python fallback:
{
"allowed": file_count >= 2,
"strategy": "parallel" if file_count >= 2 else "serial",
"max_shards": min(file_count, 10),
"reason": "python fallback (no prolog gate)",
}
Swarm vs Serial Routing
| Condition | Path |
|---|---|
decision["allowed"] == True AND self._postman is not None |
Swarm path |
| Otherwise | Serial path |
Self-Review Loop
Loop Logic
self_review_loop(task_summary, files_created, workspace, ...) → List[str]
for cycle in range(1, MAX_SELF_REVIEW_CYCLES + 1):
1. run_deterministic_review(workspace, files) → issues (fast, no LLM)
2. LLM call with SELF_REVIEW_PROMPT + file contents → REVIEW_VERDICT
3. If REVIEW_VERDICT == PASS: break
4. If issues found: delegate fixes to junior driver
5. Collect updated files from driver output
Review Checks (Deterministic)
| Check ID | Category | Description |
|---|---|---|
| SYNTAX | Blocking | AST parse — detects unclosed brackets, missing colons, indentation errors |
| IMPORTS | Blocking | Cross-references all imports against stdlib, pyproject.toml deps, local file tree |
| ENTRY_POINT | Blocking | Verifies if __name__ == '__main__': guard exists in entry-point files |
| LINE_LENGTH | Non-blocking | Lines > 120 characters |
| FULL_IMPLEMENTATION | Blocking | Detects pass, to-do markers, NotImplementedError in non-stub files |
| DEPENDENCY_DECLARED | Blocking | Third-party imports present but not in pyproject.toml |
| TRACEABILITY | Non-blocking | Checks @traces decorator presence on public methods |
| LINT | Blocking | ruff check subprocess for fast static analysis |
SELF_REVIEW_PROMPT Structure
The review prompt instructs the LLM to perform these checks in order, stopping at the first FAIL:
[SYNTAX]— Valid Python parse[IMPORTS]— Every import resolves (stdlib, third-party, local)[API_CORRECTNESS]— Function calls match actual signatures[FILE_COMPLETENESS]— No circular imports, all referenced files present[ENTRY_POINT]— Working entry point withif __name__ == '__main__'[ERROR_HANDLING](non-blocking) — try/except with specific exception types[STUB_CONTENT](non-blocking) — No criticalpass/to-dopaths
Output format is always: REVIEW_VERDICT: PASS or FAIL followed by ISSUES: list.
Fix Delegation
prepare_fix_delegation(pkt, workspace)
Builds a J:Junior implement packet whose aider_prompt includes:
- The issue list from U:Qa
- Current file contents of files requiring fixes
- CODING_STANDARDS_FIX instructions
review_cyclefor tracking
handle_fix_return(pkt, pending, workspace)
Processes J:Junior's implementation_complete response after a fix:
- Updates
files_createdfrom the junior's output - Builds
implementation_readypacket to HUMAN - Updates
summarywith fix cycle context
Data Models
ProjectSpec
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ProjectSpec",
"description": "Complete parsed project specification",
"type": "object",
"required": ["name", "root_dir", "package_name"],
"properties": {
"name": { "type": "string" },
"root_dir": { "type": "string" },
"package_name": { "type": "string" },
"file_paths": { "type": "array", "items": { "type": "string" } },
"modules": { "type": "array", "description": "List of ModuleSpec" },
"dependencies": { "type": "array", "items": { "type": "string" } },
"python_version": { "type": "string", "pattern": "^3\\.\\d+$", "default": "3.11" }
}
}
MethodSpec
{
"title": "MethodSpec",
"type": "object",
"required": ["name", "params"],
"properties": {
"name": { "type": "string" },
"params": { "type": "array", "items": { "type": "array", "minItems": 2, "maxItems": 2 } },
"return_type": { "type": "string", "default": "None" },
"is_async": { "type": "boolean", "default": false },
"is_classmethod": { "type": "boolean", "default": false },
"is_property": { "type": "boolean", "default": false },
"docstring": { "type": "string", "default": "" },
"raises": { "type": "array", "items": { "type": "string" } }
}
}
ClassSpec
{
"title": "ClassSpec",
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"fields": { "type": "array", "description": "List of (name, type, default) tuples" },
"methods": { "type": "array", "description": "List of MethodSpec" },
"bases": { "type": "array", "items": { "type": "string" } },
"is_dataclass": { "type": "boolean", "default": false },
"docstring": { "type": "string", "default": "" }
}
}
FanOutDecision
{
"title": "FanOutDecision",
"type": "object",
"required": ["allowed", "strategy", "max_shards", "reason"],
"properties": {
"allowed": { "type": "boolean" },
"strategy": { "type": "string", "enum": ["parallel", "serial"] },
"max_shards": { "type": "integer", "minimum": 1, "maximum": 10 },
"reason": { "type": "string" }
}
}
Functional Requirements
Core Implementation
| ID | Requirement | Testable Success Criteria |
|---|---|---|
| FR-001 | U:Cd shall receive implement CXP packets from U:Ar |
Packet with subject implement triggers _handle_implement |
| FR-002 | U:Cd shall extract design docs from packet payload | file_tree, api_spec, requirements, architecture accessible |
| FR-003 | U:Cd shall generate deterministic skeleton files | ScaffoldGenerator produces .py files with NotImplementedError |
| FR-004 | Skeleton generation shall create directory structure | All directories from file_tree exist before file creation |
| FR-005 | Skeleton generation shall produce pyproject.toml | Valid TOML with parsed dependencies |
| FR-006 | Skeleton generation shall create init.py files | One per package directory |
| FR-007 | Skeleton generation shall write context.json | File with status: scaffold_complete |
| FR-008 | U:Cd shall query Prolog for fan-out decision | prolog.fan_out_decision() called when prolog available |
| FR-009 | Fan-out shall fallback to Python logic | Python returns allowed=True for ≥2 source files |
| FR-010 | Swarm path shall invoke SwarmCoordinator | _swarm_path() dispatches to parallel J:Junior |
| FR-011 | Serial path shall delegate to single J:Junior | _serial_path() builds aider prompt and dispatches |
| FR-012 | U:Cd shall await implementation_complete before review | Blocking wait on junior response |
| FR-013 | Self-review loop shall run determinstic checks first | SYNTAX, IMPORTS, LINT run before LLM |
| FR-014 | Self-review loop shall call LLM with SELF_REVIEW_PROMPT | call_llm invoked with review prompt |
| FR-015 | Self-review loop shall exit on REVIEW_VERDICT: PASS | Loop breaks immediately on PASS |
| FR-016 | Self-review loop shall request fixes on FAIL | Junior driver receives fix-specific prompt |
| FR-017 | Self-review loop shall terminate at MAX_SELF_REVIEW_CYCLES | Loop count reaches 99 then exits |
| FR-018 | U:Cd shall receive fix_issues packets from U:Qa |
Packet with subject fix_issues triggers _handle_fix_issues |
| FR-019 | Fix delegation shall include issue list in prompt | aider_prompt contains all issues from U:Qa |
| FR-020 | U:Cd shall emit implementation_ready to HUMAN |
Packet sent with files_created and task_summary |
Parser Requirements
| ID | Requirement | Testable Success Criteria |
|---|---|---|
| FR-021 | parse_file_tree shall extract directory paths | List of directory strings from file_tree input |
| FR-022 | parse_api_spec shall extract ModuleSpec list | Each module has name, classes, methods |
| FR-023 | parse_code_blocks shall handle Kimi-style full blocks | Code extracted from **Module: fence blocks |
| FR-024 | parse_code_blocks shall handle Kimi-style paths | Code extracted from **path.py** headers |
| FR-025 | parse_code_blocks shall handle single-block format | Multiple modules parsed from one fenced block |
| FR-026 | Parser shall normalize src/src/ double-nesting | Paths corrected before file writing |
Review Requirements
| ID | Requirement | Testable Success Criteria |
|---|---|---|
| FR-027 | SYNTAX check shall detect Python parse errors | SyntaxError files flagged as blocking |
| FR-028 | IMPORTS check shall verify all imports resolve | Unresolved imports flagged |
| FR-029 | DEPENDENCY_DECLARED check shall flag undeclared third-party | Import without pyproject.toml entry flagged |
| FR-030 | ENTRY_POINT check shall verify main guard | Entry files missing guard flagged |
| FR-031 | FULL_IMPLEMENTATION check shall detect pass/to-do markers/NotImplementedError | Non-stub files with placeholders flagged |
| FR-032 | LINE_LENGTH check shall flag lines > 120 chars | Long lines flagged as non-blocking |
| FR-033 | TRACEABILITY check shall verify @traces decorator | Public methods without @traces flagged |
| FR-034 | LINT check shall run ruff subprocess | ruff check output parsed for issues |
Protocol Requirements
| ID | Requirement | Testable Success Criteria |
|---|---|---|
| FR-035 | U:Cd shall register with alias U:Cd | BaseVolk alias assignment correct |
| FR-036 | U:Cd shall route packets by subject | process() dispatches to correct handler |
| FR-037 | implement packet requires task_summary field | Validation rejects packet without task_summary |
| FR-038 | implementation_complete packet requires files_created | Validation requires populated file list |
API Contracts
CodeDirectorVolk (volk.py)
class CodeDirectorVolk(BaseVolk):
alias = "U:Cd"
role = "CodeDirector (Coder)"
def __init__(self, config: Dict[str, Any]) -> None:
"""Initialize CodeDirector with optional Prolog and Postman."""
def process(self, packet: CXPPacket) -> Optional[CXPPacket]:
"""Route inbound packet by subject to appropriate handler."""
# Returns: None (async response via postman) or CXPPacket
def _handle_implement(self, pkt: CXPPacket) -> None:
"""Handle implement request from U:Ar."""
def _handle_implementation_complete(self, pkt: CXPPacket) -> None:
"""Handle completion from J:Junior, trigger self-review."""
def _handle_fix_issues(self, pkt: CXPPacket) -> None:
"""Handle fix request from U:Qa."""
ScaffoldGenerator (scaffold/generator.py)
def generate_skeleton(
project_dir: Path,
design_docs: Dict[str, str],
project_name: str
) -> List[str]:
"""Generate deterministic project skeleton.
Args:
project_dir: Target directory for skeleton
design_docs: Dict with file_tree, api_spec, etc.
project_name: Name for project/package
Returns:
List of created file paths
Raises:
ScaffoldError: On generation failure
"""
def build_project_spec(
name: str,
root_dir: Path,
design_docs: Dict[str, str]
) -> ProjectSpec:
"""Parse design docs into ProjectSpec."""
Review Module (review.py)
def self_review_loop(
task_summary: str,
files_created: List[str],
workspace: Path,
max_cycles: int = MAX_SELF_REVIEW_CYCLES,
max_issues: int = MAX_SELF_REVIEW_ISSUES
) -> Tuple[List[str], bool]:
"""Run self-review loop on generated files.
Returns:
Tuple of (final_files, passed)
"""
def prepare_fix_delegation(
pkt: CXPPacket,
workspace: Path
) -> Tuple[CXPPacket, dict]:
"""Build fix-specific implement packet for J:Junior.
Returns:
Tuple of (implement_packet, pending_state)
"""
def handle_fix_return(
pkt: CXPPacket,
pending: dict,
workspace: Path
) -> CXPPacket:
"""Process implementation_complete after fix.
Returns:
implementation_ready packet to HUMAN
"""
ReviewChecks (review_checks.py)
def run_deterministic_review(
workspace: Path,
files: List[str]
) -> List[Issue]:
"""Run AST/regex-based checks on files.
Returns:
List of Issue objects with check_id, severity, message
"""
Implementation Helpers (implementation.py)
def extract_design_docs(packet: CXPPacket) -> Dict[str, Any]:
"""Extract design documents from implement packet."""
def generate_skeleton_files(
workspace: Path,
docs: Dict[str, str],
summary: str
) -> List[str]:
"""Generate skeleton, return list of created files."""
def get_fan_out_decision(
files: List[str],
prolog: Optional[Any],
summary: str
) -> Dict[str, Any]:
"""Query Prolog or use Python fallback.
Returns:
Dict with allowed, strategy, max_shards, reason
"""
def execute_swarm_path(
pkt: CXPPacket,
skeleton_files: List[str],
source_files: List[str]
) -> Tuple[List[str], str]:
"""Execute parallel junior via SwarmCoordinator.
Returns:
Tuple of (files_created, output)
"""
def build_aider_prompt(
files: List[str],
workspace: Path,
summary: str,
skeleton_files: Optional[List[str]] = None
) -> str:
"""Build implementation prompt for J:Junior."""
Non-Functional Requirements
Performance
| Requirement | Target | Measurement |
|---|---|---|
| Skeleton generation (20 files) | < 3s (P95) | Benchmark with 20 modules |
| Fan-out decision (Prolog) | < 100ms | Timer around prolog call |
| Fan-out decision (Python) | < 1ms | Timer around fallback |
| Self-review deterministic (50 files) | < 5s | Timer for all checks |
| Self-review LLM call | < 30s | Timer for call_llm |
| uv sync | < 60s | Timer for subprocess |
| Aider prompt construction | < 50ms | Timer for build_aider_prompt |
| CXP packet routing | < 5ms | Timer for process() |
Reliability
| Requirement | Target |
|---|---|
| Self-review convergence | 99 cycles max before exit |
| Swarm shard timeout | 300s per shard |
| Junior driver timeout | 600s for serial path |
| Graceful degradation | All errors logged, operation continues |
Scalability
| Requirement | Target |
|---|---|
| Maximum swarm shards | 10 parallel juniors |
| Source files per shard | file_count // max_shards |
| Self-review file limit | 100 files per review cycle |
Examples
Example 1: Implement Request from Architect
Inbound CXP Packet:
{
"from_agent": "U:Ar",
"to_agent": "U:Cd",
"subject": "implement",
"payload": {
"task_summary": "Implement user authentication module",
"file_tree": "src/\n auth/\n __init__.py\n models.py\n handlers.py\n tests/\n unit/\n test_auth.py",
"api_spec": "class AuthHandler:\n def authenticate(self, username: str, password: str) -> bool:\n ...",
"project_dir": "/workspace/myapp"
}
}
Response Flow:
- ScaffoldGenerator creates directories and stubs
- Fan-out decision returns
allowed=False(1 source file) - Serial path builds aider_prompt
- J:Junior receives implement packet
- Self-review runs, returns PASS
- implementation_ready sent to HUMAN
Example 2: Swarm Path for Multi-File Project
Fan-out Decision:
{
"allowed": True,
"strategy": "parallel",
"max_shards": 4,
"reason": "prolog: 4 source files, within limits"
}
SwarmCoordinator Dispatch:
- Shard 1: src/models/user.py, src/models/session.py
- Shard 2: src/api/auth.py, src/api/users.py
- Parallel execution by 4 J:Junior instances
Example 3: QA Fix Request
Inbound Packet from U:Qa:
{
"from_agent": "U:Qa",
"to_agent": "U:Cd",
"subject": "fix_issues",
"payload": {
"issues": [
"AuthHandler.authenticate missing try/except",
"Password hashing uses insecure algorithm"
],
"files_to_fix": ["src/auth/handlers.py"],
"review_cycle": 1
}
}
Fix Delegation:
- prepare_fix_delegation builds prompt with issue list
- J:Junior receives implement with fix instructions
- handle_fix_return emits implementation_ready
Security Requirements
Input Validation
| Requirement | Implementation |
|---|---|
| Packet schema validation | CXPPacket enforces required fields |
| path traversal prevention | Path.resolve() + prefix checking |
| command injection prevention | Subprocess with shell=False |
| LLM prompt injection | Input sanitization in prompt builders |
Authorization
| Requirement | Implementation |
|---|---|
| Only U:Ar can trigger implement | Subject routing from expected agent |
| Only U:Qa can trigger fix_issues | Subject routing from expected agent |
| Only J:Junior sends completion | Subject validation |
Audit Logging
| Requirement | Implementation |
|---|---|
| All packet receipts | process() logs from_agent, subject |
| Skeleton generation | generate_skeleton logs file count |
| Fan-out decisions | get_fan_out_decision logs decision |
| Self-review cycles | self_review_loop logs each cycle |
| Fix cycles | prepare_fix_delegation logs review_cycle |
Governance
Prolog Gate Rules
The fan-out decision requires Prolog governance:
fan_out_decision(Slug, FileCount, Decision) :-
FileCount >= 2,
Decision = allowed{strategy:parallel, max_shards:min(10, FileCount)}.
fan_out_decision(_, FileCount, not_allowed{strategy:serial, reason:single_file}) :-
FileCount < 2.
PAM++ Rules
| Action | Actor | Target | Condition |
|---|---|---|---|
| can_act | U:Cd | implement | from_agent == U:Ar |
| can_act | U:Cd | fix_issues | from_agent == U:Qa |
| can_route | U:Cd | J:Junior | skeleton_generated == true |
Compliance
| Requirement | Verification |
|---|---|
| All public methods traced | @traces decorator on methods |
| All errors logged | logging.error for all ERR-* |
| No secrets in prompts | CODING_STANDARDS checked, no API keys |
Integration Points
U:Ar (Architect)
- Interface: CXP packet with subject
implement - Direction: Inbound
- Payload: task_summary, file_tree, api_spec, requirements, architecture
U:Qa (QA Engineer)
- Interface: CXP packet with subject
fix_issues - Direction: Inbound
- Payload: issues list, files_to_fix, review_cycle
J:Junior (Junior Developer)
- Interface: CXP packet with subject
implement(outbound) andimplementation_complete(inbound) - Direction: Bidirectional
- Payload: aider_prompt, skeleton_files, files_created
SwarmCoordinator
- Interface: Python function call
- Direction: Outbound
- Method: execute_swarm(skeleton_files, source_files, ...)
Prolog Engine
- Interface: Python predicate call
- Direction: Outbound
- Method: prolog.fan_out_decision(slug, file_count)
Neo4j Knowledge Graph
- Interface: Graph context injection
- Direction: Outbound (optional)
- Purpose: Traceability checks in self-review
Testing Requirements
Unit Tests
| Module | Test Coverage Target |
|---|---|
| scaffold/types.py | 100% |
| scaffold/parser.py | 100% |
| scaffold/generator.py | 90% |
| implementation.py | 90% |
| review_checks.py | 100% |
| review.py | 85% |
| prompts.py | 100% |
Integration Tests
| Scenario | Test |
|---|---|
| Full implement flow | test_implement_full_serial |
| Swarm path execution | test_implement_swarm_parallel |
| Self-review pass | test_self_review_passes |
| Self-review fix cycle | test_self_review_fixes_issues |
| Fix delegation | test_fix_delegation_from_qa |
| Prolog unavailable | test_fan_out_python_fallback |
Error Condition Tests
| ERR-ID | Test |
|---|---|
| ERR-001 | test_empty_design_docs_fallback |
| ERR-002 | test_invalid_file_tree_format |
| ERR-003 | test_missing_api_spec_fallback |
| ERR-004 | test_skeleton_generation_failure |
| ERR-005 | test_prolog_unavailable_fallback |
| ERR-006 | test_swarm_coordinator_failure |
| ERR-007 | test_junior_driver_timeout |
| ERR-008 | test_junior_driver_failure |
| ERR-009 | test_self_review_max_cycles |
| ERR-010 | test_deterministic_review_error |
| ERR-011 | test_llm_review_failure |
| ERR-012 | test_fix_pending_mismatch |
| ERR-013 | test_invalid_fix_issues_packet |
| ERR-014 | test_implementation_complete_mismatch |
Success Criteria
| ID | Condition | Verification |
|---|---|---|
| DoD-001 | All functional requirements (FR-001 through FR-038) implemented and traced via @traces | RTM extraction shows ≥95% coverage |
| DoD-002 | All acceptance criteria (AC-001 through AC-020) pass in CI | ci/local-ci.sh test green with all CodeDirector tests passing |
| DoD-003 | All error conditions (ERR-001 through ERR-014) have corresponding test cases | Test file contains functions for each error ID |
| DoD-004 | Performance targets met under load: skeleton generation <3s, LLM review <30s | Benchmark test suite with measured values |
| DoD-005 | Test coverage for codedirector package ≥ 90% | Coverage report from ci/local-ci.sh |
| DoD-006 | Code passes black, isort, flake8, mypy with zero errors |
Formatting pipeline in CI |
| DoD-007 | CodeDirectorVolk registered in DI container and PAM++ rules allow can_act(cd, implement) |
Integration test verifying DI and Prolog resolution |
| DoD-008 | All four parser formats (standard, Kimi-full, Kimi-path, single-block) have fixture-based tests | Parser test file covers all four branches |
| DoD-009 | Scaffold Jinja2 templates produce valid Python syntax | Compile-time AST check on all generated stubs |
| DoD-010 | Self-review deterministic checks cover all 8 check IDs | Unit tests for each check ID |
Performance Targets
| Operation | Target (P95) |
|---|---|
| Skeleton generation (20 files) | < 3s |
| Fan-out decision (Prolog) | < 100ms |
| Fan-out decision (Python fallback) | < 1ms |
| Self-review deterministic checks (50 files) | < 5s |
| Self-review LLM call | < 30s |
| uv sync | < 60s |
| aider prompt construction | < 50ms |
| CXP packet routing (process()) | < 5ms |
File Structure
packages/orchestrata-codedirector/
├── pyproject.toml
└── src/orchestrata/volks/codedirector/
├── __init__.py
├── volk.py # CodeDirectorVolk (main entry point)
├── implementation.py # Skeleton, swarm, prompt helpers
├── review.py # self_review_loop, fix delegation
├── review_checks.py # Deterministic AST/ruff checks
├── prompts.py # CODEDIRECTOR_SYSTEM_PROMPT, SELF_REVIEW_PROMPT, constants
└── scaffold/
├── __init__.py
├── types.py # MethodSpec, ClassSpec, ModuleSpec, ProjectSpec
├── parser.py # parse_file_tree, parse_api_spec, parse_code_blocks
├── generator.py # generate_skeleton (Jinja2-based)
└── templates/ # pyproject.toml.j2, module.py.j2, conftest.py.j2, init.py.j2
Visual Architecture
Class Diagram
Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 15:).
classDiagram-direction LR
class ArchitectAgent {
$agent_type: ClassVar[str] = 'U:Ar'
---
+__init__(model: str = 'claude-3-5-haiku', agent_name: str = '')
+async analyze_impact(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async design_solution(requirements: dict[str, Any]): dict[str, Any]
+async review_architecture(architecture: dict[str, Any]): dict[str, Any]
}
class BaseAgent <<pydantic>> {
-model: str = Field(default='claude-3-5-haiku', description='Model identifier for the agent', min_length=1, strict=True)
-agent_id: str = Field(default='', description='Unique agent identifier', strict=True)
-agent_name: str = Field(default='', description='Human-readable agent name', strict=True)
$agent_type: ClassVar[str] = 'U:Base'
$_instance_counters: ClassVar[dict[str, int]] = {}
---
{@classmethod} +validate_model(v: str): str
+__init__(**data: Any): None
#_generate_unique_id(): str
+model_post_init(__context: Any): None
+async receive_message(message: Any, sender: str | None = None): Any
}
class CodeDirectorAgent {
$agent_type: ClassVar[str] = 'U:Cd'
---
+__init__(model: str = 'claude-3-5-sonnet', agent_name: str = '')
+async execute_edit(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async review_code(code: str, requirements: dict[str, Any]): dict[str, Any]
+async implement_feature(spec: dict[str, Any]): dict[str, Any]
}
class QualityAssuranceAgent {
$agent_type: ClassVar[str] = 'U:Qa'
---
+__init__(model: str = 'claude-3-5-sonnet', agent_name: str = '')
+async review_edit(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async run_tests(test_suite: str): dict[str, Any]
+async audit_security(code: str): dict[str, Any]
}
class UserExperienceAgent {
$agent_type: ClassVar[str] = 'U:Ux'
---
+__init__(model: str = 'claude-3-5-haiku', agent_name: str = '')
+async review_ux(file_path: str, old_string: str, new_string: str, context: dict[str, Any] | None = None): dict[str, Any]
+async design_ui(requirements: dict[str, Any]): dict[str, Any]
+async evaluate_accessibility(ui: dict[str, Any]): dict[str, Any]
}
BaseAgent <|-- ArchitectAgent
BaseModel <|-- BaseAgent
BaseAgent <|-- CodeDirectorAgent
BaseAgent <|-- QualityAssuranceAgent
BaseAgent <|-- UserExperienceAgent
US-001: Skeleton-First Implementation (Critical)
As a system operator I want a deterministic project skeleton generated before any LLM code generation So that the junior never has to invent file structure or class shapes
Acceptance Criteria:
- U:Cd receives
implementpacket with file_tree and api_spec - ScaffoldGenerator creates all directories, init.py files, pyproject.toml, and module stubs
- Stubs have correct class names, method signatures, and
NotImplementedErrorbodies - Skeleton is passed to J:Junior via skeleton_files payload field
- aider_prompt instructs junior to implement bodies only, not create new files
US-002: Swarm Parallel Coding (High)
As a system operator I want large projects (≥2 source files) to be coded in parallel So that implementation is faster than serial execution
Acceptance Criteria:
- Fan-out decision returns
allowed=Truefor ≥2 source files - SwarmCoordinator is invoked with skeleton_files and source_files
- Shard results aggregated into unified files_created list
- Swarm artifact logged with shard success/failure counts
implementation_readypacket includesswarm: Trueflag
US-003: Serial Junior Delegation (High)
As a system operator I want small projects (<2 source files) to route to a single junior So that overhead of swarm coordination is avoided
Acceptance Criteria:
- Fan-out returns
allowed=Falsefor <2 source files - Serial path builds aider_prompt (skeleton-based or fallback)
- CXP packet dispatched to J:Junior with subject
implement - U:Cd awaits
implementation_completebefore proceeding
US-004: Self-Review Quality Gate (High)
As a system operator I want U:Cd to review junior output before sending to HUMAN So that common defects are caught without full QA engagement
Acceptance Criteria:
- Deterministic checks run first (SYNTAX, IMPORTS, DEPENDENCY_DECLARED)
- LLM review uses SELF_REVIEW_PROMPT with file contents
- FAIL verdict triggers targeted fix via junior driver
- PASS verdict exits loop and proceeds to
implementation_ready - Loop terminates at MAX_SELF_REVIEW_CYCLES even without PASS
US-005: QA Fix Loop (High)
As a system operator I want U:Qa fix requests routed back through J:Junior So that QA-identified issues are addressed with the same implementation tooling
Acceptance Criteria:
- U:Cd receives
fix_issuespacket from U:Qa - prepare_fix_delegation builds fix-specific aider_prompt with issue list
- J:Junior receives
implementpacket with fix prompt - On
implementation_complete, handle_fix_return emitsimplementation_ready
US-006: Fallback When No Design Docs (Medium)
As a system operator I want U:Cd to proceed even when the architect omits file_tree or api_spec So that simple tasks without full design artifacts still produce code
Acceptance Criteria:
- Missing file_tree or api_spec triggers fallback prompt (build_fallback_prompt)
- Fallback includes task_summary, requirements, architecture text
- Junior receives usable prompt with CODING_STANDARDS appended
- No skeleton files generated in fallback mode
US-007: Kimi-Style Code Block Passthrough (Medium)
As a system operator I want complete code blocks in the API_SPEC to be written directly to disk So that architects using Kimi's output format are handled without re-generation
Acceptance Criteria:
- parse_code_blocks detects fenced code blocks keyed by filename
- Populated code_blocks dict triggers _write_code_blocks path
- Standard stub generation is skipped
- Written files appear in created_files list
Standardized Acceptance Criteria
| ID | Story | Criterion | Verification |
|---|---|---|---|
| AC-001 | US-001 | ScaffoldGenerator creates all directories from FILE_TREE before any module stub is written | Unit test asserting directory existence before file creation |
| AC-002 | US-001 | Every parsed class gets a stub with raise NotImplementedError in method bodies |
Inspect generated file content for NotImplementedError |
| AC-003 | US-001 | pyproject.toml.j2 template produces valid TOML with all parsed dependencies | python -m tomllib parse test |
| AC-004 | US-001 | context.json written to project_dir root with status: scaffold_complete | File existence + JSON parse |
| AC-005 | US-002 | Fan-out decision queries Prolog when prolog instance is available | Integration test with real Prolog engine |
| AC-006 | US-002 | Python fallback returns allowed=True for ≥2 source files | Unit test with 0, 1, 2, 5 source files |
| AC-007 | US-002 | SwarmCoordinator receives skeleton_files and source_files as separate arguments | Integration test tracing SwarmCoordinator.execute_swarm call |
| AC-008 | US-003 | Serial path builds skeleton-based prompt when skeleton_files is populated | Unit test: assert prompt contains "SKELETON FILES TO IMPLEMENT" |
| AC-009 | US-003 | Serial path builds fallback prompt when skeleton_files is not provided | Unit test: assert prompt starts with "Create the following project" |
| AC-010 | US-003 | append_prompt_extras appends CODING_STANDARDS to every aider_prompt | Assert CODING_STANDARDS substring in final prompt |
| AC-011 | US-004 | Deterministic SYNTAX check detects SyntaxError files before LLM review | Unit test with malformed .py file |
| AC-012 | US-004 | Deterministic IMPORTS check flags third-party import missing from pyproject.toml | Unit test with undeclared import |
| AC-013 | US-004 | REVIEW_VERDICT: PASS exits the self-review loop immediately | Verify cycle count = 1 when junior output passes |
| AC-014 | US-004 | Loop exits after MAX_SELF_REVIEW_CYCLES even if review never reaches PASS | Integration test with permanent FAIL condition |
| AC-015 | US-005 | prepare_fix_delegation includes the full issues list in aider_prompt | Assert issues appear in junior's implement packet payload |
| AC-016 | US-005 | handle_fix_return returns implementation_ready packet to HUMAN | Assert packet subject and to_agent |
| AC-017 | US-006 | generate_skeleton_files returns [] when file_tree is not provided | Unit test with absent design docs |
| AC-018 | US-007 | parse_code_blocks extracts code from **Module: \pkg.module`**` style headers |
Unit test with Kimi-format API_SPEC fixture |
| AC-019 | US-007 | src/src/ double-nesting is corrected by regex normalization in parser | Unit test with dotted path starting with "src." |
| AC-020 | US-001 | uv sync subprocess is called after pyproject.toml creation | Integration test confirming uv sync invocation |
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-04-04 | Mohamed | Initial spec — complete implementation documented |
| 1.1.0 | 2026-04-09 | Mohamed | Added Functional Requirements (FR-001 to FR-038), API Contracts, Non-Functional Requirements, Examples, Security, Governance, Integration Points, Testing sections. Renamed E-nnn error IDs to ERR-nnn. Renamed Spec Versioning to Revision History. Merged Definition of Done into Success Criteria. |