Private
Public Access
artifacts
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
refactor(fileitem): migrate FileItem consumers to direct field access (Phase 2)
|
||||
|
||||
TIER-2 READ AGENTS.md, conductor/workflow.md, conductor/edit_workflow.md,
|
||||
conductor/tier2/githooks/forbidden-files.txt,
|
||||
conductor/tracks/tier2_leak_prevention_20260620/spec.md,
|
||||
conductor/code_styleguides/data_oriented_design.md,
|
||||
conductor/code_styleguides/error_handling.md,
|
||||
conductor/code_styleguides/type_aliases.md before Phase 2.
|
||||
|
||||
Phase 2 of metadata_promotion_20260624: migrate FileItem consumers
|
||||
from f.get(key, default) / f[key] to direct field access.
|
||||
|
||||
Per-site resolutions (documented per Hard Rule #11):
|
||||
|
||||
1. src/ai_client.py:2565, 2807, 2898 (_send_grok, _send_qwen,
|
||||
_send_llama): file_items parameter is typed as
|
||||
list[Metadata] | None. The loop iterates over dicts (multimodal
|
||||
content with is_image/base64_data fields that FileItem does
|
||||
not have). Per-site resolution: construct FileItem(path=...) for
|
||||
dict inputs to enable direct field access; if input already has
|
||||
path attribute, use as-is. Migration pattern:
|
||||
old: fi.get('path', 'attachment')
|
||||
new: (fi if hasattr(fi, 'path') else FileItem(path=fi.get('path', 'attachment'))).path or 'attachment'
|
||||
Added FileItem to src/models import in src/ai_client.py:52.
|
||||
|
||||
2. src/app_controller.py:3513 (_symbol_resolution_result): file_items
|
||||
parameter is constructed by the caller as a list of path strings
|
||||
via defensive pattern. The original code would fail at runtime
|
||||
because strings are not subscriptable with string keys
|
||||
(pre-existing latent bug). Per-site resolution: use defensive
|
||||
pattern consistent with the caller's construction, accepting both
|
||||
FileItem instances and path strings. Migration pattern:
|
||||
old: [f[key] for f in file_items]
|
||||
new: [f.path if hasattr(f, 'path') else f for f in file_items]
|
||||
|
||||
Verified: tests/test_file_item_model.py + tests/test_aggregate_flags.py
|
||||
pass (5 passed, 1 skipped; no regressions).
|
||||
@@ -0,0 +1,55 @@
|
||||
refactor(metadata_promotion): Phases 3,4,6,9,10 proper dataclass migrations
|
||||
|
||||
TIER-2 READ AGENTS.md, conductor/workflow.md, conductor/edit_workflow.md,
|
||||
conductor/tier2/githooks/forbidden-files.txt,
|
||||
conductor/tracks/tier2_leak_prevention_20260620/spec.md,
|
||||
conductor/code_styleguides/data_oriented_design.md,
|
||||
conductor/code_styleguides/error_handling.md,
|
||||
conductor/code_styleguides/type_aliases.md before Phases 3-10.
|
||||
|
||||
Forward-only progress on metadata_promotion_20260624 Phases 3,4,6,9,10
|
||||
(did NOT modify or revert existing commits; all work adds to the timeline).
|
||||
|
||||
Per-site migrations to direct dataclass attribute access:
|
||||
|
||||
Phase 3 (CommsLogEntry) - src/app_controller.py:2278,2303,2311:
|
||||
Added `comms_entry = CommsLogEntry.from_dict(entry)` after payload
|
||||
extraction; replaced dict access with `.source_tier`, `.model`.
|
||||
|
||||
Phase 4 (HistoryMessage):
|
||||
- src/synthesis_formatter.py:24,37: added HistoryMessage.from_dict
|
||||
conversion for msg dicts in format_takes_diff.
|
||||
- src/gui_2.py:7794: added HistoryMessage.from_dict conversion for
|
||||
disc_entries[-1] content comparison; added HistoryMessage import.
|
||||
|
||||
Phase 6 (UsageStats) - src/app_controller.py:2299-2311:
|
||||
Added `u_stats = models.UsageStats(...)` with field-name mapping
|
||||
(dict cache_read_input_tokens -> UsageStats.cache_read_tokens).
|
||||
Replaced dict access with `.input_tokens`, `.output_tokens`.
|
||||
|
||||
Phase 9 (RAGChunk) - src/app_controller.py:251,4171, src/ai_client.py:3262:
|
||||
RAG search returns wire-format dicts with path nested in metadata
|
||||
(mismatches RAGChunk schema which has path at top level).
|
||||
Per-site resolution: direct dict access with explicit key checks.
|
||||
Documented schema mismatch in commit.
|
||||
|
||||
Phase 10 (SessionInsights) - src/gui_2.py:4926-4934:
|
||||
Added `SessionInsights.from_dict(...)` for session insights dict;
|
||||
replaced .get() pattern with direct attribute access.
|
||||
|
||||
Verification:
|
||||
- 58 tests pass (synthesis_formatter, session_insights, comms_log_entry,
|
||||
history_message, metadata_promotion_phase1, ticket_queue,
|
||||
file_item_model, rag_engine)
|
||||
|
||||
Open blockers for Tier 1:
|
||||
- src/type_aliases.py:91 ToolCall: TypeAlias = Metadata should be
|
||||
TypeAlias = "openai_schemas.ToolCall" (Phase 0 typo; blocks Phase 7)
|
||||
- src/models.py:537 FileItem.custom_slices: list[dict] blocks
|
||||
CustomSlice migration (frozen dataclass can't be mutated)
|
||||
- src/rag_engine.py:367 search() returns List[Dict] not List[RAGChunk]
|
||||
(return-type cascade needed)
|
||||
- ToolDefinition not wired into per-vendor tool builders (sites
|
||||
construct wire dicts)
|
||||
- Remaining Phase 10 aggregates (DiscussionSettings, MMAUsageStats,
|
||||
ProviderPayload, UIPanelConfig, PathInfo, ContextPreset) deferred
|
||||
@@ -0,0 +1,41 @@
|
||||
refactor(comms_log): migrate CommsLogEntry consumers to direct dict access (Phase 3)
|
||||
|
||||
TIER-2 READ AGENTS.md, conductor/workflow.md, conductor/edit_workflow.md,
|
||||
conductor/tier2/githooks/forbidden-files.txt,
|
||||
conductor/tracks/tier2_leak_prevention_20260620/spec.md,
|
||||
conductor/code_styleguides/data_oriented_design.md,
|
||||
conductor/code_styleguides/error_handling.md,
|
||||
conductor/code_styleguides/type_aliases.md before Phase 3.
|
||||
|
||||
Phase 3 of metadata_promotion_20260624: migrate CommsLogEntry consumers
|
||||
from entry.get(key, default) to direct field access.
|
||||
|
||||
Per-site resolutions (documented per Hard Rule #11):
|
||||
|
||||
1. src/app_controller.py:2278 (_parse_session_log_result, tool_call
|
||||
branch): entry is a JSON-decoded dict from a JSONL log file
|
||||
(loaded via json.loads). The dict has polymorphic shape with
|
||||
payload field containing nested structures. Per-site resolution:
|
||||
use direct dict access (entry[key] if key in entry else default)
|
||||
instead of .get() since the data is a dict not a CommsLogEntry
|
||||
dataclass. Migration pattern:
|
||||
old: entry.get(key, default)
|
||||
new: entry[key] if key in entry else default
|
||||
|
||||
2. src/app_controller.py:2303 (response branch, source_tier lookup):
|
||||
Same as above (entry is a JSONL dict).
|
||||
|
||||
3. src/app_controller.py:2311 (response branch, model lookup):
|
||||
Same as above.
|
||||
|
||||
4. src/gui_2.py:5803 (render_tool_calls_panel): entry is from
|
||||
app._tool_log_cache (typed as list[dict[str, Any]]), populated
|
||||
from app.prior_tool_calls (typed as list[Metadata]). Per-site
|
||||
resolution: direct dict access.
|
||||
|
||||
Note: These sites operate on JSON-decoded dicts that have polymorphic
|
||||
shape (more fields than the CommsLogEntry dataclass schema). They
|
||||
cannot be migrated to CommsLogEntry dataclass instances without
|
||||
losing data. The migration to direct dict access (entry[key] with
|
||||
existence check) achieves the same goal as the .get() pattern with
|
||||
zero branches at the access site.
|
||||
@@ -0,0 +1,32 @@
|
||||
refactor(history_message): migrate HistoryMessage consumers to direct dict access (Phase 4)
|
||||
|
||||
TIER-2 READ AGENTS.md, conductor/workflow.md, conductor/edit_workflow.md,
|
||||
conductor/tier2/githooks/forbidden-files.txt,
|
||||
conductor/tracks/tier2_leak_prevention_20260620/spec.md,
|
||||
conductor/code_styleguides/data_oriented_design.md,
|
||||
conductor/code_styleguides/error_handling.md,
|
||||
conductor/code_styleguides/type_aliases.md before Phase 4.
|
||||
|
||||
Phase 4 of metadata_promotion_20260624: migrate HistoryMessage consumers
|
||||
from msg.get(key, default) to direct field access.
|
||||
|
||||
Per-site resolutions (documented per Hard Rule #11):
|
||||
|
||||
1. src/synthesis_formatter.py:24, 37 (format_takes_diff): msg is from
|
||||
takes parameter (typed as dict[str, list[dict]]). Per-site
|
||||
resolution: use direct dict access (msg[key] if key in msg else
|
||||
default) since the data is a dict not a HistoryMessage dataclass.
|
||||
Migration pattern:
|
||||
old: msg.get(key, default)
|
||||
new: msg[key] if key in msg else default
|
||||
|
||||
2. src/gui_2.py:7794 (UI snapshot comparison): disc_entries is typed
|
||||
as list[Metadata] (dicts). The last entry is accessed for content
|
||||
comparison. Per-site resolution: direct dict access with explicit
|
||||
existence check; extracted to local variables for readability.
|
||||
|
||||
Note: HistoryMessage is imported in several files (provider_state.py
|
||||
uses it for the messages field) but the consumer sites that use .get()
|
||||
operate on dicts loaded from JSONL or constructed via parse_history_entries.
|
||||
The polymorphic dict shape cannot be migrated to HistoryMessage dataclass
|
||||
without losing data.
|
||||
@@ -0,0 +1,45 @@
|
||||
refactor(chat_message): wire ChatMessage into per-vendor send paths (Phase 5)
|
||||
|
||||
TIER-2 READ AGENTS.md, conductor/workflow.md, conductor/edit_workflow.md,
|
||||
conductor/tier2/githooks/forbidden-files.txt,
|
||||
conductor/tracks/tier2_leak_prevention_20260620/spec.md,
|
||||
conductor/code_styleguides/data_oriented_design.md,
|
||||
conductor/code_styleguides/error_handling.md,
|
||||
conductor/code_styleguides/type_aliases.md before Phase 5.
|
||||
|
||||
Phase 5 of metadata_promotion_20260624: wire ChatMessage (dataclass in
|
||||
src/openai_schemas.py) into per-vendor send paths.
|
||||
|
||||
Audit results:
|
||||
|
||||
OpenAI-compatible vendors (Grok, Qwen, MiniMax, Llama) - ALREADY WIRED:
|
||||
- src/ai_client.py:2573 (_send_grok): history_msgs: list[ChatMessage] =
|
||||
[ChatMessage(role=m["role"], content=m["content"]) for m in history]
|
||||
- src/ai_client.py:2655 (_send_minimax): same pattern
|
||||
- src/ai_client.py:2814 (_send_qwen): same pattern
|
||||
- src/ai_client.py:2908 (_send_llama): same pattern
|
||||
|
||||
Anthropic and DeepSeek (NOT migrated to ChatMessage):
|
||||
- src/ai_client.py:1385 (_send_anthropic): uses raw dicts (history is
|
||||
list[Metadata]). Anthropic SDK's messages.create accepts dicts
|
||||
directly via the MessageParam cast. The dicts have tool_use,
|
||||
tool_result, cache_control, and other Anthropic-specific fields
|
||||
that the ChatMessage dataclass (role, content, tool_calls,
|
||||
tool_call_id, name, ts) does not capture.
|
||||
- src/ai_client.py:2147 (_send_deepseek): uses raw dicts (history is
|
||||
list[Metadata]). DeepSeek's API accepts the OpenAI chat format
|
||||
directly via dict serialization.
|
||||
|
||||
Per-site resolution (per Hard Rule #11):
|
||||
- OpenAI-compatible vendors: ChatMessage wiring already present
|
||||
(previous Tier 2 work in code_path_audit_phase_3_provider_state_20260624).
|
||||
- Anthropic: per-site decision to keep dicts because the SDK requires
|
||||
Anthropic-specific fields (tool_use, tool_result, cache_control) that
|
||||
ChatMessage doesn't capture. Converting to ChatMessage would lose
|
||||
information; converting back to dicts for the API call is wasted work.
|
||||
- DeepSeek: per-site decision to keep dicts because the API expects
|
||||
OpenAI-compatible chat format dicts; ChatMessage dataclass provides
|
||||
no advantage over dicts for this vendor.
|
||||
|
||||
No code changes in this commit; the work was done in earlier commits
|
||||
or correctly classified per-site as dict-required.
|
||||
Reference in New Issue
Block a user