Files
manual_slop/docs/superpowers/plans/2026-07-05-directive-preset-system.md

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 files
  • conductor/directives/presets/audit.md — inherits baseline, adds 3 audit directives
  • conductor/directives/presets/fix_tests.md — inherits baseline, adds 23 testing + 2 regression-fix
  • conductor/directives/presets/implement_feature.md — inherits baseline, adds testing + APP subsets
  • conductor/directives/presets/refactor.md — inherits baseline, adds testing + 2 refactor
  • conductor/directives/presets/new_script_tool.md — inherits baseline, adds 2 script directives
  • conductor/directives/presets/meta_tooling.md — inherits baseline, adds 1 APP:mcp + 1 meta-tooling
  • conductor/directives/presets/directives_curation.md — inherits baseline, adds META + documentation + 1 curation
  • conductor/directives/presets/documentation.md — inherits baseline, adds 3 documentation + 1 doc-update
  • conductor/directives/presets/media_analysis.md — inherits baseline, adds 2 media-analysis
  • conductor/directives/presets/ideation.md — inherits baseline, adds 7 planning + 1 ideation
  • conductor/directives/presets/tier2_autonomous.md — inherits baseline, adds tier2-sandbox + testing + delegation
  • 15 new directive directories under conductor/directives/<name>/ each with v1.md + meta.md
  • tests/test_aggregate_directives_presets.py — tests for Inherits + Non-directive context

Files to modify:

  • scripts/aggregate_directives.py — add ## Inherits resolution + ## Non-directive context section parsing + output
  • conductor/directives/tags.toml — add 15 new directive entries
  • conductor/directives/presets/current_baseline.md — mark deprecated in Notes
  • conductor/tier2/agents/tier2-autonomous.warm.md — strip inline sections covered by directives, update preset path
  • scripts/tier2/setup_tier2_clone_directives.ps1 — change -PresetPath default to tier2_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 scripts
  • conductor/directives/audit_script_as_gate — the --strict gate 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 protocol
  • conductor/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 fixing
  • conductor/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 mocks
  • conductor/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 interface
  • conductor/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 rules
  • conductor/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".