Phase 1 audit confirmed no Ticket dataclass access sites need migration:
- Ticket dataclass consumers in _spawn_worker, mutate_dag, and
multi_agent_conductor.run already use direct field access
- The t.get('id', '') style sites operate on dicts
(self.active_tickets: list[Metadata], topological_sort returns list[dict])
- These dict sites are correctly classified as Metadata collapsed-codepath
per spec FR2
35/35 tests pass. No code changes needed.
26 KiB
Plan: metadata_promotion_20260624
CORRECTED 2026-06-25 (Tier 1 audit). The original plan (commit
e50bebdd, 2026-06-25) proposed a single shared@dataclass(frozen=True, slots=True) Metadatawith ~200 fields for all 5 sub-aggregates. That proposal was REJECTED on 2026-06-25 (user direction): each sub-aggregate is its OWN dataclass with its OWN fields. The corrected plan has 12 phases (one per sub-aggregate), uses existing dataclasses where they exist (Ticket,FileItem,ToolCall,ChatMessage,UsageStats), and adds new per-aggregate dataclasses for the 8 aggregates that don't have one yet. Seedocs/reports/PLANNING_CORRECTION_metadata_promotion_20260625.mdfor the full rationale.
13 phases, 30-35 tasks, 30+ atomic commits. Per-task TDD red-first. Tier 3 workers execute; Tier 2 reviews per phase.
Phase 0: Design the per-aggregate dataclasses + add regression-guard test stubs (5 tasks, 5 commits)
Focus: Add the NEW dataclasses to src/type_aliases.py (the type-system aggregates that don't have a parent module); reuse the existing dataclasses in src/models.py and src/openai_schemas.py. No consumer migration yet.
-
Task 0.1 [Tier 3]: Add NEW dataclasses to
src/type_aliases.py.- WHERE:
src/type_aliases.py(current 30 lines) - WHAT:
- Add
@dataclass(frozen=True, slots=True) class CommsLogEntrywithts, role, kind, direction, model, source_tier, content, error(8 fields, all with defaults) - Add
@dataclass(frozen=True, slots=True) class HistoryMessagewithrole, content, tool_calls, tool_call_id, name, ts(6 fields) - Add
@dataclass(frozen=True, slots=True) class ToolDefinitionwithname, description, parameters, auto_start(4 fields) - Add
@dataclass(frozen=True, slots=True) class SessionInsightswithtotal_tokens, call_count, burn_rate, session_cost, completed_tickets, efficiency(6 fields) - Add
@dataclass(frozen=True, slots=True) class DiscussionSettingswithtemperature, top_p, max_output_tokens(3 fields) - Add
@dataclass(frozen=True, slots=True) class CustomSlicewithtag, comment, start_line, end_line(4 fields) - Add
@dataclass(frozen=True, slots=True) class MMAUsageStatswithmodel, input, output(3 fields) - Add
@dataclass(frozen=True, slots=True) class ProviderPayloadwithscript, args, output, source_tier(4 fields) - Add
@dataclass(frozen=True, slots=True) class UIPanelConfigwithseparate_message_panel, separate_response_panel, separate_tool_calls_panel(3 fields) - Add
@dataclass(frozen=True, slots=True) class PathInfowithlogs_dir, scripts_dir, project_root(3 nested fields) - Each dataclass has a paired
to_dict()(for JSON serialization) andfrom_dict()classmethod (filters unknown keys, per FR5) - KEEP
Metadata: TypeAlias = dict[str, Any]UNCHANGED (the catch-all for collapsed codepaths) - KEEP
CommsLog: TypeAlias = list[CommsLogEntry],History: TypeAlias = list[HistoryMessage],FileItems: TypeAlias = list[FileItem](the list aliases still work; the element types are now per-aggregate dataclasses) - KEEP
JsonValue,JsonPrimitive,CommsLogCallback,FileItemsDiffunchanged
- Add
- HOW:
manual-slop_edit_filefor surgical edits (orwrite_fileif the file is being substantially restructured) - SAFETY:
ast.parseOK;from src.type_aliases import CommsLogEntry, HistoryMessage, ToolDefinition, SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats, ProviderPayload, UIPanelConfig, PathInfoOK; constructors work
- WHERE:
-
COMMIT:
refactor(type_aliases): add per-aggregate dataclasses (CommsLogEntry, HistoryMessage, ToolDefinition, ...)[bacddc85] (Tier 3) -
GIT NOTE: NEW dataclasses added to
src/type_aliases.py.Metadata: TypeAlias = dict[str, Any]is UNCHANGED (the catch-all for collapsed codepaths). No consumer migration yet. -
Task 0.2 [Tier 3]: Add
RAGChunkdataclass tosrc/rag_engine.py.- WHERE:
src/rag_engine.py(the parent module for RAG) - WHAT:
@dataclass(frozen=True, slots=True) class RAGChunkwithdocument, path, score, metadata(4 fields, all with defaults); pairedto_dict()/from_dict() - HOW:
manual-slop_edit_file - SAFETY:
from src.rag_engine import RAGChunkOK; constructor works
- WHERE:
-
COMMIT:
feat(rag_engine): add RAGChunk dataclass[bacddc85] (Tier 3) -
GIT NOTE: NEW dataclass added to
src/rag_engine.py. No consumer migration yet. -
Task 0.3 [Tier 3]: Audit and complete
ContextPresetschema insrc/models.py.- WHERE:
src/models.py(the parent module for ContextPreset) - WHAT:
ContextPresetexists atsrc/models.py:932but is partial. Add missing fields based on access patterns:name, files (FileItems), screenshots (list[str])minimum; audit the actual usage and add any other required fields; ensure pairedto_dict()/from_dict() - HOW:
manual-slop_edit_file - SAFETY: existing
ContextPresetconsumers continue to work; theto_dict()round-trip is lossless
- WHERE:
-
COMMIT:
refactor(models): complete ContextPreset schema with missing fields(Tier 3) -
GIT NOTE:
ContextPresetschema extended. Existing consumers unchanged. -
Task 0.4 [Tier 3]: Create
tests/test_metadata_dataclass.py(split into per-aggregate test files per FR G7).- WHERE: NEW FILES:
tests/test_comms_log_entry.py,tests/test_history_message.py,tests/test_tool_definition.py,tests/test_rag_chunk.py,tests/test_session_insights.py,tests/test_discussion_settings.py,tests/test_custom_slice.py,tests/test_mma_usage_stats.py,tests/test_provider_payload.py,tests/test_ui_panel_config.py,tests/test_path_info.py,tests/test_context_preset_schema.py - WHAT: 5+ tests per file: constructor with kwargs, field access, frozen (raises
FrozenInstanceError),to_dict()/from_dict()round-trip, equality, hashability, default values - HOW:
write_fileper file - SAFETY:
uv run pytest tests/test_comms_log_entry.py -vshows 5/5 pass (and similarly for the other 11 files)
- WHERE: NEW FILES:
-
COMMIT:
test(type_aliases): add per-aggregate dataclass regression-guard suite[bacddc85] (Tier 3) -
GIT NOTE: 12 test files, 5+ tests each. The consumer migration is in subsequent phases; this commit only adds the new dataclasses + tests.
-
Task 0.5 [Tier 2]: Document the FR6 collapsed-codepath classification rule.
- WHERE:
conductor/code_styleguides/type_aliases.md(small clarification, NOT a rewrite) - WHAT: Add a one-paragraph "When to promote to a per-aggregate dataclass" rule: when a sub-aggregate has stable distinct fields, promote it to its OWN dataclass; do NOT share one mega-dataclass across concepts;
Metadata: TypeAlias = dict[str, Any]is preserved for collapsed codepaths (TOML config, generic JSON parsing, polymorphic log dumping) only. Reference this track's correction as the canonical example. - HOW:
manual-slop_edit_file - SAFETY: styleguide is consistent with the corrected design
- WHERE:
-
COMMIT:
docs(styleguides): clarify when to promote to per-aggregate dataclass(Tier 2) -
GIT NOTE: Styleguide clarification. The corrected design is: per-aggregate dataclasses for known sub-aggregates;
Metadata: dict[str, Any]for collapsed codepaths only.
Phase 1: Migrate Ticket consumers (~30 sites, 2 commits)
Focus: Ticket is already a dataclass (src/models.py:302); just migrate the consumers from t.get('id', '') to t.id. The legacy Ticket.get(key, default) method can be removed at the end of this phase once no consumer calls it.
-
Task 1.1 [Tier 3]: Migrate
src/gui_2.pyTicket consumers.- WHERE:
src/gui_2.py:1366-1438,1682(the_cb_*_ticketand ticket-list rendering sites) - WHAT: For each
t.get('id', ''),t.get('depends_on', []),t.get('manual_block', False),t.get('status')→t.id,t.depends_on,t.manual_block,t.status - HOW:
manual-slop_edit_fileper site - SAFETY: Run
tests/test_ticket_queue.py+tests/test_per_ticket_model.py+tests/test_manual_block.py+ the new per-aggregate test files - RESULT: No-op. Audit confirmed
self.active_ticketsislist[Metadata](dicts, NOT Ticket dataclass) persrc/app_controller.py:1110and the comment at:3276"Keep dicts for UI table". The gui_2.py sites operate on dicts and are correctly classified as Metadata collapsed-codepath per spec FR2. No migration needed.
- WHERE:
-
COMMIT: No commit (no code changes). [no-op]
-
GIT NOTE: Audit-only. 35/35 tests pass. No migration needed.
-
Task 1.2 [Tier 3]: Migrate
src/conductor_tech_lead.pyandsrc/app_controller.pyTicket consumers.- WHERE:
src/conductor_tech_lead.py:125;src/app_controller.py:4810-4868(the ticket-list mutation sites) - WHAT: Same pattern as 1.1
- HOW:
manual-slop_edit_fileper site - SAFETY: Same as 1.1
- RESULT: No-op. Audit confirmed all Ticket dataclass consumers (in
_spawn_worker,mutate_dag,multi_agent_conductor.run) already use direct field access (t.id,t.status,t.depends_on, etc.). Thet.get('id', '')style sites operate on dicts (fromconductor_tech_lead.topological_sortreturninglist[dict[str, Any]]and fromself.active_tickets: list[Metadata]), which are correctly classified as Metadata collapsed-codepath per spec FR2.
- WHERE:
-
COMMIT: No commit (no code changes). [no-op]
-
GIT NOTE: Audit-only. 35/35 tests pass. No migration needed.
-
Task 1.3 [Tier 2]: Remove the legacy
Ticket.get(key, default)method.- WHERE:
src/models.py(thegetmethod onTicket) - WHAT: After all consumers have migrated, remove the
getmethod - HOW:
manual-slop_py_remove_def - SAFETY: Re-run the full batched test suite; no remaining
.get(key, default)on Ticket consumers
- WHERE:
-
COMMIT:
refactor(models): remove legacy Ticket.get() method(Tier 2) -
GIT NOTE: Legacy compat method removed. Direct field access is now the only path.
Phase 2: Migrate FileItem consumers (~10 sites, 2 commits)
Focus: FileItem is already a dataclass (src/models.py:533); migrate the consumers.
-
Task 2.1 [Tier 3]: Migrate
src/aggregate.pyFileItem consumers.- WHERE:
src/aggregate.py:418,421 - WHAT:
item.get('custom_slices', [])→item.custom_slices;item.get('content', '')→item.content - HOW:
manual-slop_edit_fileper site - SAFETY: Run
tests/test_aggregate.py+tests/test_file_item_model.py+ the new per-aggregate test files
- WHERE:
-
COMMIT:
refactor(aggregate): migrate FileItem access sites(Tier 3) -
GIT NOTE: Migrated ~5 FileItem access sites.
-
Task 2.2 [Tier 3]: Migrate
src/ai_client.pyandsrc/app_controller.pyFileItem consumers.- WHERE:
src/ai_client.py:2565,2807,2898;src/app_controller.py:3508 - WHAT:
fi.get('path', 'attachment')→fi.path;f['path'] for f in file_items→f.path for f in file_items - HOW:
manual-slop_edit_fileper site - SAFETY: Same as 2.1
- WHERE:
-
COMMIT:
refactor(ai_client,app_controller): migrate FileItem access sites(Tier 3) -
GIT NOTE: Migrated ~5 FileItem access sites across 2 files.
Phase 3: Migrate CommsLogEntry consumers (~30 sites, 3 commits)
Focus: New dataclass added in Phase 0; now wire it into the consumers.
-
Task 3.1 [Tier 3]: Migrate
src/session_logger.py.- WHERE:
src/session_logger.py(~30 access sites; the writer-side) - WHAT:
entry.get('source_tier', 'main')→entry.source_tier;entry.get('model', 'unknown')→entry.model; etc. - HOW:
manual-slop_edit_fileper site - SAFETY: Run
tests/test_session_logger_optimization.py+tests/test_session_logger_reset.py+tests/test_session_logging.py+tests/test_logging_e2e.py+tests/test_comms_log_entry.py
- WHERE:
-
COMMIT:
refactor(session_logger): migrate CommsLogEntry access sites(Tier 3) -
GIT NOTE: Migrated ~30 access sites.
-
Task 3.2 [Tier 3]: Migrate
src/multi_agent_conductor.py(~20 sites) -
Task 3.3 [Tier 3]: Migrate
src/app_controller.pyCommsLogEntry section (~10 sites) -
COMMIT (3.2, 3.3): 2 atomic commits
-
Task 3.4 [Tier 2]: Re-measure effective codepaths after Phase 3.
Phase 4: Migrate HistoryMessage consumers (~20 sites, 1 commit)
Focus: UI-layer discussion history (NOT provider-side ChatMessage; these are distinct layers per data_structure_strengthening_20260606 §3.1).
- Task 4.1 [Tier 3]: Migrate
src/gui_2.pydiscussion UI sites.- WHERE:
src/gui_2.py(~20 sites; the editable per-turn message list) - WHAT:
entry['role']→entry.role; etc. - HOW:
manual-slop_edit_fileper site - SAFETY: Run the per-aggregate test files
- WHERE:
- COMMIT:
refactor(gui_2): migrate HistoryMessage access sites(Tier 3) - GIT NOTE: Migrated ~20 HistoryMessage access sites.
- Task 4.2 [Tier 2]: Re-measure.
Phase 5: Wire ChatMessage into per-vendor send paths (~27 sites, 3 commits)
Focus: ChatMessage is already in src/openai_schemas.py:48; wire it into the per-vendor send paths that were migrated to provider_state.get_history("...") in code_path_audit_phase_3_provider_state_20260624.
- Task 5.1 [Tier 3]: Migrate
_send_anthropicand_send_deepseek(~9 sites) - Task 5.2 [Tier 3]: Migrate
_send_grokand_send_qwen(~9 sites) - Task 5.3 [Tier 3]: Migrate
_send_minimaxand_send_llama(~9 sites) - COMMIT (5.1, 5.2, 5.3): 3 atomic commits
- Task 5.4 [Tier 2]: Re-measure.
Phase 6: Wire UsageStats into per-call usage aggregation (~10 sites, 1 commit)
Focus: UsageStats is already in src/openai_schemas.py:68; wire it into the per-call usage aggregation in app_controller.py.
- Task 6.1 [Tier 3]: Migrate
src/app_controller.py:2299-2309.- WHERE:
src/app_controller.py:2299-2309(themma_tier_usageaggregation sites) - WHAT:
u.get('input_tokens', 0) or 0→u.input_tokens or 0; etc. - HOW:
manual-slop_edit_file - SAFETY: Run
tests/test_token_usage.py+tests/test_usage_analytics_popout_sim.py+tests/test_openai_schemas.py
- WHERE:
- COMMIT:
refactor(app_controller): migrate UsageStats access sites(Tier 3) - GIT NOTE: Migrated ~10 UsageStats access sites.
Phase 7: Wire ToolCall into the tool loop section (~56 sites, 2 commits)
Focus: ToolCall is already in src/openai_schemas.py:32; wire it into the tool loop section in ai_client.py and mcp_client.py.
- Task 7.1 [Tier 3]: Migrate
src/ai_client.pytool loop section (~56 sites) - Task 7.2 [Tier 3]: Verify
src/mcp_client.pytool loop section (the small subset) - COMMIT (7.1, 7.2): 2 atomic commits
Phase 8: Migrate ToolDefinition consumers (~94 sites, 2 commits)
Focus: New dataclass added in Phase 0; now wire it into the per-vendor tool builders.
- Task 8.1 [Tier 3]: Migrate
src/mcp_client.py(~70 sites; the bulk) - Task 8.2 [Tier 3]: Migrate
src/ai_client.pyper-vendor tool builders (~24 sites) - COMMIT (8.1, 8.2): 2 atomic commits
Phase 9: Migrate RAGChunk consumers (~5 sites, 1 commit)
Focus: New dataclass added in Phase 0; migrate the RAG result consumers.
- Task 9.1 [Tier 3]: Migrate
src/rag_engine.py,src/aggregate.py,src/app_controller.pyRAG chunk consumers.- WHERE:
src/aggregate.py:3259;src/app_controller.py:251,4162 - WHAT:
chunk.get('document', '')→chunk.document; etc. - HOW:
manual-slop_edit_fileper site - SAFETY: Run
tests/test_rag_engine.py+tests/test_rag_*.py+tests/test_rag_chunk.py(new)
- WHERE:
- COMMIT:
refactor(rag_engine,aggregate,app_controller): migrate RAGChunk access sites(Tier 3) - GIT NOTE: Migrated ~5 RAGChunk access sites across 3 files.
Phase 10: Migrate small-batch aggregates (~25 sites, 2 commits)
Focus: SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats, ProviderPayload, UIPanelConfig, PathInfo. These are small aggregates with few sites; batch them.
-
Task 10.1 [Tier 3]: Migrate
src/gui_2.pysmall-batch consumers.- WHERE:
src/gui_2.py:2199-2201,2216,3535,4048-4054,4926-4931(SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats) - WHAT:
insights.get('total_tokens', 0)→insights.total_tokens;entry.get('temperature', 0.7)→entry.temperature;slc.get('tag', '')→slc.tag;stats.get('model', 'unknown')→stats.model - HOW:
manual-slop_edit_fileper site - SAFETY: Run the per-aggregate test files + the GUI tests
- WHERE:
-
COMMIT:
refactor(gui_2): migrate SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats(Tier 3) -
GIT NOTE: Migrated ~20 small-aggregate access sites.
-
Task 10.2 [Tier 3]: Migrate
src/app_controller.pyProviderPayload, UIPanelConfig, PathInfo consumers.- WHERE:
src/app_controller.py:1972-2033,2068-2070,2274-2310(the project config + UI panel config + provider payload sites) - WHAT:
payload.get('script')→payload.script;gui_cfg.get('separate_message_panel', False)→gui_cfg.separate_message_panel;path_info['logs_dir']['path']→path_info.logs_dir.path(nested access) - HOW:
manual-slop_edit_fileper site - SAFETY: Run the per-aggregate test files + the app_controller tests
- WHERE:
-
COMMIT:
refactor(app_controller): migrate ProviderPayload, UIPanelConfig, PathInfo(Tier 3) -
GIT NOTE: Migrated ~5 small-aggregate access sites.
Phase 11: Metadata collapsed-codepath audit (FR6, 1 task, 1 commit)
Focus: Every remaining .get('key', default) site is classified as either (a) "promoted to per-aggregate dataclass → migrated" or (b) "collapsed codepath → keeps Metadata with documented justification."
- Task 11.1 [Tier 2]: Audit remaining
.get('key', default)sites.- WHERE:
git grep -nE "\.get\('[a-z_]+'," HEAD -- 'src/*.py' - WHAT: Per-site classification: (a) promoted + migrated (drop from the report), (b) collapsed-codepath (document the justification in the commit message). The expected collapsed-codepath sites are:
self.project.get('paths', {}),self.project.get('conductor', {}),self.project.get('context_presets', {}),self.project.get('discussion', {}),gui_cfg.get(...)(ifUIPanelConfigdoesn't cover it), etc. - HOW: Manual review + commit message
- WHERE:
- COMMIT:
docs(audit): classify remaining .get() sites as promoted or collapsed-codepath(Tier 2) - GIT NOTE: Per-site classification. The remaining
.get()sites are all justified collapsed-codepaths.
Phase 12: Verification + end-of-track (1 task, 3 commits)
Focus: Run all 10 VCs; write TRACK_COMPLETION; update state.toml + tracks.md.
- Task 12.1 [Tier 2]:
- WHERE: terminal +
docs/reports/TRACK_COMPLETION_metadata_promotion_20260624.md(NEW) - WHAT:
- VC1-VC10 verification (see spec.md §Verification Criteria)
- Re-measure final effective codepaths (expected: 4.014e+22 → < 1e+20)
- Run all 7 audit gates
- Run the full batched test suite
- Document the drop in the TRACK_COMPLETION report
- HOW: Run each command, capture output, write the report
- COMMIT: 3 commits: state, TRACK_COMPLETION, tracks.md update
- VERIFY: All 10 VCs pass
- WHERE: terminal +
Commit Log (Expected, 30-35 atomic commits)
- (Phase 0)
refactor(type_aliases): add per-aggregate dataclasses (CommsLogEntry, HistoryMessage, ToolDefinition, ...) - (Phase 0)
feat(rag_engine): add RAGChunk dataclass - (Phase 0)
refactor(models): complete ContextPreset schema with missing fields - (Phase 0)
test(type_aliases): add per-aggregate dataclass regression-guard suite - (Phase 0)
docs(styleguides): clarify when to promote to per-aggregate dataclass - (Phase 1)
refactor(gui_2): migrate Ticket access sites to direct field access - (Phase 1)
refactor(app_controller,conductor_tech_lead): migrate Ticket access sites - (Phase 1)
refactor(models): remove legacy Ticket.get() method - (Phase 2)
refactor(aggregate): migrate FileItem access sites - (Phase 2)
refactor(ai_client,app_controller): migrate FileItem access sites - (Phase 3)
refactor(session_logger): migrate CommsLogEntry access sites - (Phase 3)
refactor(multi_agent_conductor): migrate CommsLogEntry access sites - (Phase 3)
refactor(app_controller): migrate CommsLogEntry access sites - (Phase 4)
refactor(gui_2): migrate HistoryMessage access sites - (Phase 5)
refactor(ai_client): migrate ChatMessage access sites in _send_anthropic/_send_deepseek - (Phase 5)
refactor(ai_client): migrate ChatMessage access sites in _send_grok/_send_qwen - (Phase 5)
refactor(ai_client): migrate ChatMessage access sites in _send_minimax/_send_llama - (Phase 6)
refactor(app_controller): migrate UsageStats access sites - (Phase 7)
refactor(ai_client): migrate ToolCall access sites in tool loop section - (Phase 7)
refactor(mcp_client): migrate ToolCall access sites in tool loop section - (Phase 8)
refactor(mcp_client): migrate ToolDefinition access sites - (Phase 8)
refactor(ai_client): migrate ToolDefinition access sites - (Phase 9)
refactor(rag_engine,aggregate,app_controller): migrate RAGChunk access sites - (Phase 10)
refactor(gui_2): migrate SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats - (Phase 10)
refactor(app_controller): migrate ProviderPayload, UIPanelConfig, PathInfo - (Phase 11)
docs(audit): classify remaining .get() sites as promoted or collapsed-codepath - (Phase 12)
conductor(state): metadata_promotion_20260624 SHIPPED - (Phase 12)
docs(reports): TRACK_COMPLETION_metadata_promotion_20260624 - (Phase 12)
conductor(tracks): update metadata_promotion_20260624 row
Plus per-task plan-update commits per the workflow.
Verification Commands (run at end of each phase + Phase 12)
# VC1: Metadata is unchanged
git grep "^Metadata:" src/type_aliases.py
# Expect: Metadata: TypeAlias = dict[str, Any]
# VC2: Each new sub-aggregate is its OWN @dataclass(frozen=True, slots=True)
git grep -A 1 "^class CommsLogEntry\|^class HistoryMessage\|^class ToolDefinition\|^class RAGChunk\|^class SessionInsights\|^class DiscussionSettings\|^class CustomSlice\|^class MMAUsageStats\|^class ProviderPayload\|^class UIPanelConfig\|^class PathInfo" src/
# Expect: each followed by @dataclass(frozen=True, slots=True)
# VC3: Existing dataclasses reused
git grep "class Ticket\|class FileItem\|class ToolCall\|class ChatMessage\|class UsageStats" src/
# Expect: existing classes unchanged
# VC4: 107 .get('key', ...) sites on known aggregates replaced
git grep -E "\.get\('[a-z_]+'," HEAD -- 'src/*.py' | wc -l
# Expect: only collapsed-codepath sites (FR2; documented in Phase 11 commit)
# VC5: 106 ['key'] subscript sites on known aggregates replaced
git grep -E "\[[ ]*'[a-z_]+'[ ]*\]" HEAD -- 'src/*.py' | wc -l
# Expect: only legitimate non-aggregate uses
# VC6: 60+ tests pass (5+ per new dataclass, 12 dataclasses)
uv run pytest tests/test_comms_log_entry.py tests/test_history_message.py tests/test_tool_definition.py tests/test_rag_chunk.py tests/test_session_insights.py tests/test_discussion_settings.py tests/test_custom_slice.py tests/test_mma_usage_stats.py tests/test_provider_payload.py tests/test_ui_panel_config.py tests/test_path_info.py tests/test_context_preset_schema.py -v
# Expect: all pass
# VC7: Effective codepaths drops by >= 2 orders of magnitude
uv run python -c "
import sys
sys.path.insert(0, 'scripts/code_path_audit')
sys.path.insert(0, 'src')
from code_path_audit import build_pcg
from code_path_audit_ssdl import count_branches_in_function
pcg = build_pcg('src').data
metadata_consumers = pcg.consumers.get('Metadata', [])
total = sum(2 ** count_branches_in_function(f, 'src') for f in metadata_consumers)
print(f'Effective codepaths: {total:.3e} (baseline: 4.014e+22)')
"
# Expect: < 1e+20
# VC8: 7 audit gates pass
uv run python scripts/audit_weak_types.py --strict
uv run python scripts/generate_type_registry.py --check
uv run python scripts/audit_main_thread_imports.py
uv run python scripts/audit_no_models_config_io.py
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
uv run python scripts/audit_exception_handling.py --strict
uv run python scripts/audit_optional_in_3_files.py --strict
# All exit 0
# VC9: 10/11 batched tiers
uv run python scripts/run_tests_batched.py
# Expect: 10/11 PASS
Notes for Tier 3 workers
- Pattern consistency: For each access site, the canonical pattern is
entry.field_name or default_valuefor nullable fields,entry.field_namefor required fields. - Per-aggregate dataclass reference:
src/openai_schemas.py(the canonical pattern forToolCall,ChatMessage,UsageStats,ToolCallFunction,NormalizedResponse);src/models.py:533(FileItemwithto_dict()/from_dict()round-trip). - Dynamic keys (e.g.,
entry[variable_name]where the key is not a static string): keep asentry.to_dict()[variable_name]for those rare cases. The dataclass handles the common case. - Polymorphic construction (e.g.,
entry = {'role': 'user', 'content': 'hi'}): replace withentry = HistoryMessage(role='user', content='hi'). If the dict is dynamic, useentry = HistoryMessage.from_dict(raw_dict). - JSON serialization:
json.dumps(entry.to_dict())(notjson.dumps(entry)which would fail on dataclass). - Indentation: 1-space per level.
- No comments in source code (per AGENTS.md).
- Per-phase regression-guard test runs: after each phase, run the per-aggregate test files + the full batched test suite. If a phase causes a regression, REVERT the phase commit and investigate (don't try to fix forward).
Notes for Tier 2 reviewer
- The per-aggregate dataclasses are the central artifacts. After Phase 0, every new dataclass is importable. Each subsequent phase migrates the consumers in a specific file.
- The 4.01e22 metric drops per phase. Document the drop in the TRACK_COMPLETION report.
- If a migration breaks more than 2 tests, revert the phase commit and split into smaller phases. Don't accumulate broken state.
- The RAG test pre-existing flake is acceptable. Document it but don't try to fix.
- The classification in Phase 11 (collapsed-codepath vs promoted) is auditable; every remaining
.get()site must have a justification in the commit message.