conductor(followup): metadata_promotion_20260624 - track artifacts (886 lines)

The actual fix for the 4.01e22 combinatoric explosion. Promotes
Metadata: TypeAlias = dict[str, Any] to @dataclass(frozen=True, slots=True)
and migrates all 695 consumer functions + 213 access sites (107 .get +
106 subscript) to direct field access.

TIER-1 READ AGENTS.md + conductor/workflow.md + conductor/edit_workflow.md
+ conductor/code_styleguides/data_oriented_design.md + conductor/code_styleguides/error_handling.md + conductor/code_styleguides/type_aliases.md + docs/reports/SSDL_CAMPAIGN_ABORTED_20260624.md + src/type_aliases.py + scripts/code_path_audit/code_path_audit.py + scripts/code_path_audit/code_path_audit_ssdl.py before this commit.

Why this fixes 4.01e22:
- The combinatoric explosion is from dict[str, Any] type-dispatch at every
  entry.get('key', default) site (per SSDL post-mortem)
- Each access has 3 branches: is None, getattr, default
- 695 consumers * ~2 branches each = 1390 branches in the sum
- 2^1390 ≈ 4.01e22 (the measured baseline)
- Promotion to @dataclass with direct field access = 0 branches per access
- Expected drop: 4.014e+22 -> < 1e+20 (>= 2 orders of magnitude)

10 VCs:
- VC1: Metadata is @dataclass(frozen=True, slots=True), not dict[str, Any]
- VC2: 107 .get sites replaced
- VC3: 106 subscript sites replaced
- VC4: 12+ tests pass in tests/test_metadata_dataclass.py
- VC5: 5 sub-aggregate TypeAliases (CommsLogEntry, HistoryMessage, FileItem,
       ToolDefinition, ToolCall) all point to the new Metadata
- VC6: Effective codepaths < 1e+20
- VC7: All 7 audit gates pass --strict
- VC8: 10/11 batched test tiers PASS
- VC9: End-of-track report written
- VC10: New regression-guard test file exists

5-phase phased migration (smallest sub-aggregate first):
- Phase 1: CommsLogEntry (~150 sites in session_logger, multi_agent_conductor, app_controller)
- Phase 2: HistoryMessage (~80 sites in ai_client)
- Phase 3: FileItem (~200 sites in aggregate, app_controller, gui_2)
- Phase 4: ToolDefinition+ToolCall (~150 sites in mcp_client, ai_client tool loop)
- Phase 5: Metadata direct usage (~115 sites catch-all)

6 phases total (0 + 5 + verification). 18-21 atomic commits.

blocked_by: code_path_audit_phase_3_provider_state_20260624 (recommended prerequisite;
the two tracks are orthogonal so they can run in parallel; listed as blocked_by
for sequencing preference not strict blocking)
This commit is contained in:
ed
2026-06-25 12:06:50 -04:00
parent dc397db7ed
commit e50bebddd9
5 changed files with 886 additions and 0 deletions
@@ -0,0 +1,68 @@
{
"track_id": "metadata_promotion_20260624",
"name": "Metadata Promotion: dict[str, Any] -> @dataclass(frozen=True, slots=True)",
"status": "active",
"type": "fix",
"parent": "any_type_componentization_20260621",
"grandparent": "code_path_audit_20260607",
"date_created": "2026-06-25",
"created_by": "tier1-orchestrator",
"blocks": [],
"blocked_by": {
"code_path_audit_phase_3_provider_state_20260624": "pending (not started yet; recommended prerequisite to run in parallel)"
},
"scope": {
"new_files": [
"tests/test_metadata_dataclass.py",
"docs/reports/metadata_promotion_progress.md"
],
"modified_files": [
"src/type_aliases.py"
],
"consumer_files": [
"src/session_logger.py",
"src/multi_agent_conductor.py",
"src/app_controller.py",
"src/ai_client.py",
"src/aggregate.py",
"src/gui_2.py",
"src/mcp_client.py",
"src/models.py",
"src/paths.py",
"src/synthesis_formatter.py"
]
},
"verification_criteria": [
"Metadata is @dataclass(frozen=True, slots=True), not dict[str, Any]",
"All 107 .get('key', ...) access sites on Metadata consumers replaced",
"All 106 ['key'] subscript access sites on Metadata consumers replaced",
"tests/test_metadata_dataclass.py: 12+ tests pass",
"All 5 sub-aggregate TypeAliases (CommsLogEntry, HistoryMessage, FileItem, ToolDefinition, ToolCall) point to the new Metadata",
"Effective codepaths drops by >= 2 orders of magnitude (< 1e+20; was 4.014e+22)",
"All 7 audit gates pass --strict (no regression)",
"10/11 batched test tiers PASS (RAG flake acceptable)",
"End-of-track report written (docs/reports/TRACK_COMPLETION_metadata_promotion_20260624.md)",
"New regression-guard test file (tests/test_metadata_dataclass.py)"
],
"estimated_effort": {
"method": "scope (per workflow.md \u00a7Tier 1 Track Initialization Rules). NO day estimates.",
"scope": "1 source file replaced (src/type_aliases.py: 30 lines -> ~200 lines for the dataclass) + 1 new test file (12+ tests) + 10 consumer files modified (~213 access sites total) + 6 phase checkpoint commits; estimated 18-21 atomic commits total"
},
"risk_register": [
"R1 (medium): 213 access sites have polymorphic keys that don't fit cleanly into a single dataclass - mitigated by Optional[T] for all fields + from_dict() classmethod + to_dict() for serialization",
"R2 (low): Some sites do entry['key'] with dynamic keys - mitigated by keeping dict-style access for dynamic keys via entry.to_dict()[var_name]",
"R3 (low): to_dict() round-trip loses information for nested dicts - mitigated by careful implementation; nested dicts pass through as dict[str, Any]",
"R4 (medium): Some sites mutate entry (e.g., entry['key'] = value); dataclass is frozen - mitigated by audit + replacement with dataclasses.replace()",
"R5 (low): Migration breaks regression-guard tests - mitigated by per-phase regression-guard test runs",
"R6 (high): 695 consumer functions are too many for one track - mitigated by 5-phase sub-aggregate migration; each phase independent",
"R7 (medium): Dict-shape used for JSON-serialized payloads (comms.log); dataclass breaks JSON layer - mitigated by to_dict() + from_dict() methods on the dataclass"
],
"out_of_scope": [
"Modifications to src/code_path_audit*.py (the audit infrastructure is correct)",
"The 4 NG1 + 7 NG2 audit violations (already addressed in dc397db7)",
"The 4.01e22's nil-check component (per SSDL post-mortem; minor contributor)",
"The RAG test pre-existing flake (per docs/reports/SSDL_CAMPAIGN_ABORTED_20260624.md Out of Scope)",
"New src/<thing>.py files (per AGENTS.md hard rule; the dataclass goes in src/type_aliases.py)",
"The 5 sub-aggregates becoming separate dataclasses each (overkill; they share the same Metadata base)"
]
}