Files
manual_slop/conductor/tracks/metadata_ssdl_defusing_20260624/spec.md
T
ed 7c352e1c30 conductor(followup): code_path_audit_phase_2_20260624 - the actual followup + abort SSDL campaign
VERIFIED STATE OF MASTER a18b8ad6 (just measured):
- 751 Metadata consumers in src/
- 3,454 total branches
- 4.014e+22 effective codepaths (UNCHANGED from the 4.01e+22 baseline)
- 73 nil-check funcs in Metadata consumers (real SSDL measurement)
- 14 module globals still in src/ai_client.py (_anthropic_history + lock, etc.)
- MCP_TOOL_SPECS: list[dict[str, Any]] still in src/mcp_client.py
- src/ai_client.py:908 still uses old NormalizedResponse API (usage_input_tokens=...)
- 3 orphaned modules: mcp_tool_specs, openai_schemas, provider_state (exist, nothing imports)
- 4 pre-existing INTERNAL_OPTIONAL_RETURN violations in external_editor, session_logger, project_manager (NG1)
- 7 pre-existing Optional[T] return-type violations in mcp_client.py:1285,1289 + ai_client.py:159,247,619,673,3115 (NG2)
- audit_weak_types PASS, generate_type_registry PASS, audit_main_thread_imports PASS, audit_no_models_config_io PASS, audit_code_path_audit_coverage PASS, audit_exception_handling (baseline) PASS, audit_optional_in_3_files FAIL (NG2)

SSDL CAMPAIGN ABORT (premise was wrong):
- '6 nil-check functions' was a static text string in src/code_path_audit_gen.py:108, not a runtime measurement
- SSDL detector finds 0 Metadata-typed nil-checks
- The 1 function Tier 2 migrated (_build_files_section_from_items) was a 'path is None' check, NOT a Metadata nil-check
- The 4.01e22 combinatoric explosion is from dict[str, Any] type-dispatch, not nil-checks
- Salvage: NIL_METADATA = {} in src/aggregate.py + 5 tests stay as useful primitives

THE ACTUAL FIX: re-apply any_type_componentization_20260621's 48 call-site migrations
- Phase 1: mcp_tool_specs (8 sites) - 4 in mcp_client.py + 3 in ai_client.py + 1 in mcp_client.py:2747
- Phase 2: openai_schemas (17 sites) - 12 in openai_compatible.py + 5 in 3 send_* functions in ai_client.py; REMOVE the backward-compat __init__ from fix_test_failures_20260624
- Phase 3: provider_state (14 globals + ~27 callers) - 9 send_* functions use get_history('...') instead
- Phase 4: log_registry Session (7 sites)
- Phase 5: api_hooks WebSocketMessage (16 sites)
- Phase 6: NG1 fixups (4 INTERNAL_OPTIONAL_RETURN violations)
- Phase 7: NG2 fixups (7 Optional[T] return-type violations)
- Phase 8: Re-audit (measure new effective-codepaths; target < 1e+20)
- Phase 9: Verification + end-of-track report

