96 KiB
Directive Preset System Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Replace the single flat current_baseline.md preset with a layered preset system: a curated baseline.md (57 directives + 4 non-directive context files), 12 engagement presets that inherit baseline, 15 new op-specific directives, a deduplicated .warm.md, and an extended aggregate tool that resolves ## Inherits and surfaces ## Non-directive context.
Architecture: The aggregate tool (scripts/aggregate_directives.py) is extended to parse two new preset sections (## Inherits and ## Non-directive context), recursively flatten the parent's directives + non-directive files into the child's list (dedup on path), read each directive's v1.md and each non-directive file's full body, and return one concatenated blob. Preset files are markdown (no YAML/TOML). Engagement presets list only their targeted additions; baseline provides the foundation.
Tech Stack: Python 3.11+, 1-space indent, type hints, @dataclass(frozen=True, slots=True) for any new data types, re for preset parsing, pathlib.Path for file I/O, pytest for tests.
Spec: docs/superpowers/specs/2026-07-05-directive-preset-system-design.md
File Structure
Files to create:
conductor/directives/presets/baseline.md— curated 57 BASELINE directives + 4 non-directive context filesconductor/directives/presets/audit.md— inherits baseline, adds 3 audit directivesconductor/directives/presets/fix_tests.md— inherits baseline, adds 23 testing + 2 regression-fixconductor/directives/presets/implement_feature.md— inherits baseline, adds testing + APP subsetsconductor/directives/presets/refactor.md— inherits baseline, adds testing + 2 refactorconductor/directives/presets/new_script_tool.md— inherits baseline, adds 2 script directivesconductor/directives/presets/meta_tooling.md— inherits baseline, adds 1 APP:mcp + 1 meta-toolingconductor/directives/presets/directives_curation.md— inherits baseline, adds META + documentation + 1 curationconductor/directives/presets/documentation.md— inherits baseline, adds 3 documentation + 1 doc-updateconductor/directives/presets/media_analysis.md— inherits baseline, adds 2 media-analysisconductor/directives/presets/ideation.md— inherits baseline, adds 7 planning + 1 ideationconductor/directives/presets/tier2_autonomous.md— inherits baseline, adds tier2-sandbox + testing + delegation- 15 new directive directories under
conductor/directives/<name>/each withv1.md+meta.md tests/test_aggregate_directives_presets.py— tests for Inherits + Non-directive context
Files to modify:
scripts/aggregate_directives.py— add## Inheritsresolution +## Non-directive contextsection parsing + outputconductor/directives/tags.toml— add 15 new directive entriesconductor/directives/presets/current_baseline.md— mark deprecated in Notesconductor/tier2/agents/tier2-autonomous.warm.md— strip inline sections covered by directives, update preset pathscripts/tier2/setup_tier2_clone_directives.ps1— change-PresetPathdefault totier2_autonomous.md
Phase 1: Extend aggregate_directives.py (Inherits + Non-directive context)
Focus: Add ## Inherits recursive resolution and ## Non-directive context file reading to the aggregate tool. TDD — write failing tests first, implement to pass.
Task 1.1: Write failing tests for Inherits resolution
Files:
-
Create:
tests/test_aggregate_directives_presets.py -
Create:
tests/artifacts/_pytest_tmp/preset_child_test/(temp preset fixtures) -
Step 1: Write the failing test for Inherits
Create tests/test_aggregate_directives_presets.py:
"""Tests for aggregate_directives preset inheritance and non-directive context."""
from __future__ import annotations
import sys
from pathlib import Path
import pytest
# Add scripts/ to sys.path so we can import aggregate_directives
SCRIPTS_DIR = Path(__file__).resolve().parent.parent / "scripts"
if str(SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPTS_DIR))
from aggregate_directives import parse_preset_sections, resolve_inheritance, aggregate_directives
class TestParsePresetSections:
"""Test the new section-based parser that extracts Inherits, Directives, Non-directive context."""
def test_parse_returns_three_sections(self, tmp_path: Path):
preset = tmp_path / "test_preset.md"
preset.write_text("""# Preset: test
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- foo: conductor/directives/foo/v1.md
- bar: conductor/directives/bar/v1.md
## Non-directive context
Read each file below as full documents.
- project rules: AGENTS.md
## Notes
test
""", encoding="utf-8")
sections = parse_preset_sections(preset)
assert sections.inherits == "baseline"
assert len(sections.directives) == 2
assert sections.directives[0] == ("foo", Path("conductor/directives/foo/v1.md"))
assert sections.directives[1] == ("bar", Path("conductor/directives/bar/v1.md"))
assert len(sections.non_directive_context) == 1
assert sections.non_directive_context[0] == ("project rules", Path("AGENTS.md"))
def test_parse_preset_without_inherits(self, tmp_path: Path):
preset = tmp_path / "test_preset.md"
preset.write_text("""# Preset: test
## Directives to warm
- foo: conductor/directives/foo/v1.md
## Non-directive context
- doc: AGENTS.md
""", encoding="utf-8")
sections = parse_preset_sections(preset)
assert sections.inherits == ""
assert len(sections.directives) == 1
assert len(sections.non_directive_context) == 1
def test_parse_preset_without_non_directive_context(self, tmp_path: Path):
preset = tmp_path / "test_preset.md"
preset.write_text("""# Preset: test
## Directives to warm
- foo: conductor/directives/foo/v1.md
""", encoding="utf-8")
sections = parse_preset_sections(preset)
assert sections.inherits == ""
assert len(sections.directives) == 1
assert sections.non_directive_context == []
class TestResolveInheritance:
"""Test that resolve_inheritance merges parent directives into child, dedup on name."""
def test_child_directives_plus_parent_directives(self, tmp_path: Path):
parent = tmp_path / "parent.md"
parent.write_text("""# Preset: parent
## Directives to warm
- alpha: conductor/directives/alpha/v1.md
- beta: conductor/directives/beta/v1.md
""", encoding="utf-8")
child = tmp_path / "child.md"
child.write_text("""# Preset: child
## Inherits
parent
## Directives to warm
- beta: conductor/directives/beta/v1.md
- gamma: conductor/directives/gamma/v1.md
""", encoding="utf-8")
merged = resolve_inheritance(child, root=tmp_path)
names = [n for n, _ in merged.directives]
assert names == ["beta", "gamma", "alpha"]
assert len(merged.non_directive_context) == 0
def test_child_wins_on_directive_conflict(self, tmp_path: Path):
parent = tmp_path / "parent.md"
parent.write_text("""# Preset: parent
## Directives to warm
- shared: conductor/directives/shared_parent/v1.md
""", encoding="utf-8")
child = tmp_path / "child.md"
child.write_text("""# Preset: child
## Inherits
parent
## Directives to warm
- shared: conductor/directives/shared_child/v1.md
""", encoding="utf-8")
merged = resolve_inheritance(child, root=tmp_path)
paths = [p for _, p in merged.directives]
assert Path("conductor/directives/shared_child/v1.md") in paths
assert Path("conductor/directives/shared_parent/v1.md") not in paths
def test_non_directive_context_merges_dedup_on_path(self, tmp_path: Path):
parent = tmp_path / "parent.md"
parent.write_text("""# Preset: parent
## Directives to warm
- alpha: conductor/directives/alpha/v1.md
## Non-directive context
- rules: AGENTS.md
- product: conductor/product.md
""", encoding="utf-8")
child = tmp_path / "child.md"
child.write_text("""# Preset: child
## Inherits
parent
## Directives to warm
- beta: conductor/directives/beta/v1.md
## Non-directive context
- rules: AGENTS.md
- tech: conductor/tech-stack.md
""", encoding="utf-8")
merged = resolve_inheritance(child, root=tmp_path)
paths = [p for _, p in merged.non_directive_context]
assert Path("AGENTS.md") in paths
assert Path("conductor/product.md") in paths
assert Path("conductor/tech-stack.md") in paths
assert paths.count(Path("AGENTS.md")) == 1
def test_three_level_inheritance(self, tmp_path: Path):
grandparent = tmp_path / "grandparent.md"
grandparent.write_text("""# Preset: grandparent
## Directives to warm
- alpha: conductor/directives/alpha/v1.md
""", encoding="utf-8")
parent = tmp_path / "parent.md"
parent.write_text("""# Preset: parent
## Inherits
grandparent
## Directives to warm
- beta: conductor/directives/beta/v1.md
""", encoding="utf-8")
child = tmp_path / "child.md"
child.write_text("""# Preset: child
## Inherits
parent
## Directives to warm
- gamma: conductor/directives/gamma/v1.md
""", encoding="utf-8")
merged = resolve_inheritance(child, root=tmp_path)
names = [n for n, _ in merged.directives]
assert "alpha" in names
assert "beta" in names
assert "gamma" in names
def test_inheritance_loop_detected(self, tmp_path: Path):
a = tmp_path / "a.md"
a.write_text("""# Preset: a
## Inherits
b
## Directives to warm
- alpha: conductor/directives/alpha/v1.md
""", encoding="utf-8")
b = tmp_path / "b.md"
b.write_text("""# Preset: b
## Inherits
a
## Directives to warm
- beta: conductor/directives/beta/v1.md
""", encoding="utf-8")
with pytest.raises(ValueError, match="inheritance loop"):
resolve_inheritance(a, root=tmp_path)
- Step 2: Run tests to verify they fail
Run: uv run pytest tests/test_aggregate_directives_presets.py -v
Expected: FAIL with ImportError: cannot import name 'parse_preset_sections' from 'aggregate_directives'
Task 1.2: Implement parse_preset_sections + resolve_inheritance + aggregate with non-directive context
Files:
-
Modify:
scripts/aggregate_directives.py(the full file — rewrite with new functions) -
Step 1: Implement the new parsing + inheritance + non-directive context
Replace the full content of scripts/aggregate_directives.py with:
#!/usr/bin/env python3
"""Aggregate directive bodies from a preset markdown file.
Supports three preset sections:
## Inherits — name of parent preset (resolved recursively, 3-level max)
## Directives to warm — list of <name>: <path to v1.md>
## Non-directive context — list of <description>: <path to full markdown file>
Child directives + non-directive files override parent on name/path conflict.
"""
from __future__ import annotations
import argparse
import re
import sys
from dataclasses import dataclass, field
from pathlib import Path
if hasattr(sys.stdout, "reconfigure"):
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
if hasattr(sys.stderr, "reconfigure"):
try:
sys.stderr.reconfigure(encoding="utf-8")
except Exception:
pass
REPO_ROOT = Path(__file__).resolve().parent.parent
ENTRY_RE = re.compile(r"^\s*-\s+(?P<name>[^\s:]+)\s*:\s*(?P<path>\S+)\s*$")
EXPECTED_PATTERN_TEMPLATE = r"^conductor/directives/{name}/v\d+\.md$"
MAX_INHERIT_DEPTH = 3
@dataclass(frozen=True, slots=True)
class PresetSections:
inherits: str
directives: list[tuple[str, Path]]
non_directive_context: list[tuple[str, Path]]
def parse_preset_sections(preset_path: Path) -> PresetSections:
"""Parse a preset markdown file into Inherits, Directives, Non-directive context."""
if not preset_path.exists():
raise FileNotFoundError("preset file not found: " + str(preset_path))
text = preset_path.read_text(encoding="utf-8")
inherits: str = ""
directives: list[tuple[str, Path]] = []
non_directive: list[tuple[str, Path]] = []
current_section: str = ""
for line in text.splitlines():
if line.startswith("## Inherits"):
current_section = "inherits"
continue
if line.startswith("## Directives to warm"):
current_section = "directives"
continue
if line.startswith("## Non-directive context"):
current_section = "non_directive"
continue
if line.startswith("## ") or line.startswith("# "):
current_section = ""
continue
if current_section == "inherits" and line.strip():
inherits = line.strip()
elif current_section in ("directives", "non_directive"):
m = ENTRY_RE.match(line)
if m:
name = m.group("name")
rel_path = Path(m.group("path"))
if current_section == "directives":
directives.append((name, rel_path))
else:
non_directive.append((name, rel_path))
return PresetSections(inherits=inherits, directives=directives, non_directive_context=non_directive)
def resolve_inheritance(
preset_path: Path,
root: Path | None = None,
_visited: frozenset[str] | None = None,
_depth: int = 0,
) -> PresetSections:
"""Resolve a preset, recursively flattening parent directives + non-directive files."""
if root is None:
root = REPO_ROOT
p = preset_path if preset_path.is_absolute() else (root / preset_path).resolve()
if _visited is None:
_visited = frozenset()
key = str(p)
if key in _visited:
raise ValueError("inheritance loop detected at " + key)
if _depth > MAX_INHERIT_DEPTH:
raise ValueError("inheritance depth exceeds " + str(MAX_INHERIT_DEPTH) + " at " + key)
sections = parse_preset_sections(p)
if not sections.inherits:
return sections
parent_name = sections.inherits
parent_path = (root / "conductor" / "directives" / "presets" / (parent_name + ".md")).resolve()
if not parent_path.exists():
raise FileNotFoundError("parent preset not found: " + str(parent_path))
parent = resolve_inheritance(parent_path, root=root, _visited=_visited | {key}, _depth=_depth + 1)
merged_directives: list[tuple[str, Path]] = []
child_names: set[str] = {n for n, _ in sections.directives}
for name, path in parent.directives:
if name not in child_names:
merged_directives.append((name, path))
for name, path in sections.directives:
merged_directives.append((name, path))
merged_non_directive: list[tuple[str, Path]] = []
child_paths: set[Path] = {p for _, p in sections.non_directive_context}
for desc, path in parent.non_directive_context:
if path not in child_paths:
merged_non_directive.append((desc, path))
for desc, path in sections.non_directive_context:
merged_non_directive.append((desc, path))
return PresetSections(inherits="", directives=merged_directives, non_directive_context=merged_non_directive)
def aggregate_directives(
preset_path: str | Path,
*,
max_chars: int = 0,
project_root: str | Path | None = None,
) -> str:
"""
Read preset at preset_path, resolve inheritance, read each directive's v1.md
and each non-directive-context file, concatenate into a single text blob.
Preset format:
## Inherits <parent_name>
## Directives to warm (list of <name>: <relative path to v1.md>)
## Non-directive context (list of <description>: <relative path>)
Directives appear first (same ===== banner format as before), then a
NON-DIRECTIVE CONTEXT section appends each non-directive file's full body.
"""
root = Path(project_root).resolve() if project_root is not None else REPO_ROOT
p = Path(preset_path)
if not p.is_absolute():
p = (root / p).resolve()
if not p.exists():
raise FileNotFoundError("preset file not found: " + str(p))
sections = resolve_inheritance(p, root=root)
if not sections.directives and not sections.non_directive_context:
raise ValueError("no directive or non-directive entries found in " + str(p))
missing: list[tuple[str, Path]] = []
directive_bodies: list[tuple[str, str]] = []
for name, rel in sections.directives:
abs_path = (root / rel).resolve()
if not abs_path.exists():
missing.append((name, abs_path))
continue
try:
rel_str = abs_path.relative_to(root).as_posix()
except ValueError:
rel_str = str(abs_path)
pattern = EXPECTED_PATTERN_TEMPLATE.format(name=re.escape(name))
if not re.match(pattern, rel_str):
print("WARNING: " + name + ": path " + str(abs_path) + " does not match pattern conductor/directives/" + name + "/vN.md; including anyway", file=sys.stderr)
try:
body = abs_path.read_text(encoding="utf-8")
except UnicodeDecodeError as e:
raise ValueError(name + ": UTF-8 decode error in " + str(abs_path) + ": " + str(e)) from e
directive_bodies.append((name, body))
if missing:
names = ", ".join(n for n, _ in missing)
raise FileNotFoundError("missing v1.md files for directives: " + names)
non_directive_bodies: list[tuple[str, str]] = []
for desc, rel in sections.non_directive_context:
abs_path = (root / rel).resolve()
if not abs_path.exists():
print("WARNING: non-directive context file not found: " + str(abs_path), file=sys.stderr)
continue
try:
body = abs_path.read_text(encoding="utf-8")
except UnicodeDecodeError as e:
raise ValueError(desc + ": UTF-8 decode error in " + str(abs_path) + ": " + str(e)) from e
non_directive_bodies.append((desc, body))
out_lines: list[str] = []
for name, body in directive_bodies:
out_lines.append("=" * 40)
out_lines.append(name)
out_lines.append("=" * 40)
out_lines.append("")
out_lines.append(body.rstrip("\n"))
out_lines.append("")
out_lines.append("")
if non_directive_bodies:
out_lines.append("=" * 40)
out_lines.append("NON-DIRECTIVE CONTEXT")
out_lines.append("=" * 40)
out_lines.append("")
for desc, body in non_directive_bodies:
out_lines.append("--- " + desc + " ---")
out_lines.append("")
out_lines.append(body.rstrip("\n"))
out_lines.append("")
out_lines.append("")
rendered = "\n".join(out_lines)
if max_chars > 0 and len(rendered) > max_chars:
truncated = rendered[:max_chars]
suffix = "\n\n[truncated: showing " + str(max_chars) + " of " + str(len(rendered)) + " chars; omit max_chars for full text]"
rendered = truncated + suffix
return rendered
def aggregate(preset_path: Path, output_path: Path | None) -> int:
try:
rendered = aggregate_directives(preset_path)
except (FileNotFoundError, ValueError) as e:
print("ERROR: " + str(e), file=sys.stderr)
return 1
if output_path:
output_path.write_text(rendered, encoding="utf-8")
print("Wrote " + str(rendered.count("=" * 40) // 2) + " sections to " + str(output_path), file=sys.stderr)
else:
sys.stdout.write(rendered)
if not rendered.endswith("\n"):
sys.stdout.write("\n")
return 0
def main() -> int:
parser = argparse.ArgumentParser(description="Aggregate directive bodies from a preset markdown file.")
parser.add_argument("preset", type=Path, help="Path to the preset markdown file")
parser.add_argument("-o", "--output", type=Path, default=None, help="Write output to file instead of stdout")
args = parser.parse_args()
if not args.preset.exists():
print("ERROR: preset file not found: " + str(args.preset), file=sys.stderr)
return 1
output = args.output.resolve() if args.output else None
return aggregate(args.preset.resolve(), output)
if __name__ == "__main__":
sys.exit(main())
- Step 2: Run tests to verify they pass
Run: uv run pytest tests/test_aggregate_directives_presets.py -v
Expected: PASS (all 7 tests)
- Step 3: Run existing aggregate to verify backward compat (no Inherits in current_baseline.md)
Run: uv run python scripts/aggregate_directives.py conductor/directives/presets/current_baseline.md -o tests/artifacts/_pytest_tmp/agg_compat_test.txt
Expected: exit 0, output file contains 172 directive sections, no NON-DIRECTIVE CONTEXT section (current_baseline.md has no ## Non-directive context section)
- Step 4: Commit
git add scripts/aggregate_directives.py tests/test_aggregate_directives_presets.py
git commit -m "feat(aggregate): add Inherits resolution + Non-directive context to preset parser"
Task 1.3: Write integration test for non-directive context in the aggregate output
Files:
-
Modify:
tests/test_aggregate_directives_presets.py -
Step 1: Add integration test for non-directive context in aggregate_directives output
Append to tests/test_aggregate_directives_presets.py:
class TestAggregateWithNonDirectiveContext:
"""Integration: aggregate_directives returns non-directive files in a separate section."""
def test_aggregate_includes_non_directive_section(self, tmp_path: Path):
directives_dir = tmp_path / "conductor" / "directives" / "alpha"
directives_dir.mkdir(parents=True)
(directives_dir / "v1.md").write_text("# Alpha rule\n\nDo the thing.\n", encoding="utf-8")
context_file = tmp_path / "AGENTS.md"
context_file.write_text("# Project Rules\n\nRule 1.\n", encoding="utf-8")
preset = tmp_path / "test_preset.md"
preset.write_text("""# Preset: test
## Directives to warm
- alpha: conductor/directives/alpha/v1.md
## Non-directive context
- project rules: AGENTS.md
""", encoding="utf-8")
rendered = aggregate_directives(str(preset), project_root=str(tmp_path))
assert "alpha" in rendered
assert "Alpha rule" in rendered
assert "NON-DIRECTIVE CONTEXT" in rendered
assert "Project Rules" in rendered
assert rendered.index("alpha") < rendered.index("NON-DIRECTIVE CONTEXT")
def test_aggregate_non_directive_section_after_directives(self, tmp_path: Path):
directives_dir = tmp_path / "conductor" / "directives" / "beta"
directives_dir.mkdir(parents=True)
(directives_dir / "v1.md").write_text("# Beta rule\n\nDo beta.\n", encoding="utf-8")
context_file = tmp_path / "conductor" / "product.md"
context_file.parent.mkdir(parents=True, exist_ok=True)
context_file.write_text("# Product\n\nVision.\n", encoding="utf-8")
preset = tmp_path / "test_preset.md"
preset.write_text("""# Preset: test
## Directives to warm
- beta: conductor/directives/beta/v1.md
## Non-directive context
- product: conductor/product.md
""", encoding="utf-8")
rendered = aggregate_directives(str(preset), project_root=str(tmp_path))
assert "Beta rule" in rendered
assert "Product" in rendered
assert rendered.index("Beta rule") < rendered.index("NON-DIRECTIVE CONTEXT")
assert "product" in rendered.lower() or "Product" in rendered
- Step 2: Run tests to verify they pass
Run: uv run pytest tests/test_aggregate_directives_presets.py -v
Expected: PASS (all 9 tests)
- Step 3: Commit
git add tests/test_aggregate_directives_presets.py
git commit -m "test(aggregate): add integration tests for non-directive context in aggregate output"
Phase 2: Create baseline preset + verify
Focus: Write baseline.md with the 57 BASELINE directives + 4 non-directive context files. Verify the aggregate tool resolves it correctly against the real repo.
Task 2.1: Create baseline.md
Files:
-
Create:
conductor/directives/presets/baseline.md -
Step 1: Write baseline.md
Create conductor/directives/presets/baseline.md:
# Preset: baseline
The curated baseline — directives required to do anything in the codebase without creating entropy. Type promotion, edit discipline, git hard bans, research-first, error handling, state management, process anti-patterns. Excludes anything tier-specific, app-subsystem-specific, testing-specific, documentation-specific, or meta-directive. Engagement presets inherit this and add targeted subsets.
## Directives to warm
Read each file below before any action.
- atomic_per_task_commits: conductor/directives/atomic_per_task_commits/v1.md
- git_hard_bans: conductor/directives/git_hard_bans/v1.md
- timeline_is_immutable: conductor/directives/timeline_is_immutable/v1.md
- verbose_commit_message_ban: conductor/directives/verbose_commit_message_ban/v1.md
- verify_before_editing: conductor/directives/verify_before_editing/v1.md
- edit_small_incremental: conductor/directives/edit_small_incremental/v1.md
- mandatory_research_first: conductor/directives/mandatory_research_first/v1.md
- ast_parse_insufficient: conductor/directives/ast_parse_insufficient/v1.md
- ast_verify_class_methods_after_edit: conductor/directives/ast_verify_class_methods_after_edit/v1.md
- decorator_orphan_pitfall: conductor/directives/decorator_orphan_pitfall/v1.md
- preserve_line_endings: conductor/directives/preserve_line_endings/v1.md
- contract_change_audit: conductor/directives/contract_change_audit/v1.md
- search_all_call_sites_after_signature_change: conductor/directives/search_all_call_sites_after_signature_change/v1.md
- anti_entropy_state_audit_before_adding: conductor/directives/anti_entropy_state_audit_before_adding/v1.md
- no_diagnostic_noise: conductor/directives/no_diagnostic_noise/v1.md
- no_comments_in_body: conductor/directives/no_comments_in_body/v1.md
- one_space_indent: conductor/directives/one_space_indent/v1.md
- type_hints_required: conductor/directives/type_hints_required/v1.md
- no_new_src_files_without_permission: conductor/directives/no_new_src_files_without_permission/v1.md
- file_naming_convention: conductor/directives/file_naming_convention/v1.md
- large_files_are_fine: conductor/directives/large_files_are_fine/v1.md
- core_value_read_first: conductor/directives/core_value_read_first/v1.md
- ban_any_type: conductor/directives/ban_any_type/v1.md
- ban_dict_any: conductor/directives/ban_dict_any/v1.md
- ban_dict_get_on_known_fields: conductor/directives/ban_dict_get_on_known_fields/v1.md
- ban_getattr_dispatch: conductor/directives/ban_getattr_dispatch/v1.md
- ban_hasattr_dispatch: conductor/directives/ban_hasattr_dispatch/v1.md
- ban_optional_returns: conductor/directives/ban_optional_returns/v1.md
- ban_local_imports: conductor/directives/ban_local_imports/v1.md
- ban_prefix_aliasing: conductor/directives/ban_prefix_aliasing/v1.md
- ban_repeated_from_dict: conductor/directives/ban_repeated_from_dict/v1.md
- boundary_layer_exception: conductor/directives/boundary_layer_exception/v1.md
- metadata_boundary_type: conductor/directives/metadata_boundary_type/v1.md
- per_aggregate_dataclass_promotion: conductor/directives/per_aggregate_dataclass_promotion/v1.md
- typed_dataclass_fields: conductor/directives/typed_dataclass_fields/v1.md
- nil_sentinel_pattern: conductor/directives/nil_sentinel_pattern/v1.md
- result_error_pattern: conductor/directives/result_error_pattern/v1.md
- missing_data_renders_as_em_dash_not_crash: conductor/directives/missing_data_renders_as_em_dash_not_crash/v1.md
- comprehensive_logging: conductor/directives/comprehensive_logging/v1.md
- modular_controller_pattern: conductor/directives/modular_controller_pattern/v1.md
- strict_state_management: conductor/directives/strict_state_management/v1.md
- inherited_cruft_ask_first: conductor/directives/inherited_cruft_ask_first/v1.md
- deduction_loop_limit: conductor/directives/deduction_loop_limit/v1.md
- report_instead_of_fix_ban: conductor/directives/report_instead_of_fix_ban/v1.md
- scope_creep_track_doc_ban: conductor/directives/scope_creep_track_doc_ban/v1.md
- reproduction_before_fix: conductor/directives/reproduction_before_fix/v1.md
- single_hypothesis_minimal_test: conductor/directives/single_hypothesis_minimal_test/v1.md
- three_fix_failures_question_architecture: conductor/directives/three_fix_failures_question_architecture/v1.md
- cheap_fix_first_investigation_phases: conductor/directives/cheap_fix_first_investigation_phases/v1.md
- evidence_before_completion_claims: conductor/directives/evidence_before_completion_claims/v1.md
- verify_clean_baseline_before_starting: conductor/directives/verify_clean_baseline_before_starting/v1.md
- master_branch_default: conductor/directives/master_branch_default/v1.md
- pathlib_read_write_no_newline_kwarg: conductor/directives/pathlib_read_write_no_newline_kwarg/v1.md
- sdm_dependency_tags: conductor/directives/sdm_dependency_tags/v1.md
- convention_enforcement_4_mechanisms: conductor/directives/convention_enforcement_4_mechanisms/v1.md
- skill_check_before_clarifying: conductor/directives/skill_check_before_clarifying/v1.md
- no_content_duplication_across_agent_docs: conductor/directives/no_content_duplication_across_agent_docs/v1.md
## Non-directive context
Read each file below as full documents (NOT as directives — these carry product/tech/architecture context the directives reinforce but do not fully encode).
- project rules: AGENTS.md
- product vision: conductor/product.md
- product guidelines: conductor/product-guidelines.md
- tech stack: conductor/tech-stack.md
## Notes
The 57 BASELINE directives — rules required to do anything in the codebase without creating entropy. Classification based on the 2026-07-05 audit of all 172 directives (see docs/superpowers/specs/2026-07-05-directive-preset-system-design.md §2.4). The 4 non-directive context files are the product/tech docs agents tend to skip. Replaces current_baseline.md as the curated default; current_baseline.md is retained as the original control group.
- Step 2: Verify the aggregate resolves baseline.md correctly
Run: uv run python scripts/aggregate_directives.py conductor/directives/presets/baseline.md -o tests/artifacts/_pytest_tmp/agg_baseline_test.txt
Expected: exit 0, output file contains 57 directive sections + 1 NON-DIRECTIVE CONTEXT section with AGENTS.md, product.md, product-guidelines.md, tech-stack.md bodies.
- Step 3: Verify the directive count is exactly 57
Run: uv run python -c "from pathlib import Path; import sys; sys.path.insert(0, 'scripts'); from aggregate_directives import resolve_inheritance; s = resolve_inheritance(Path('conductor/directives/presets/baseline.md')); print(len(s.directives)); print(len(s.non_directive_context))"
Expected: 57 then 4.
- Step 4: Commit
git add conductor/directives/presets/baseline.md
git commit -m "feat(directives): add curated baseline.md preset (57 BASELINE + 4 non-directive context)"
Phase 3: Create 15 new op-specific directives
Focus: Create the 15 new directives that fill engagement-preset gaps. Each follows the existing <name>/v1.md + meta.md convention. These are new rules (no prior source to verbatim-lift); the meta.md records "new rule, no prior source."
Task 3.1: Create the 3 audit directives
Files:
-
Create:
conductor/directives/audit_script_as_gate/v1.md+meta.md -
Create:
conductor/directives/audit_walks_filesystem_fresh/v1.md+meta.md -
Create:
conductor/directives/baseline_capture_before_work/v1.md+meta.md -
Step 1: Write audit_script_as_gate
Create conductor/directives/audit_script_as_gate/v1.md:
# Audit scripts that classify or summarize must have a `--strict` quality gate that exits 1 on regression
## What it says
Every audit script in `scripts/audit_*.py` that produces classified output (weak types, exception handling, tier2 leaks, etc.) MUST implement a `--strict` mode that exits non-zero when the audit finds violations. The default mode (no `--strict`) is informational — it prints a human-readable report and exits 0. The `--strict` mode is the CI gate.
## Why
An audit without a gate is a suggestion. An audit with a `--strict` gate is a convention enforced before merge. The project's 4 existing audit scripts (`audit_weak_types.py`, `audit_exception_handling.py`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) all follow this pattern. New audit scripts MUST follow it too.
## The pattern
```python
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--strict", action="store_true", help="Exit 1 on any violation")
parser.add_argument("--json", action="store_true", help="Machine-readable output")
args = parser.parse_args()
violations = run_audit()
if args.json:
print(json.dumps(violations))
else:
print_human_report(violations)
if args.strict and violations:
return 1
return 0
See also
conductor/directives/convention_enforcement_4_mechanisms— the 4-mechanism enforcement model (styleguide + checklist + audit script + CI gate)conductor/directives/quality_gate_catches_broken_classifier_before_ship— the quality gate for classifier scripts
Create `conductor/directives/audit_script_as_gate/meta.md`:
```markdown
# audit_script_as_gate
## v1
**Why this iteration:** New rule, no prior source. Encodes the pattern already followed by the 4 existing audit scripts (`audit_weak_types.py`, `audit_exception_handling.py`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) so new audit scripts follow the same `--strict` gate convention.
**Source:** new rule (pattern inferred from existing `scripts/audit_*.py`)
---
**Lifted:** 2026-07-05
- Step 2: Write audit_walks_filesystem_fresh
Create conductor/directives/audit_walks_filesystem_fresh/v1.md:
# Audit scripts walk the filesystem fresh on every run — never pin to a historical snapshot
## What it says
Audit scripts MUST walk the filesystem fresh on every invocation. They MUST NOT cache the file list, pin to a historical snapshot, or read from a stale index. Each run is a fresh walk of `src/`, `tests/`, `scripts/`, or whatever directory the audit targets.
## Why
A stale audit misses regressions. If the audit reads from a cached file list (e.g., a JSON index written last session), it will not see files added, renamed, or deleted since. The audit's value is "what does the codebase look like RIGHT NOW." A historical snapshot answers the wrong question.
## The pattern
```python
# WRONG: read from a cached index
files = json.loads(Path("tests/artifacts/file_index.json").read_text())
# RIGHT: walk fresh
files = list(Path("src").rglob("*.py"))
See also
conductor/directives/generation_script_walks_filesystem_fresh_each_run— the same rule for generation/index scriptsconductor/directives/audit_script_as_gate— the--strictgate companion
Create `conductor/directives/audit_walks_filesystem_fresh/meta.md`:
```markdown
# audit_walks_filesystem_fresh
## v1
**Why this iteration:** New rule, no prior source. Companion to `generation_script_walks_filesystem_fresh_each_run` but scoped to audit scripts specifically.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 3: Write baseline_capture_before_work
Create conductor/directives/baseline_capture_before_work/v1.md:
# Before any track, capture the audit baseline numbers to a file so per-task deltas are auditable
## What it says
Before starting any track that will change the codebase, the agent MUST run the relevant audit scripts (`audit_weak_types.py`, `audit_exception_handling.py`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) and save the baseline output to a file. The per-task commits then show the delta against this baseline.
## Why
Without a baseline, "did this task introduce a regression?" is unanswerable. The agent commits a change, the audit shows 47 violations, but the agent does not know if it was 47 before or 45 before. The baseline file is the "before" snapshot that makes the "after" meaningful.
## The pattern
```bash
# Before the first task
uv run python scripts/audit_weak_types.py --json > tests/artifacts/tier2_state/<track>/baseline_weak_types.json
uv run python scripts/audit_exception_handling.py --json > tests/artifacts/tier2_state/<track>/baseline_exception_handling.json
# After each task, compare
uv run python scripts/audit_weak_types.py --json > tests/artifacts/tier2_state/<track>/after_task_N_weak_types.json
See also
conductor/directives/tier2_pre_flight_audit_gates— the Tier 2 pre-flight audit protocolconductor/directives/verify_clean_baseline_before_starting— verify test baseline before starting
Create `conductor/directives/baseline_capture_before_work/meta.md`:
```markdown
# baseline_capture_before_work
## v1
**Why this iteration:** New rule, no prior source. Encodes the baseline-capture pattern already practiced in `conductor/directives/tier2_pre_flight_audit_gates` but generalized to any track (not just tier2-sandbox).
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 4: Commit
git add conductor/directives/audit_script_as_gate/ conductor/directives/audit_walks_filesystem_fresh/ conductor/directives/baseline_capture_before_work/
git commit -m "feat(directives): add 3 audit-specific directives (gate, fresh-walk, baseline-capture)"
Task 3.2: Create the 2 fix_tests directives
Files:
-
Create:
conductor/directives/regression_bisect_to_clean_baseline/v1.md+meta.md -
Create:
conductor/directives/adapt_test_not_skip_test/v1.md+meta.md -
Step 1: Write regression_bisect_to_clean_baseline
Create conductor/directives/regression_bisect_to_clean_baseline/v1.md:
# When fixing a regression, bisect to the last known-green commit before proposing a fix
## What it says
When a test regresses (was passing, now failing), the agent MUST `git bisect` (or manually bisect by running the test at recent commits) to identify the exact commit that introduced the regression BEFORE proposing a fix. The bisect result tells you what changed; the fix targets the cause, not the symptom.
## Why
Without a bisect, the agent is guessing at the cause. "The test fails because X is null" — but WHY is X null? The bisect points to the commit that made X null. The fix is then surgical: revert or repair the specific change. Without the bisect, the agent adds a null check (treating the symptom) and the real cause (a broken initialization in a different module) ships to production.
## The pattern
```bash
# Identify the last known-green commit
git log --oneline -20
# Run the failing test at recent commits until you find the green->red transition
git stash # if needed to preserve working tree
git switch -c bisect-tmp <older_commit>
uv run pytest tests/test_failing.py -v
# ... repeat until you find the transition commit
git switch - # back to the working branch
git branch -D bisect-tmp
See also
conductor/directives/reproduction_before_fix— reproduce the bug before fixingconductor/directives/single_hypothesis_minimal_test— test one hypothesis at a time
Create `conductor/directives/regression_bisect_to_clean_baseline/meta.md`:
```markdown
# regression_bisect_to_clean_baseline
## v1
**Why this iteration:** New rule, no prior source. The bisect-first pattern is implied by `reproduction_before_fix` but not explicitly stated for regressions.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 2: Write adapt_test_not_skip_test
Create conductor/directives/adapt_test_not_skip_test/v1.md:
# When a test fails due to a production API change, adapt the test to the new contract — never skip it
## What it says
When a test fails because production code changed its public API (function signature, return shape, callable-vs-value), the agent MUST adapt the test to the new contract. The agent MUST NOT add `@pytest.mark.skip` to make the test "pass." Skipping hides the regression; adapting fixes it.
## Why
A skipped test is a test that does not run. It provides zero coverage. The production API changed, the test is the only thing that would catch a consumer of the old API, and skipping it means the consumer breakage ships unnoticed. Adapting the test to the new contract keeps the coverage live.
## The pattern
```python
# WRONG: skip the test
@pytest.mark.skip(reason="API changed")
def test_old_behavior():
...
# RIGHT: adapt to the new contract
def test_new_behavior():
# Old: result = C_LBL (value)
# New: result = C_LBL() (callable)
result = C_LBL()
assert isinstance(result, ImVec4)
See also
conductor/directives/adapt_test_mocks_to_production_api_change— the broader rule for adapting test mocksconductor/directives/no_skip_markers_as_avoidance— skip markers are documentation, not avoidance
Create `conductor/directives/adapt_test_not_skip_test/meta.md`:
```markdown
# adapt_test_not_skip_test
## v1
**Why this iteration:** New rule, no prior source. Companion to `adapt_test_mocks_to_production_api_change` but scoped to the test itself (not the mock). Reinforces `no_skip_markers_as_avoidance` for the API-change case specifically.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 3: Commit
git add conductor/directives/regression_bisect_to_clean_baseline/ conductor/directives/adapt_test_not_skip_test/
git commit -m "feat(directives): add 2 regression-fix directives (bisect-to-baseline, adapt-not-skip)"
Task 3.3: Create the 2 refactor directives
Files:
-
Create:
conductor/directives/refactor_preserves_behavior/v1.md+meta.md -
Create:
conductor/directives/refactor_one_subsystem_per_phase/v1.md+meta.md -
Step 1: Write refactor_preserves_behavior
Create conductor/directives/refactor_preserves_behavior/v1.md:
# A refactor must preserve observable behavior — tests passing before must pass after
## What it says
A refactor is a change to internal structure that does NOT change observable behavior. The contract: every test that passed before the refactor MUST pass after. If a test fails after the refactor, either the refactor broke behavior (fix the refactor) or the test was testing an implementation detail (fix the test — but only if the implementation detail was not part of the public contract).
## Why
A refactor that breaks tests is not a refactor — it's a behavior change disguised as a refactor. The user reviews "refactor" commits differently than "feature" commits; a refactor is expected to be behavior-neutral. If the refactor breaks tests, the user's review assumption (this is safe) is violated.
## The pattern
```bash
# Before refactor: capture the test baseline
uv run python scripts/run_tests_batched.py --tier tier3 > tests/artifacts/tier2_state/<track>/before_refactor.log 2>&1
# After refactor: run the same tier
uv run python scripts/run_tests_batched.py --tier tier3 > tests/artifacts/tier2_state/<track>/after_refactor.log 2>&1
# Compare: every test that passed before must pass after
See also
conductor/directives/contract_change_audit— audit all callers when changing a public interfaceconductor/directives/search_all_call_sites_after_signature_change— search all call sites
Create `conductor/directives/refactor_preserves_behavior/meta.md`:
```markdown
# refactor_preserves_behavior
## v1
**Why this iteration:** New rule, no prior source. The behavior-preservation contract is implicit in the word "refactor" but never explicitly stated.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 2: Write refactor_one_subsystem_per_phase
Create conductor/directives/refactor_one_subsystem_per_phase/v1.md:
# Refactor one subsystem per phase — never touch two subsystems in the same atomic commit
## What it says
A refactor phase targets ONE subsystem (e.g., `src/ai_client.py`, `src/mcp_client.py`, `src/app_controller.py`). Two subsystems in the same phase means the diff is unreviewable: if one subsystem's refactor has a bug, the user cannot revert just that subsystem without also reverting the other.
## Why
The atomic-per-task commit principle extends to refactors. A phase that touches `ai_client.py` AND `mcp_client.py` in the same commit is a phase that cannot be bisected. If the post-refactor tests fail, the bisect points at the one commit that touched both — the agent cannot tell which subsystem caused the failure.
## The pattern
WRONG: one phase, two subsystems
Phase 1: refactor ai_client.py type promotion + refactor mcp_client.py type promotion
RIGHT: two phases, one subsystem each
Phase 1: refactor ai_client.py type promotion Phase 2: refactor mcp_client.py type promotion
## See also
- `conductor/directives/atomic_per_task_commits` — one task = one commit
- `conductor/directives/scope_creep_track_doc_ban` — scope creep is banned
Create conductor/directives/refactor_one_subsystem_per_phase/meta.md:
# refactor_one_subsystem_per_phase
## v1
**Why this iteration:** New rule, no prior source. Extends `atomic_per_task_commits` to the refactor phase granularity.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 3: Commit
git add conductor/directives/refactor_preserves_behavior/ conductor/directives/refactor_one_subsystem_per_phase/
git commit -m "feat(directives): add 2 refactor directives (preserves-behavior, one-subsystem-per-phase)"
Task 3.4: Create the 2 new_script_tool directives
Files:
-
Create:
conductor/directives/scripts_namespace_isolated/v1.md+meta.md -
Create:
conductor/directives/scripts_audit_pattern/v1.md+meta.md -
Step 1: Write scripts_namespace_isolated
Create conductor/directives/scripts_namespace_isolated/v1.md:
# Scripts are namespace-isolated by directory — no `from scripts.foo import bar` across script dirs
## What it says
Script directories (`scripts/`, `scripts/tier2/`, `scripts/audit/`, `scripts/tier2/artifacts/`) are namespace-isolated. A script in one directory MUST NOT import from a script in another directory. Scripts are not a package; they are standalone tools.
## Why
Scripts are throw-away or single-purpose tools. If `scripts/audit_weak_types.py` imports from `scripts/tier2/failcount.py`, then `audit_weak_types.py` depends on the tier2 sandbox's internal state. The dependency makes the audit script fragile (it breaks if tier2 moves) and the tier2 scripts less isolated (they're now part of a graph, not standalone).
## The pattern
```python
# WRONG: cross-directory import
from scripts.tier2.failcount import should_give_up
# RIGHT: copy the needed function into the script, or factor it into src/
See also
conductor/directives/file_naming_convention— the file naming rulesconductor/directives/large_files_are_fine— large files are fine; don't split for modularity
Create `conductor/directives/scripts_namespace_isolated/meta.md`:
```markdown
# scripts_namespace_isolated
## v1
**Why this iteration:** New rule, no prior source. Encodes the existing project practice (scripts do not cross-import) as an explicit directive.
**Source:** new rule (pattern inferred from existing `scripts/` structure)
---
**Lifted:** 2026-07-05
- Step 2: Write scripts_audit_pattern
Create conductor/directives/scripts_audit_pattern/v1.md:
# New audit scripts follow the `audit_<thing>.py` naming + `--json` + `--strict` pattern of the existing 4
## What it says
A new audit script MUST:
1. Be named `scripts/audit_<thing>.py` (not `check_<thing>.py`, not `lint_<thing>.py`).
2. Have a `--help` that explains what it checks and how to fix violations.
3. Have a `--json` mode for CI integration (machine-readable output).
4. Have a default informational mode (exits 0; prints human-readable report).
5. Have a `--strict` mode (exits 1 on any violation; the CI gate).
## Why
The 4 existing audit scripts (`audit_weak_types.py`, `audit_exception_handling.py`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) all follow this pattern. A new audit script that breaks the pattern (e.g., named `check_foo.py` with no `--strict`) is inconsistent — the CI pipeline will not know how to gate on it, and the user will not know how to run it.
## See also
- `conductor/directives/audit_script_as_gate` — the `--strict` gate rule
- `conductor/directives/convention_enforcement_4_mechanisms` — the 4-mechanism model
Create conductor/directives/scripts_audit_pattern/meta.md:
# scripts_audit_pattern
## v1
**Why this iteration:** New rule, no prior source. Encodes the existing audit-script conventions as a directive so new audit scripts follow the same shape.
**Source:** new rule (pattern inferred from existing `scripts/audit_*.py`)
---
**Lifted:** 2026-07-05
- Step 3: Commit
git add conductor/directives/scripts_namespace_isolated/ conductor/directives/scripts_audit_pattern/
git commit -m "feat(directives): add 2 script-authoring directives (namespace-isolated, audit-pattern)"
Task 3.5: Create the remaining 6 directives (meta_tooling, directives_curation, documentation, media_analysis x2, ideation)
Files:
-
Create:
conductor/directives/meta_tooling_no_app_imports/v1.md+meta.md -
Create:
conductor/directives/directive_one_concept_per_file/v1.md+meta.md -
Create:
conductor/directives/doc_update_after_track_ships/v1.md+meta.md -
Create:
conductor/directives/media_source_cited_in_output/v1.md+meta.md -
Create:
conductor/directives/media_analysis_neutral_voice/v1.md+meta.md -
Create:
conductor/directives/ideation_leads_with_recommended/v1.md+meta.md -
Step 1: Write meta_tooling_no_app_imports
Create conductor/directives/meta_tooling_no_app_imports/v1.md:
# Meta-tooling scripts must not import `src/` application modules — the meta-tooling domain is distinct from the application domain
## What it says
Scripts in `scripts/` that are part of the META-TOOLING layer (the agent orchestration, the conductor, the directive system) MUST NOT import application modules from `src/` (e.g., `src/ai_client.py`, `src/app_controller.py`, `src/mcp_client.py`). The meta-tooling domain builds the tool; the application domain is the tool being built.
## Why
The meta-tooling/application boundary (see `docs/guide_meta_boundary.md`) is load-bearing. If a meta-tooling script imports `src/ai_client`, the meta-tooling domain now depends on the application's internal state. A refactor of `ai_client.py` breaks the meta-tooling script. The two domains evolve independently because they are different concerns.
## See also
- `conductor/directives/meta_tooling_app_boundary_check` — the broader boundary-check rule
- `docs/guide_meta_boundary.md` — the canonical boundary guide
Create conductor/directives/meta_tooling_no_app_imports/meta.md:
# meta_tooling_no_app_imports
## v1
**Why this iteration:** New rule, no prior source. Reinforces `meta_tooling_app_boundary_check` at the import level.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 2: Write directive_one_concept_per_file
Create conductor/directives/directive_one_concept_per_file/v1.md:
# One directive per directory — do not combine two rules in one `v1.md`
## What it says
Each directive directory (`conductor/directives/<name>/`) contains exactly ONE rule in its `v1.md`. Do not combine two related-but-distinct rules into a single `v1.md`. If a rule has two parts that could be independently tagged, split into two directives.
## Why
Directives are independently tagged (the 6-dim `tags.toml`), independently composed into presets, and independently tested. A `v1.md` that combines "ban `dict[str, Any]`" and "ban `Optional[T]` returns" cannot be tagged with a single subject (data-structures vs error-handling) and cannot be independently included in a preset (one without the other). One concept per file keeps the directive atomic.
## See also
- `conductor/directives/verbatim_lift_not_rewrite` — the harvest rule
- `conductor/directives/warm_md_duplicates_not_in_place` — the `.warm.md` duplicate rule
Create conductor/directives/directive_one_concept_per_file/meta.md:
# directive_one_concept_per_file
## v1
**Why this iteration:** New rule, no prior source. Encodes the existing practice (every directive is one concept) as an explicit rule for future harvesters.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 3: Write doc_update_after_track_ships
Create conductor/directives/doc_update_after_track_ships/v1.md:
# After a track ships, update the affected `docs/guide_*.md` to reflect the new module structure
## What it says
When a track changes the shape of a module (renames a file, moves a system, adds a new system file), the implementing agent MUST update the corresponding `docs/guide_*.md` to reflect the new structure. This is part of the track's final phase — not a follow-up track.
## Why
A track that only changes code (not docs) is incomplete. The next agent reads `docs/guide_*.md` to understand the module; if the guide is stale, the agent's mental model is wrong from the start. The documentation refresh is the track's handoff to the next agent.
## See also
- `conductor/directives/end_of_track_report_required` — the TRACK_COMPLETION report
- `conductor/directives/chronology_must_regenerate_after_every_track_ship` — the chronology regeneration
Create conductor/directives/doc_update_after_track_ships/meta.md:
# doc_update_after_track_ships
## v1
**Why this iteration:** New rule, no prior source. Encodes the existing "Documentation Refresh Protocol" from `conductor/workflow.md` as a directive.
**Source:** new rule (pattern from `conductor/workflow.md` §"Documentation Refresh Protocol")
---
**Lifted:** 2026-07-05
- Step 4: Write media_source_cited_in_output
Create conductor/directives/media_source_cited_in_output/v1.md:
# Media analysis output must cite the source URL/timestamp for every claim — no unsourced assertions
## What it says
When an agent analyzes content from a media source (YouTube transcript, substack article, tweet, user-provided text), every claim in the output MUST cite the source: the URL, the timestamp (for video/audio), or the paragraph number (for text). Unsourced assertions are banned.
## Why
Media analysis without citations is indistinguishable from hallucination. The user cannot verify a claim like "the author argues X" without knowing where in the source the author said X. The citation is the provenance; without it, the analysis is unverifiable.
## See also
- `conductor/directives/rag_six_rules` — the RAG provenance rule (same principle, different domain)
- `conductor/directives/comprehensive_logging` — comprehensive logging includes source provenance
Create conductor/directives/media_source_cited_in_output/meta.md:
# media_source_cited_in_output
## v1
**Why this iteration:** New rule, no prior source. The citation requirement is the media-analysis equivalent of RAG's provenance rule.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 5: Write media_analysis_neutral_voice
Create conductor/directives/media_analysis_neutral_voice/v1.md:
# Media analysis output uses neutral voice — value judgments about the source content are the user's call, not the agent's
## What it says
When an agent analyzes media content, the output MUST use neutral voice. The agent describes what the source says, summarizes the arguments, extracts the claims — but does NOT evaluate whether the source is "good," "bad," "right," "wrong," "compelling," or "unconvincing." Value judgments are the user's domain.
## Why
The agent is a tool for understanding content, not a critic. If the agent says "this is a compelling argument," the user's own judgment is preempted. The user wants the content extracted and organized; the user decides whether it's compelling.
## See also
- `conductor/directives/neutral_language_for_doc_drift` — neutral language for documentation drift (same principle)
- `conductor/directives/no_performative_agreement_in_review` — no performative agreement (same principle)
Create conductor/directives/media_analysis_neutral_voice/meta.md:
# media_analysis_neutral_voice
## v1
**Why this iteration:** New rule, no prior source. The neutral-voice principle from `neutral_language_for_doc_drift` applied to media analysis.
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 6: Write ideation_leads_with_recommended
Create conductor/directives/ideation_leads_with_recommended/v1.md:
# Ideation sessions lead with a recommended concept + the reasoning, not 3 unranked options
## What it says
When an agent helps the user ideate new concepts, tools, or UX, the output MUST lead with a single recommended concept and the reasoning for why it's the best fit. The agent MAY present 2-3 alternatives after the recommendation, but the recommendation comes first with the reasoning.
## Why
"Here are 3 options, pick one" offloads the synthesis to the user. The user asked for ideation help, not a multiple-choice quiz. The agent has the context; the agent should make the call. The user can reject the recommendation, but starting from a recommendation is faster than starting from a blank list.
## See also
- `conductor/directives/design_leads_with_recommendation` — the brainstorming equivalent
- `conductor/directives/exactly_four_completion_options` — completion options are different (they're structured choices, not ideation)
Create conductor/directives/ideation_leads_with_recommended/meta.md:
# ideation_leads_with_recommended
## v1
**Why this iteration:** New rule, no prior source. Companion to `design_leads_with_recommendation` but scoped to ideation (concept generation) rather than design (architecture selection).
**Source:** new rule
---
**Lifted:** 2026-07-05
- Step 7: Commit
git add conductor/directives/meta_tooling_no_app_imports/ conductor/directives/directive_one_concept_per_file/ conductor/directives/doc_update_after_track_ships/ conductor/directives/media_source_cited_in_output/ conductor/directives/media_analysis_neutral_voice/ conductor/directives/ideation_leads_with_recommended/
git commit -m "feat(directives): add 6 engagement-specific directives (meta-tooling, curation, doc, media x2, ideation)"
Task 3.6: Update tags.toml with the 15 new directives
Files:
-
Modify:
conductor/directives/tags.toml -
Step 1: Add 15 new entries to tags.toml
Append to conductor/directives/tags.toml (after the last existing entry, before EOF):
# 2026-07-05: 15 new engagement-specific directives (directive_preset_system track)
[directive.audit_script_as_gate]
tags = ["process", "verifying", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
[directive.audit_walks_filesystem_fresh]
tags = ["python", "writing", "all-tiers", "architecture", "mandatory", "lifted-from-new-rule"]
[directive.baseline_capture_before_work]
tags = ["process", "verifying", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
[directive.regression_bisect_to_clean_baseline]
tags = ["process", "debugging", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
[directive.adapt_test_not_skip_test]
tags = ["python", "testing", "all-tiers", "styleguide", "mandatory", "lifted-from-new-rule"]
[directive.refactor_preserves_behavior]
tags = ["python", "editing", "all-tiers", "architecture", "mandatory", "lifted-from-new-rule"]
[directive.refactor_one_subsystem_per_phase]
tags = ["process", "editing", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
[directive.scripts_namespace_isolated]
tags = ["python", "writing", "all-tiers", "imports", "mandatory", "lifted-from-new-rule"]
[directive.scripts_audit_pattern]
tags = ["process", "writing", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
[directive.meta_tooling_no_app_imports]
tags = ["python", "writing", "all-tiers", "mcp", "mandatory", "lifted-from-new-rule"]
[directive.directive_one_concept_per_file]
tags = ["process", "writing", "all-tiers", "documentation", "mandatory", "lifted-from-new-rule"]
[directive.doc_update_after_track_ships]
tags = ["process", "writing", "all-tiers", "documentation", "mandatory", "lifted-from-new-rule"]
[directive.media_source_cited_in_output]
tags = ["process", "writing", "all-tiers", "documentation", "mandatory", "lifted-from-new-rule"]
[directive.media_analysis_neutral_voice]
tags = ["process", "writing", "all-tiers", "documentation", "mandatory", "lifted-from-new-rule"]
[directive.ideation_leads_with_recommended]
tags = ["process", "writing", "all-tiers", "conductor", "mandatory", "lifted-from-new-rule"]
- Step 2: Verify tags.toml parses
Run: uv run python -c "import tomllib; tomllib.load(open('conductor/directives/tags.toml','rb')); print('OK')"
Expected: OK
- Step 3: Commit
git add conductor/directives/tags.toml
git commit -m "feat(directives): add 15 new directive entries to tags.toml"
Phase 4: Create 12 engagement presets
Focus: Write the 12 engagement preset files that inherit baseline and add their targeted subsets. Each is a markdown file with ## Inherits, ## Directives to warm, ## Non-directive context, and ## Notes.
Task 4.1: Create audit.md, fix_tests.md, new_script_tool.md, meta_tooling.md
Files:
-
Create:
conductor/directives/presets/audit.md -
Create:
conductor/directives/presets/fix_tests.md -
Create:
conductor/directives/presets/new_script_tool.md -
Create:
conductor/directives/presets/meta_tooling.md -
Step 1: Write audit.md
Create conductor/directives/presets/audit.md:
# Preset: audit
For agents auditing the codebase — running the audit scripts, capturing baselines, classifying violations, and producing audit reports. Adds the 3 audit-specific directives on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- audit_script_as_gate: conductor/directives/audit_script_as_gate/v1.md
- audit_walks_filesystem_fresh: conductor/directives/audit_walks_filesystem_fresh/v1.md
- baseline_capture_before_work: conductor/directives/baseline_capture_before_work/v1.md
## Notes
Engagement preset for the "auditing the codebase" op. Inherits baseline (57) + adds 3 audit-specific directives. Total: 60 directives + 4 non-directive context files (inherited).
- Step 2: Write fix_tests.md
Create conductor/directives/presets/fix_tests.md:
# Preset: fix_tests
For agents fixing test regressions — bisecting to the clean baseline, adapting tests to production API changes, running the batched test runner, and verifying in batch (not isolation). Adds the 23 TARGETED:testing directives + 2 regression-fix directives on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- tdd_red_green_required: conductor/directives/tdd_red_green_required/v1.md
- test_must_fail_for_believed_reason: conductor/directives/test_must_fail_for_believed_reason/v1.md
- test_passing_immediately_proves_nothing: conductor/directives/test_passing_immediately_proves_nothing/v1.md
- test_narrow_not_kitchen_sink: conductor/directives/test_narrow_not_kitchen_sink/v1.md
- batch_verification_not_isolation: conductor/directives/batch_verification_not_isolation/v1.md
- fragile_test_in_batch_is_failing_test: conductor/directives/fragile_test_in_batch_is_failing_test/v1.md
- no_skip_markers_as_avoidance: conductor/directives/no_skip_markers_as_avoidance/v1.md
- ban_arbitrary_core_mocking: conductor/directives/ban_arbitrary_core_mocking/v1.md
- test_instantiation_not_mock_away: conductor/directives/test_instantiation_not_mock_away/v1.md
- adapt_test_mocks_to_production_api_change: conductor/directives/adapt_test_mocks_to_production_api_change/v1.md
- live_gui_poll_not_sleep: conductor/directives/live_gui_poll_not_sleep/v1.md
- live_gui_session_scoped_no_restart: conductor/directives/live_gui_session_scoped_no_restart/v1.md
- no_real_io_during_tests: conductor/directives/no_real_io_during_tests/v1.md
- enforce_no_real_toml_in_tests: conductor/directives/enforce_no_real_toml_in_tests/v1.md
- test_sandbox: conductor/directives/test_sandbox/v1.md
- workspace_paths: conductor/directives/workspace_paths/v1.md
- opt_in_integration_test_via_env_var_marker: conductor/directives/opt_in_integration_test_via_env_var_marker/v1.md
- deterministic_signal_endpoint_pattern: conductor/directives/deterministic_signal_endpoint_pattern/v1.md
- failure_message_actionable_not_vague: conductor/directives/failure_message_actionable_not_vague/v1.md
- three_tier_test_strategy_for_fragile_subsystems: conductor/directives/three_tier_test_strategy_for_fragile_subsystems/v1.md
- test_classification_via_import_presence: conductor/directives/test_classification_via_import_presence/v1.md
- surface_dirty_state_in_test_runner: conductor/directives/surface_dirty_state_in_test_runner/v1.md
- imscope_tuple_return_per_scope_override: conductor/directives/imscope_tuple_return_per_scope_override/v1.md
- regression_bisect_to_clean_baseline: conductor/directives/regression_bisect_to_clean_baseline/v1.md
- adapt_test_not_skip_test: conductor/directives/adapt_test_not_skip_test/v1.md
## Notes
Engagement preset for the "fixing tests based on regressions" op. Inherits baseline (57) + adds 23 TARGETED:testing + 2 regression-fix. Total: 82 directives + 4 non-directive context files (inherited).
- Step 3: Write new_script_tool.md
Create conductor/directives/presets/new_script_tool.md:
# Preset: new_script_tool
For agents creating new script tools under `scripts/`. Adds the 2 script-authoring directives on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- scripts_namespace_isolated: conductor/directives/scripts_namespace_isolated/v1.md
- scripts_audit_pattern: conductor/directives/scripts_audit_pattern/v1.md
## Notes
Engagement preset for the "making new script tools" op. Inherits baseline (57) + adds 2 script-authoring directives. Total: 59 directives + 4 non-directive context files (inherited).
- Step 4: Write meta_tooling.md
Create conductor/directives/presets/meta_tooling.md:
# Preset: meta_tooling
For agents adjusting the meta-tooling layer — the conductor system, the directive harness, the agent prompts, the MCP server. Adds the meta-tooling boundary directive on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- meta_tooling_app_boundary_check: conductor/directives/meta_tooling_app_boundary_check/v1.md
- meta_tooling_no_app_imports: conductor/directives/meta_tooling_no_app_imports/v1.md
## Non-directive context
Read each file below as full documents.
- meta boundary guide: docs/guide_meta_boundary.md
## Notes
Engagement preset for the "adjusting meta-tooling" op. Inherits baseline (57) + adds 1 APP:mcp + 1 new meta-tooling directive + the meta-boundary guide. Total: 59 directives + 5 non-directive context files.
- Step 5: Commit
git add conductor/directives/presets/audit.md conductor/directives/presets/fix_tests.md conductor/directives/presets/new_script_tool.md conductor/directives/presets/meta_tooling.md
git commit -m "feat(directives): add 4 engagement presets (audit, fix_tests, new_script_tool, meta_tooling)"
Task 4.2: Create implement_feature.md, refactor.md, directives_curation.md, documentation.md
Files:
-
Create:
conductor/directives/presets/implement_feature.md -
Create:
conductor/directives/presets/refactor.md -
Create:
conductor/directives/presets/directives_curation.md -
Create:
conductor/directives/presets/documentation.md -
Step 1: Write implement_feature.md
Create conductor/directives/presets/implement_feature.md:
# Preset: implement_feature
For agents implementing a new feature into `./src`, `./simulation`, or `./tests`. Adds the full testing set + the APP-subsystem directives (imgui, app-controller, architecture, rag-memory, mcp) on top of baseline. The agent loads the union; if the feature touches only one subsystem, the irrelevant APP directives are still useful as context.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- tdd_red_green_required: conductor/directives/tdd_red_green_required/v1.md
- test_must_fail_for_believed_reason: conductor/directives/test_must_fail_for_believed_reason/v1.md
- test_passing_immediately_proves_nothing: conductor/directives/test_passing_immediately_proves_nothing/v1.md
- test_narrow_not_kitchen_sink: conductor/directives/test_narrow_not_kitchen_sink/v1.md
- batch_verification_not_isolation: conductor/directives/batch_verification_not_isolation/v1.md
- fragile_test_in_batch_is_failing_test: conductor/directives/fragile_test_in_batch_is_failing_test/v1.md
- no_skip_markers_as_avoidance: conductor/directives/no_skip_markers_as_avoidance/v1.md
- ban_arbitrary_core_mocking: conductor/directives/ban_arbitrary_core_mocking/v1.md
- test_instantiation_not_mock_away: conductor/directives/test_instantiation_not_mock_away/v1.md
- adapt_test_mocks_to_production_api_change: conductor/directives/adapt_test_mocks_to_production_api_change/v1.md
- live_gui_poll_not_sleep: conductor/directives/live_gui_poll_not_sleep/v1.md
- live_gui_session_scoped_no_restart: conductor/directives/live_gui_session_scoped_no_restart/v1.md
- no_real_io_during_tests: conductor/directives/no_real_io_during_tests/v1.md
- enforce_no_real_toml_in_tests: conductor/directives/enforce_no_real_toml_in_tests/v1.md
- test_sandbox: conductor/directives/test_sandbox/v1.md
- workspace_paths: conductor/directives/workspace_paths/v1.md
- opt_in_integration_test_via_env_var_marker: conductor/directives/opt_in_integration_test_via_env_var_marker/v1.md
- deterministic_signal_endpoint_pattern: conductor/directives/deterministic_signal_endpoint_pattern/v1.md
- failure_message_actionable_not_vague: conductor/directives/failure_message_actionable_not_vague/v1.md
- three_tier_test_strategy_for_fragile_subsystems: conductor/directives/three_tier_test_strategy_for_fragile_subsystems/v1.md
- test_classification_via_import_presence: conductor/directives/test_classification_via_import_presence/v1.md
- surface_dirty_state_in_test_runner: conductor/directives/surface_dirty_state_in_test_runner/v1.md
- imscope_tuple_return_per_scope_override: conductor/directives/imscope_tuple_return_per_scope_override/v1.md
- imgui_scope_verification: conductor/directives/imgui_scope_verification/v1.md
- imgui_scope_entered_flag_for_no_op_return: conductor/directives/imgui_scope_entered_flag_for_no_op_return/v1.md
- ui_delegation_for_hot_reload: conductor/directives/ui_delegation_for_hot_reload/v1.md
- modal_explicit_opened_list_for_lifecycle: conductor/directives/modal_explicit_opened_list_for_lifecycle/v1.md
- view_composes_does_not_leak_into_theme_get_color: conductor/directives/view_composes_does_not_leak_into_theme_get_color/v1.md
- float_only_math_for_visual_transforms: conductor/directives/float_only_math_for_visual_transforms/v1.md
- controller_property_delegation_no_dual_state: conductor/directives/controller_property_delegation_no_dual_state/v1.md
- config_state_owner: conductor/directives/config_state_owner/v1.md
- reset_session_preserves_project_path: conductor/directives/reset_session_preserves_project_path/v1.md
- defer_heavy_sdk_imports_to_subprocess: conductor/directives/defer_heavy_sdk_imports_to_subprocess/v1.md
- defer_not_catch_for_native_crashes: conductor/directives/defer_not_catch_for_native_crashes/v1.md
- graceful_optional_dependency_degradation: conductor/directives/graceful_optional_dependency_degradation/v1.md
- submit_io_lazy_pool_recreation: conductor/directives/submit_io_lazy_pool_recreation/v1.md
- log_pruner_backoff_for_locked_files: conductor/directives/log_pruner_backoff_for_locked_files/v1.md
- undo_redo_100_snapshot_capacity: conductor/directives/undo_redo_100_snapshot_capacity/v1.md
- feature_flag_delete_to_turn_off: conductor/directives/feature_flag_delete_to_turn_off/v1.md
- runtime_config_flag_vs_test_env_var_gate: conductor/directives/runtime_config_flag_vs_test_env_var_gate/v1.md
- interceptor_activates_only_on_matching_shape: conductor/directives/interceptor_activates_only_on_matching_shape/v1.md
- quarantine_flag_the_engine_not_shared_types: conductor/directives/quarantine_flag_the_engine_not_shared_types/v1.md
- profile_first_optimize_second: conductor/directives/profile_first_optimize_second/v1.md
- state_visible_at_the_right_layer: conductor/directives/state_visible_at_the_right_layer/v1.md
- per_dimension_pick_dim_not_tool: conductor/directives/per_dimension_pick_dim_not_tool/v1.md
- cache_stable_to_volatile: conductor/directives/cache_stable_to_volatile/v1.md
- rag_six_rules: conductor/directives/rag_six_rules/v1.md
- knowledge_harvest_pattern: conductor/directives/knowledge_harvest_pattern/v1.md
- chroma_cache_path: conductor/directives/chroma_cache_path/v1.md
- per_conversation_scratch_dir: conductor/directives/per_conversation_scratch_dir/v1.md
- file_id_stable_across_rename: conductor/directives/file_id_stable_across_rename/v1.md
- meta_tooling_app_boundary_check: conductor/directives/meta_tooling_app_boundary_check/v1.md
## Notes
Engagement preset for the "implementing a new feature into ./src, ./simulation, or ./tests" op. Inherits baseline (57) + adds 23 TARGETED:testing + 14 APP:architecture + 6 APP:imgui + 3 APP:app-controller + 5 APP:rag-memory + 1 APP:mcp. Total: 109 directives + 4 non-directive context files (inherited). If the blob is too large for the context window, pass a smaller op-specific subset via `max_chars`.
- Step 2: Write refactor.md
Create conductor/directives/presets/refactor.md:
# Preset: refactor
For agents refactoring or overhauling the codebase. Adds the testing set + 2 refactor-specific directives on top of baseline. The refactor must preserve behavior (tests pass before and after); one subsystem per phase.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- tdd_red_green_required: conductor/directives/tdd_red_green_required/v1.md
- test_must_fail_for_believed_reason: conductor/directives/test_must_fail_for_believed_reason/v1.md
- test_passing_immediately_proves_nothing: conductor/directives/test_passing_immediately_proves_nothing/v1.md
- test_narrow_not_kitchen_sink: conductor/directives/test_narrow_not_kitchen_sink/v1.md
- batch_verification_not_isolation: conductor/directives/batch_verification_not_isolation/v1.md
- fragile_test_in_batch_is_failing_test: conductor/directives/fragile_test_in_batch_is_failing_test/v1.md
- no_skip_markers_as_avoidance: conductor/directives/no_skip_markers_as_avoidance/v1.md
- ban_arbitrary_core_mocking: conductor/directives/ban_arbitrary_core_mocking/v1.md
- test_instantiation_not_mock_away: conductor/directives/test_instantiation_not_mock_away/v1.md
- adapt_test_mocks_to_production_api_change: conductor/directives/adapt_test_mocks_to_production_api_change/v1.md
- live_gui_poll_not_sleep: conductor/directives/live_gui_poll_not_sleep/v1.md
- live_gui_session_scoped_no_restart: conductor/directives/live_gui_session_scoped_no_restart/v1.md
- no_real_io_during_tests: conductor/directives/no_real_io_during_tests/v1.md
- enforce_no_real_toml_in_tests: conductor/directives/enforce_no_real_toml_in_tests/v1.md
- test_sandbox: conductor/directives/test_sandbox/v1.md
- workspace_paths: conductor/directives/workspace_paths/v1.md
- opt_in_integration_test_via_env_var_marker: conductor/directives/opt_in_integration_test_via_env_var_marker/v1.md
- deterministic_signal_endpoint_pattern: conductor/directives/deterministic_signal_endpoint_pattern/v1.md
- failure_message_actionable_not_vague: conductor/directives/failure_message_actionable_not_vague/v1.md
- three_tier_test_strategy_for_fragile_subsystems: conductor/directives/three_tier_test_strategy_for_fragile_subsystems/v1.md
- test_classification_via_import_presence: conductor/directives/test_classification_via_import_presence/v1.md
- surface_dirty_state_in_test_runner: conductor/directives/surface_dirty_state_in_test_runner/v1.md
- imscope_tuple_return_per_scope_override: conductor/directives/imscope_tuple_return_per_scope_override/v1.md
- refactor_preserves_behavior: conductor/directives/refactor_preserves_behavior/v1.md
- refactor_one_subsystem_per_phase: conductor/directives/refactor_one_subsystem_per_phase/v1.md
## Notes
Engagement preset for the "refactoring or overhauling the codebase" op. Inherits baseline (57) + adds 23 TARGETED:testing + 2 refactor. Total: 82 directives + 4 non-directive context files (inherited).
- Step 3: Write directives_curation.md
Create conductor/directives/presets/directives_curation.md:
# Preset: directives_curation
For agents improving, curating, or adding workflow directives or context. Adds the 3 META directives + 3 TARGETED:documentation directives + 1 new curation directive on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- verbatim_lift_not_rewrite: conductor/directives/verbatim_lift_not_rewrite/v1.md
- warm_md_duplicates_not_in_place: conductor/directives/warm_md_duplicates_not_in_place/v1.md
- generation_script_walks_filesystem_fresh_each_run: conductor/directives/generation_script_walks_filesystem_fresh_each_run/v1.md
- docs_philosophy_then_boundaries_then_logic_then_verify: conductor/directives/docs_philosophy_then_boundaries_then_logic_then_verify/v1.md
- neutral_language_for_doc_drift: conductor/directives/neutral_language_for_doc_drift/v1.md
- no_conductor_yaml_for_artifacts: conductor/directives/no_conductor_yaml_for_artifacts/v1.md
- directive_one_concept_per_file: conductor/directives/directive_one_concept_per_file/v1.md
## Notes
Engagement preset for the "improving, curating, or adding workflow directives or context" op. Inherits baseline (57) + adds 3 META + 3 TARGETED:documentation + 1 curation. Total: 64 directives + 4 non-directive context files (inherited).
- Step 4: Write documentation.md
Create conductor/directives/presets/documentation.md:
# Preset: documentation
For agents writing or updating codebase documentation (`docs/guide_*.md`, `docs/Readme.md`, `docs/AGENTS.md`). Adds the 3 TARGETED:documentation directives + 1 new doc-update directive on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- docs_philosophy_then_boundaries_then_logic_then_verify: conductor/directives/docs_philosophy_then_boundaries_then_logic_then_verify/v1.md
- neutral_language_for_doc_drift: conductor/directives/neutral_language_for_doc_drift/v1.md
- no_conductor_yaml_for_artifacts: conductor/directives/no_conductor_yaml_for_artifacts/v1.md
- doc_update_after_track_ships: conductor/directives/doc_update_after_track_ships/v1.md
## Non-directive context
Read each file below as full documents.
- docs index: docs/Readme.md
- agent docs mirror: docs/AGENTS.md
## Notes
Engagement preset for the "writing or updating codebase documentation" op. Inherits baseline (57) + adds 3 TARGETED:documentation + 1 doc-update. Total: 61 directives + 6 non-directive context files (4 inherited + 2 added).
- Step 5: Commit
git add conductor/directives/presets/implement_feature.md conductor/directives/presets/refactor.md conductor/directives/presets/directives_curation.md conductor/directives/presets/documentation.md
git commit -m "feat(directives): add 4 engagement presets (implement_feature, refactor, directives_curation, documentation)"
Task 4.3: Create media_analysis.md, ideation.md, tier2_autonomous.md
Files:
-
Create:
conductor/directives/presets/media_analysis.md -
Create:
conductor/directives/presets/ideation.md -
Create:
conductor/directives/presets/tier2_autonomous.md -
Step 1: Write media_analysis.md
Create conductor/directives/presets/media_analysis.md:
# Preset: media_analysis
For agents doing analysis on content from various media sources (YouTube, substack, twitter, user-provided text/markdown). Adds 2 media-analysis directives on top of baseline. No testing directives — media analysis does not touch the test suite.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- media_source_cited_in_output: conductor/directives/media_source_cited_in_output/v1.md
- media_analysis_neutral_voice: conductor/directives/media_analysis_neutral_voice/v1.md
## Notes
Engagement preset for the "doing analysis on content from various media sources" op. Inherits baseline (57) + adds 2 media-analysis. Total: 59 directives + 4 non-directive context files (inherited).
- Step 2: Write ideation.md
Create conductor/directives/presets/ideation.md:
# Preset: ideation
For agents ideating new concepts, tools, or UX with the user. Adds the 7 PROCESS:planning directives + 1 new ideation directive on top of baseline.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- brainstorm_even_for_simple_projects: conductor/directives/brainstorm_even_for_simple_projects/v1.md
- design_leads_with_recommendation: conductor/directives/design_leads_with_recommendation/v1.md
- spec_self_review_four_checks: conductor/directives/spec_self_review_four_checks/v1.md
- plan_steps_2_to_5_minutes_each: conductor/directives/plan_steps_2_to_5_minutes_each/v1.md
- plans_no_placeholders_or_tbds: conductor/directives/plans_no_placeholders_or_tbds/v1.md
- review_plan_critically_before_executing: conductor/directives/review_plan_critically_before_executing/v1.md
- surface_upstream_api_limits_honestly_in_spec: conductor/directives/surface_upstream_api_limits_honestly_in_spec/v1.md
- ideation_leads_with_recommended: conductor/directives/ideation_leads_with_recommended/v1.md
## Notes
Engagement preset for the "ideating new concepts or tools or ux with the user" op. Inherits baseline (57) + adds 7 PROCESS:planning + 1 ideation. Total: 65 directives + 4 non-directive context files (inherited).
- Step 3: Write tier2_autonomous.md
Create conductor/directives/presets/tier2_autonomous.md:
# Preset: tier2_autonomous
The compound preset for Tier-2 autonomous sandbox execution. Inherits baseline + adds the 20 TARGETED:tier2-sandbox + 23 TARGETED:testing + 8 PROCESS:delegation directives. This is the preset the `tier2-autonomous.warm.md` agent prompt warms with.
## Inherits
baseline
## Directives to warm
Read each file below before any action.
- ban_appdata_paths: conductor/directives/ban_appdata_paths/v1.md
- use_batched_test_runner: conductor/directives/use_batched_test_runner/v1.md
- no_output_filtering: conductor/directives/no_output_filtering/v1.md
- prefer_targeted_tier_runs: conductor/directives/prefer_targeted_tier_runs/v1.md
- throwaway_scripts_isolated_subdir: conductor/directives/throwaway_scripts_isolated_subdir/v1.md
- acknowledgment_in_first_commit: conductor/directives/acknowledgment_in_first_commit/v1.md
- end_of_track_report_required: conductor/directives/end_of_track_report_required/v1.md
- tier2_pre_commit_deletion_and_diff_check: conductor/directives/tier2_pre_commit_deletion_and_diff_check/v1.md
- tier2_pre_flight_audit_gates: conductor/directives/tier2_pre_flight_audit_gates/v1.md
- tier2_post_track_ruff_mypy_audit: conductor/directives/tier2_post_track_ruff_mypy_audit/v1.md
- per_phase_metric_regression_fix: conductor/directives/per_phase_metric_regression_fix/v1.md
- run_full_tier_after_phase_refactor: conductor/directives/run_full_tier_after_phase_refactor/v1.md
- user_corrections_log_in_state_toml: conductor/directives/user_corrections_log_in_state_toml/v1.md
- surface_gaps_at_discovery_not_checkpoint: conductor/directives/surface_gaps_at_discovery_not_checkpoint/v1.md
- chronology_must_regenerate_after_every_track_ship: conductor/directives/chronology_must_regenerate_after_every_track_ship/v1.md
- use_git_history_as_classification_source_of_truth: conductor/directives/use_git_history_as_classification_source_of_truth/v1.md
- classifier_must_emit_per_row_evidence: conductor/directives/classifier_must_emit_per_row_evidence/v1.md
- quality_gate_catches_broken_classifier_before_ship: conductor/directives/quality_gate_catches_broken_classifier_before_ship/v1.md
- manual_compaction_only_no_auto_summarize: conductor/directives/manual_compaction_only_no_auto_summarize/v1.md
- preserve_before_compact_archive: conductor/directives/preserve_before_compact_archive/v1.md
- tdd_red_green_required: conductor/directives/tdd_red_green_required/v1.md
- test_must_fail_for_believed_reason: conductor/directives/test_must_fail_for_believed_reason/v1.md
- test_passing_immediately_proves_nothing: conductor/directives/test_passing_immediately_proves_nothing/v1.md
- test_narrow_not_kitchen_sink: conductor/directives/test_narrow_not_kitchen_sink/v1.md
- batch_verification_not_isolation: conductor/directives/batch_verification_not_isolation/v1.md
- fragile_test_in_batch_is_failing_test: conductor/directives/fragile_test_in_batch_is_failing_test/v1.md
- no_skip_markers_as_avoidance: conductor/directives/no_skip_markers_as_avoidance/v1.md
- ban_arbitrary_core_mocking: conductor/directives/ban_arbitrary_core_mocking/v1.md
- test_instantiation_not_mock_away: conductor/directives/test_instantiation_not_mock_away/v1.md
- adapt_test_mocks_to_production_api_change: conductor/directives/adapt_test_mocks_to_production_api_change/v1.md
- live_gui_poll_not_sleep: conductor/directives/live_gui_poll_not_sleep/v1.md
- live_gui_session_scoped_no_restart: conductor/directives/live_gui_session_scoped_no_restart/v1.md
- no_real_io_during_tests: conductor/directives/no_real_io_during_tests/v1.md
- enforce_no_real_toml_in_tests: conductor/directives/enforce_no_real_toml_in_tests/v1.md
- test_sandbox: conductor/directives/test_sandbox/v1.md
- workspace_paths: conductor/directives/workspace_paths/v1.md
- opt_in_integration_test_via_env_var_marker: conductor/directives/opt_in_integration_test_via_env_var_marker/v1.md
- deterministic_signal_endpoint_pattern: conductor/directives/deterministic_signal_endpoint_pattern/v1.md
- failure_message_actionable_not_vague: conductor/directives/failure_message_actionable_not_vague/v1.md
- three_tier_test_strategy_for_fragile_subsystems: conductor/directives/three_tier_test_strategy_for_fragile_subsystems/v1.md
- test_classification_via_import_presence: conductor/directives/test_classification_via_import_presence/v1.md
- surface_dirty_state_in_test_runner: conductor/directives/surface_dirty_state_in_test_runner/v1.md
- imscope_tuple_return_per_scope_override: conductor/directives/imscope_tuple_return_per_scope_override/v1.md
- tier3_worker_amnesia: conductor/directives/tier3_worker_amnesia/v1.md
- tier4_qa_compressed_fix: conductor/directives/tier4_qa_compressed_fix/v1.md
- token_firewall_prevents_bloat: conductor/directives/token_firewall_prevents_bloat/v1.md
- never_inherit_session_history_to_subagent: conductor/directives/never_inherit_session_history_to_subagent/v1.md
- subagent_returns_artifact_not_transcript: conductor/directives/subagent_returns_artifact_not_transcript/v1.md
- agent_prompt_one_independent_domain: conductor/directives/agent_prompt_one_independent_domain/v1.md
- decompose_or_isolate_never_offload: conductor/directives/decompose_or_isolate_never_offload/v1.md
- worker_three_point_abort_check: conductor/directives/worker_three_point_abort_check/v1.md
## Non-directive context
Read each file below as full documents.
- tier2 autonomous guide: docs/guide_tier2_autonomous.md
## Notes
Compound preset for Tier-2 autonomous sandbox execution. Inherits baseline (57) + adds 20 TARGETED:tier2-sandbox + 23 TARGETED:testing + 8 PROCESS:delegation. Total: 108 directives + 5 non-directive context files (4 inherited + 1 added). This is the preset `tier2-autonomous.warm.md` warms with.
- Step 4: Verify each engagement preset resolves correctly via aggregate
Run: uv run python -c "from pathlib import Path; import sys; sys.path.insert(0, 'scripts'); from aggregate_directives import resolve_inheritance; [print(f'{n}: {len(resolve_inheritance(Path(f\"conductor/directives/presets/{n}.md\")).directives)} directives') for n in ['baseline','audit','fix_tests','implement_feature','refactor','new_script_tool','meta_tooling','directives_curation','documentation','media_analysis','ideation','tier2_autonomous']]"
Expected: baseline=57, audit=60, fix_tests=82, implement_feature=109, refactor=82, new_script_tool=59, meta_tooling=59, directives_curation=64, documentation=61, media_analysis=59, ideation=65, tier2_autonomous=108.
- Step 5: Commit
git add conductor/directives/presets/media_analysis.md conductor/directives/presets/ideation.md conductor/directives/presets/tier2_autonomous.md
git commit -m "feat(directives): add 3 engagement presets (media_analysis, ideation, tier2_autonomous)"
Task 4.4: Mark current_baseline.md deprecated
Files:
-
Modify:
conductor/directives/presets/current_baseline.md(Notes section only) -
Step 1: Update the Notes section of current_baseline.md
In conductor/directives/presets/current_baseline.md, replace the ## Notes section's first line. Find the line starting with All v1 (verbatim lifts from current production docs; and prepend a deprecation notice above it:
Insert at the start of the Notes section (after ## Notes):
**DEPRECATED (2026-07-05):** This preset is the original control group from the `directive_hotswap_harness_20260627` track. It lists all 172 directives indiscriminately. The curated replacement is `baseline.md` (57 BASELINE directives + 4 non-directive context files). Engagement presets (`audit.md`, `fix_tests.md`, etc.) inherit `baseline.md` and add targeted subsets. This file is RETAINED as the original control group for future A/B encoding experiments — do not delete. New agents should warm with `baseline.md` or an engagement preset, not this file.
- Step 2: Commit
git add conductor/directives/presets/current_baseline.md
git commit -m "docs(directives): mark current_baseline.md deprecated (retained as control group)"
Phase 5: Dedup .warm.md + update bootstrap default
Focus: Strip the inline bulk-markdown sections from tier2-autonomous.warm.md that are now covered by directives. Update the preset path to tier2_autonomous.md. Update the bootstrap script's default.
Task 5.1: Dedup tier2-autonomous.warm.md
Files:
-
Modify:
conductor/tier2/agents/tier2-autonomous.warm.md -
Step 1: Update the warm-with preset path
In conductor/tier2/agents/tier2-autonomous.warm.md, find the manual-slop_aggregate_directives(preset_path="conductor/directives/presets/current_baseline.md") line and change it to:
manual-slop_aggregate_directives(preset_path="conductor/directives/presets/tier2_autonomous.md")
- Step 2: Strip the "Hard Bans" section
Find the ## Hard Bans (cannot run, enforced at 3 layers) section and its entire body (including the "THE TIMELINE-IS-IMMUTABLE PRINCIPLE" subsection) and remove it. This content is covered by the git_hard_bans, ban_appdata_paths, and timeline_is_immutable directives.
- Step 3: Strip the "Conventions" section
Find the ## Conventions (MUST follow - added 2026-06-17; updated 2026-06-27) section and remove its bullet points about: test runner, never filter test output, prefer targeted tier runs, default branch, line endings, throw-away scripts, end-of-track report, run-time expectation, temp files. These are covered by use_batched_test_runner, no_output_filtering, prefer_targeted_tier_runs, master_branch_default, preserve_line_endings, throwaway_scripts_isolated_subdir, end_of_track_report_required directives. Replace the entire section with a one-line pointer:
## Conventions
The tier2_autonomous.md preset (warmed above) includes the TARGETED:tier2-sandbox directives that encode all sandbox conventions (batched test runner, no output filtering, targeted tier runs, throw-away script paths, end-of-track report, AppData ban, etc.). Follow them.
- Step 4: Strip the "Sub-Agent Delegation" section
Find the ## Sub-Agent Delegation (replaces legacy mma_exec.py — updated 2026-06-27) section and remove it. Covered by tier3_worker_amnesia, tier4_qa_compressed_fix, agent_prompt_one_independent_domain, decompose_or_isolate_never_offload directives.
- Step 5: Strip the "TDD Protocol" section
Find the ## TDD Protocol section and remove it. Covered by tdd_red_green_required and per_phase_metric_regression_fix.
- Step 6: Strip the "Per-Task Commit Protocol" section
Find the ## Per-Task Commit Protocol section and remove it. Covered by atomic_per_task_commits and verbose_commit_message_ban.
- Step 7: Keep "Failcount Contract", "Pre-Delegation Checkpoint", and "Limitations" inline
Do NOT strip these sections. They contain tier-2-specific operational detail (failcount thresholds, git add . safety net, scope limitations) that no directive covers.
- Step 8: Verify the file is syntactically valid markdown + reduced in size
Run: uv run python -c "from pathlib import Path; content = Path('conductor/tier2/agents/tier2-autonomous.warm.md').read_text(encoding='utf-8'); print(f'Size: {len(content)} chars, {content.count(chr(10))} lines')"
Expected: size significantly reduced from ~17940 chars (target ~6-8KB).
- Step 9: Commit
git add conductor/tier2/agents/tier2-autonomous.warm.md
git commit -m "refactor(tier2): dedup tier2-autonomous.warm.md — strip inline sections covered by directives"
Task 5.2: Update setup_tier2_clone_directives.ps1 default preset
Files:
-
Modify:
scripts/tier2/setup_tier2_clone_directives.ps1 -
Step 1: Change the -PresetPath default
In scripts/tier2/setup_tier2_clone_directives.ps1, find the param block:
param(
[string]$MainRepoPath = "C:\projects\manual_slop",
[string]$Tier2ClonePath = "C:\projects\manual_slop_tier2",
[string]$PresetPath = "conductor/directives/presets/current_baseline.md"
)
Change the $PresetPath default to:
[string]$PresetPath = "conductor/directives/presets/tier2_autonomous.md"
- Step 2: Run the script to verify it works with the new default
Run: & "C:\projects\manual_slop\scripts\tier2\setup_tier2_clone_directives.ps1"
Expected: bootstrap completes, [tier2-bootstrap-directives] preset resolved at C:\projects\manual_slop_tier2\conductor\directives\presets\tier2_autonomous.md.
- Step 3: Commit
git add scripts/tier2/setup_tier2_clone_directives.ps1
git commit -m "feat(tier2): update setup_tier2_clone_directives.ps1 default preset to tier2_autonomous.md"
Phase 6: Final verification
Focus: Run the full test suite for the new test file, verify all presets resolve, verify the aggregate tool produces correct output for the new presets.
Task 6.1: Run all tests + verify all presets resolve
- Step 1: Run the aggregate_directives preset tests
Run: uv run pytest tests/test_aggregate_directives_presets.py -v
Expected: all 9 tests PASS.
- Step 2: Verify all 12 presets resolve via the aggregate tool
Run: uv run python -c "from pathlib import Path; import sys; sys.path.insert(0, 'scripts'); from aggregate_directives import aggregate_directives; [aggregate_directives(f'conductor/directives/presets/{n}.md') or print(f'{n}: OK') for n in ['baseline','audit','fix_tests','implement_feature','refactor','new_script_tool','meta_tooling','directives_curation','documentation','media_analysis','ideation','tier2_autonomous']]"
Expected: 12 lines of <name>: OK.
- Step 3: Verify baseline.md returns exactly 57 directives + 4 non-directive context
Run: uv run python -c "from pathlib import Path; import sys; sys.path.insert(0, 'scripts'); from aggregate_directives import resolve_inheritance; s = resolve_inheritance(Path('conductor/directives/presets/baseline.md')); assert len(s.directives) == 57, f'expected 57, got {len(s.directives)}'; assert len(s.non_directive_context) == 4, f'expected 4, got {len(s.non_directive_context)}'; print('baseline: 57 directives + 4 non-directive context OK')"
Expected: baseline: 57 directives + 4 non-directive context OK.
- Step 4: Verify tier2_autonomous.md returns the expected count
Run: uv run python -c "from pathlib import Path; import sys; sys.path.insert(0, 'scripts'); from aggregate_directives import resolve_inheritance; s = resolve_inheritance(Path('conductor/directives/presets/tier2_autonomous.md')); assert len(s.directives) == 108, f'expected 108, got {len(s.directives)}'; assert len(s.non_directive_context) == 5, f'expected 5, got {len(s.non_directive_context)}'; print('tier2_autonomous: 108 directives + 5 non-directive context OK')"
Expected: tier2_autonomous: 108 directives + 5 non-directive context OK.
- Step 5: Verify the .warm.md file is reduced
Run: uv run python -c "from pathlib import Path; content = Path('conductor/tier2/agents/tier2-autonomous.warm.md').read_text(encoding='utf-8'); size = len(content); assert size < 10000, f'expected < 10KB, got {size}'; assert 'tier2_autonomous.md' in content, 'preset path not updated'; assert '## Hard Bans' not in content, 'Hard Bans section not stripped'; assert '## Sub-Agent Delegation' not in content, 'Sub-Agent Delegation not stripped'; print(f'.warm.md: {size} chars OK')"
Expected: .warm.md: <size> chars OK.
- Step 6: Commit the final verification state (if any uncommitted test artifacts)
If there are uncommitted test artifacts in tests/artifacts/_pytest_tmp/, clean them up:
Remove-Item -Recurse -Force tests/artifacts/_pytest_tmp/ -ErrorAction SilentlyContinue
No commit needed if the working tree is clean.
Self-Review Notes
Spec coverage check:
- G1 (baseline preset) → Task 2.1 ✓
- G2 (12 engagement presets) → Tasks 4.1-4.3 ✓
- G3 (preset format extension: Inherits + Non-directive context) → Task 1.2 ✓
- G4 (aggregate tool extended) → Task 1.2 ✓
- G5 (15 new directives) → Tasks 3.1-3.5 ✓
- G6 (.warm.md dedup) → Task 5.1 ✓
- G7 (current_baseline.md retained, marked deprecated) → Task 4.4 ✓
- G8 (setup script default updated) → Task 5.2 ✓
- NFR5 (tags.toml updated) → Task 3.6 ✓
- V1-V5 (verification) → Task 6.1 ✓
Type consistency check: PresetSections dataclass is used consistently in parse_preset_sections, resolve_inheritance, and the tests. Field names match: inherits, directives, non_directive_context.
No placeholders: All steps contain complete code. No "TBD", "implement later", "similar to Task N".