VERIFICATION (10 VCs):
- VC1: 3 modules actually used by src/*.py (git grep >= 5 hits in src/, not just in plan/spec text)
- VC2: 14 module globals in src/ai_client.py gone
- VC3: MCP_TOOL_SPECS dict literal gone
- VC4: usage_input_tokens= in src/ai_client.py gone
- VC5: effective codepaths drops >= 2 orders of magnitude (target: 4.014e+22 -> < 1e+20)
- VC6: NG1 fixed (0 INTERNAL_OPTIONAL_RETURN violations)
- VC7: NG2 fixed (0 Optional[T] return-type violations)
- VC8: all 6 audit gates pass --strict
- VC9: 11/11 batched test tiers PASS
- VC10: end-of-track report written

5 files aborted, 5 files created (new track), 1 post-mortem doc.
2026-06-24 16:24:53 -04:00

12 KiB
Raw Blame History

Campaign Specification: metadata_ssdl_defusing_20260624

Overview

3-child campaign to defuse the Metadata aggregate's combinatoric explosion (4.01e22 effective codepaths) via Fleury's SSDL techniques. Each child produces one SSDL primitive, is independently shippable, and is gated by a budget check that re-measures effective codepaths after each child.

The parent audit (code_path_audit_20260607 / AUDIT_REPORT.md Finding 1, CRITICAL) identified 3 specific techniques:

  1. Nil Sentinel [N] for the 6 nil-check functions
  2. Generational Handle wrapping Metadata
  3. Immediate-Mode Cache [Q:key] -> [I:FetchCached] -> [T] for the 123 field-access sites

The campaign executes them in dependency order: child 1 introduces the sentinel fallback that child 2's generation-mismatch path returns to; child 2's stable identity enables child 3's cache keying.

Current State Audit (as of master @ 7a9261c4, post-fix_test_failures_20260624 merge)

The audit baseline is captured in docs/reports/code_path_audit/2026-06-22/AUDIT_REPORT.md:

  • Metadata: 483 producers / 752 consumers / 123 field-access sites (0 typed)
  • Effective codepaths: 4.01e22 (sum of 2^branches across 752 consumers)
  • Branch points: 3466 across consumer functions
  • Nil-check functions: 6 (the is None / == None / != None detection sites)

The behavioral SSDL test exists at tests/test_code_path_audit_ssdl_behavioral.py and uses a synthetic 5-function × 3-if-statements fixture to assert compute_effective_codepaths math (5 × 2^3 = 40). The real-Metadata measurement is captured by src.code_path_audit_ssdl.compute_effective_codepaths(Metadata_profile).

Goals

ID Goal Acceptance
G1 Child 1 (Nil Sentinel) ships: 6 nil-check functions use sentinel-return 6 functions refactored; behavioral test for sentinel; 4.01e22 number drops measurably
G2 Child 2 (Generational Handle) ships: lifetime branches collapse to 1 lookup + 1 generation comparison Registry in place; 1 lookup benchmark; further effective-codepath drop
G3 Child 3 (Field Cache) ships: 123 string-keyed entry.get('key', default) sites become cache hits Cache in place; 123 sites benchmarked; further effective-codepath drop
G4 End-of-campaign report: cumulative effective-codepath measurement vs 4.01e22 baseline docs/reports/TRACK_COMPLETION_metadata_ssdl_defusing_20260624.md written
G5 All 4 audit gates remain clean weak_types ≤ 112, type_registry in sync, main_thread_imports clean, no_models_config_io clean

Non-Goals

  • Touching any aggregate OTHER than Metadata (the audit's other 9 in-scope aggregates + 3 candidates are out of scope; the SSDL primitives established by this campaign can be applied to them in follow-up campaigns)
  • Modifying the audit infrastructure (src/code_path_audit*.py); the campaign USES the audit to measure progress but does not change the audit
  • Refactoring the 7-file split (NG3 from code_path_audit_polish_20260622); that's a separate refactor track
  • Runtime profiling (the campaign uses the static branch_count heuristic; runtime profiling is Track F from the previous menu)

Per-Child Specs

Child 1: metadata_nil_sentinel_20260624 (Nil Sentinel)

Scope: Introduce NIL_METADATA = Metadata(...) constant with safe defaults. Migrate the 6 nil-check functions (detected by src.code_path_audit_ssdl.detect_nil_check_pattern) to sentinel-return: replace if entry is None: ... / if entry == None: ... / if entry != None: ... patterns with entry = entry or NIL_METADATA (or the function's equivalent).

Acceptance:

  • 6 functions refactored
  • 1 behavioral test (tests/test_metadata_nil_sentinel.py): asserts the sentinel is used, asserts the 6 functions no longer have the 3-pattern nil-check branches
  • Budget gate: re-run compute_effective_codepaths(Metadata_profile); if the number drops by < 10%, pause and report

Why first: establishes the sentinel that child 2's generation-mismatch path returns to.

Child 2: metadata_generational_handle_20260624 (Generational Handle)

Scope: Wrap Metadata in (index, generation) resolved through a registry. Validation is one comparison: if metadata.generation != registry.generations[metadata.index], return NIL_METADATA. Otherwise, the value is valid.

Acceptance:

  • MetadataHandleRegistry (or equivalent) introduced in a sensible location (likely src/aggregate.py or a new sibling module per AGENTS.md §File Naming Convention)
  • Migration: the production Metadata value is now wrapped in a handle; lifetime-branch code (e.g., the 3466 branch points that include lifetime checks) collapses to 1 lookup + 1 comparison
  • 1 behavioral test: assert handle lookup is O(1), assert generation mismatch returns sentinel
  • Budget gate: re-run compute_effective_codepaths(Metadata_profile); if the number drops by < 20%, pause and report (the generational handle is expected to produce a larger drop than the sentinel)

Why second: builds on child 1's sentinel as the fallback path. Provides a stable identity for child 3's cache keying.

Child 3: metadata_field_cache_20260624 (Immediate-Mode Cache)

Scope: Introduce MetadataFieldCache[(handle_id, field_name)] -> value. Consumers request (metadata_handle, 'field_name'), get cached value. The 123 string-keyed entry.get('key', default) sites become 123 cache lookups.

Acceptance:

  • MetadataFieldCache introduced
  • Migration: the 123 field-access sites in src/ use the cache
  • 1 behavioral test: assert cache hit, assert cache miss with sentinel fallback
  • Budget gate: re-run compute_effective_codepaths(Metadata_profile); if the number drops by < 30%, pause and report (the cache is expected to produce the largest drop)

Why third: the cache needs the handle's stable identity (child 2) to use as a key.

Budget Gate Protocol

REPLACED by Amendment 1 (post-child-1 finding). See amendment_1_budget_gate_metric.md.

The original "X% drop in compute_effective_codepaths(Metadata_profile)" metric is mathematically broken for this codebase: the sum is dominated by the largest 2^N terms, so removing 1 branch from a 10-branch function drops that function 50% but changes the total sum by < 1 part in 4e22. Child 1 measured -0.1% (within rounding error) despite a successful migration.

The new metric is a simple pattern count, testable with git diff:

  • Child 1 (Nil Sentinel): count of is None / == None / != None patterns in Metadata-typed code paths eliminated
  • Child 2 (Generational Handle): count of lifetime-branch patterns in Metadata-typed code paths eliminated (e.g., if entry.lifetime != current_lifetime: ... replaced with handle.registry_lookup() or NIL_METADATA)
  • Child 3 (Field Cache): count of entry.get('key', default) and entry['key'] patterns in Metadata-typed code paths eliminated (replaced with cache.get(handle, 'key'))

The new gate per child: all targeted patterns in the campaign's scope are eliminated (= 0 remaining after the migration). Tier 2 reports: "before N patterns, after 0 patterns, target met."

The measurement is captured in docs/reports/campaign_measurements_20260624.md (existing file, updated per child) and rolled up into the campaign's end-of-campaign report.

Functional Requirements

FR1: Each child preserves the existing test suite

After each child, all 6 VCs from the parent fix_test_failures_20260624 track remain green: 14 previously-failing tests still pass; no new failures.

FR2: Each child is independently shippable

A child can be merged without the other 2 (the campaign gates are forward-looking; a child that meets its budget is shippable on its own).

FR3: The end-of-campaign report quantifies the cumulative effect

docs/reports/TRACK_COMPLETION_metadata_ssdl_defusing_20260624.md shows: pre-campaign baseline 4.01e22, post-child-1 number, post-child-2 number, post-child-3 number, total reduction.

Non-Functional Requirements

  • NFR1: 1-space indentation (project convention)
  • NFR2: CRLF line endings on Windows
  • NFR3: No comments in source code
  • NFR4: No new pip dependencies
  • NFR5: Per-task atomic commits with git notes
  • NFR6: Each child's Result[T] returns for fallible fns (per conductor/code_styleguides/error_handling.md)
  • NFR7: The new SSDL primitives are exported from a sensible location; no new top-level src/<thing>.py files (per AGENTS.md §File Naming Convention) unless the user explicitly approves

Architecture Reference

  • docs/reports/code_path_audit/2026-06-22/AUDIT_REPORT.md — Finding 1 (CRITICAL) and the 3 proposed fixes
  • src/code_path_audit_ssdl.py:84-100detect_nil_check_pattern (the function that identifies the 6 nil-check sites)
  • src/code_path_audit_ssdl.py:39-55compute_effective_codepaths (the measurement function)
  • src/code_path_audit.py:271-296CANONICAL_MEMORY_DIM and MEMORY_DIM_FILE_HEURISTIC (where to file new primitives)
  • conductor/code_styleguides/data_oriented_design.md — the canonical DOD reference
  • conductor/code_styleguides/error_handling.md — the Result[T] convention
  • conductor/code_styleguides/agent_memory_dimensions.md — the 4 memory dimensions (Metadata is discussion)

Out of Scope

  • Aggregates other than Metadata (FileItem, CommsLogEntry, HistoryMessage, ToolDefinition, ToolCall, Result, the 3 list-typed, the 3 candidates) — the SSDL primitives are general but the campaign is Metadata-specific
  • Modifying src/code_path_audit*.py (the audit infrastructure)
  • Refactoring the 7-file split
  • Runtime profiling (Track F from the previous menu)
  • Modifying the campaign structure (3 children are fixed; adding a 4th is out of scope)

Verification Criteria (Definition of Done)

# Criterion Verification command
VC1 All 3 children SHIPPED Each child track has status = "completed", current_phase = "complete", all phases completed
VC2 End-of-campaign report exists cat docs/reports/TRACK_COMPLETION_metadata_ssdl_defusing_20260624.md shows the 3 measurements + cumulative reduction
VC3 Full test suite remains green uv run python scripts/run_tests_batched.py → all 11 tiers PASS
VC4 4 audit gates remain clean weak_types ≤ 112, type_registry in sync, main_thread_imports clean, no_models_config_io clean
VC5 No new src/<thing>.py files created (per AGENTS.md) git diff master..HEAD --stat -- 'src/*.py' | grep -E 'src/[a-z_]+\.py' returns only the existing src/ modules; the new SSDL primitives live in existing files
VC6 Behavioral tests for each child exist and pass uv run pytest tests/test_metadata_nil_sentinel.py tests/test_metadata_generational_handle.py tests/test_metadata_field_cache.py -v → all pass

Risks

# Risk Likelihood Mitigation
R1 Child 1 doesn't measurably drop the effective-codepaths number low The 6 nil-checks are documented in AUDIT_REPORT.md; their removal MUST drop the number. If not, the audit or the SSDL math is wrong (separate investigation).
R2 Child 2 (generational handle) breaks code that expects raw Metadata medium The handle is a wrapper; consumers can still extract the raw value via .value or similar. Behavioral test verifies backwards-compat for the common cases.
R3 Child 3 (field cache) cache invalidation is wrong medium The cache is keyed by (handle_id, field_name). When the underlying value changes, the handle's generation bumps, invalidating all cache entries for that handle. The cache is a write-through thin wrapper.
R4 The cumulative drop is less than expected (e.g., 4.01e22 → 1e15 instead of 4.01e22 → 1e5) low The campaign's value is in the TECHNIQUE, not the final number. The numbers are heuristic; the actual goal is the structural improvement (sentinel, handle, cache). If the techniques ship, the campaign succeeds regardless of the final heuristic number.
R5 New src/<thing>.py files needed for the SSDL primitives low Per AGENTS.md, helpers go in the parent module. The new primitives live in src/aggregate.py (the parent module for Metadata). If the user explicitly approves new top-level files, the campaign can be extended.