- File:lines —
_chat.py:26–93andchat_commands.py:54–115 - Description — Both files define
handle_memory_failures,handle_pin,handle_unpin,handle_pinned,handle_memory_clear,get_failure_warnings, andexecute_shell_command. The implementations are slightly different:_chat.pyuses emoji in some print messages;chat_commands.pyuses plain text. Theexecute_shell_commandimplementations differ in their denylist logic (executable-based vs string-pattern-based). - Impact — Divergent behavior depending on which import path is used. Maintenance burden. Security risk: the older
chat_commands.pyversion checks for'rm -rf /'as a substring, which is bypassable (e.g.,rm -rf /tmp), while_chat.pyuses a proper executable denylist. - Severity — Medium (security difference in
execute_shell_command).
- File:lines —
_chat.py:1029,_chat.py:1292 - Description — The legacy
run_chat_replin_chat.pyadds a hardcoded10cents per task instead of usingresult.cost_cents. The newerchat_repl.py::run_chat_replusesChatSessionControllerwhich properly accumulatesresult.cost_cents. The legacy version is still imported and exported from_chat.py. - Impact — Any code path using
_chat.py::run_chat_repldirectly (rather than throughChatSessionController) will always show$0.10 * n_tasksregardless of actual cost. This is CG-03 unresolved in the legacy path. - Severity — Medium (cost display bug in legacy path).
- File:lines —
_chat.py:486–526 - Description — The legacy
suspend_to_backgroundin_chat.pyrunsgit checkout -b suspended-{run_id}on a dirty workspace without user confirmation. The newer version inchat_repl.pydoes NOT create a branch (warns instead). The two implementations are inconsistent. - Impact — Surprise git branch creation when using the legacy code path. The new version is safer.
- Severity — Low (only triggered by
/backgroundcommand).
- File:lines —
chat_session_controller.py:143–159 - Description — Both the result-store save and undo-journal save are wrapped in
try/except (AttributeError, TypeError)with comment "Audit logger is likely a mock in tests." Real persistence failures (e.g., disk full, permission denied) would also be caught and silently ignored. - Impact — Lost run history and undo journals without any user-visible error.
- Severity — Medium.
- File:lines —
chat_session_controller.py:218–219 - Description — The outer
except Exception as exccatch-all inundo_last_run()means any programming error (e.g.,AttributeErroron a refactoredUndoJournal) returnsFalseand outputs[TeaAgent] Error in undo: {exc}rather than propagating the traceback. - Impact — Debugging undo failures is difficult since the exception type and full stack trace are swallowed.
- Severity — Low (correct behavior for users; painful for developers).
- File:lines —
_chat.py:311–413vschat_completion.py:8–110 - Description — The completion functions are duplicated verbatim (same logic).
chat_repl.pyimports fromchat_completion.py; the legacy_chat.pydefines its own copies. - Impact — Any fix to completion logic must be applied in two places.
- Severity — Low.
- File:lines —
chat_repl.py:580–581,chat_repl.py:831–832 - Description — After
controller.execute_task(), the code syncs back:This casts the float to int, losing fractional cents. Thesession_cost_cents = int(session_state.session_cost_cents)
show_effort_status()function usessession_cost_cents(the local int), notsession_state.session_cost_cents(the float). The/costcommand in the REPL uses the local variable directly (line 670). - Impact — Displayed cost is always rounded down to the nearest cent.
- Severity — Low.
| Scenario | Behavior |
|---|---|
execute_task() called with resumed_from=None |
initial_context_extra is not passed to run_chat_agent (condition at line 138) |
undo_last_run() when no runs exist |
store.latest_run_with_undo() returns None; outputs Nothing to undo |
execute_task() with a mock audit that has .path = None |
Store persistence is skipped silently (line 145: if audit.path) |
config.model is None (no / separator) |
provider = 'gpt', model_part = None → creates default GPT adapter |
config.model = 'claude' (no /) |
Same as above: provider inferred as 'gpt', not 'claude' — potential provider mismatch |
| ID | Description | Location |
|---|---|---|
| CG-03 (partial) | Legacy _chat.py::run_chat_repl hardcodes 10-cent cost per task |
_chat.py:1029, 1292 |
| Duplicate implementation | handle_pin, handle_unpin, handle_memory_failures, etc. exist in both _chat.py and chat_commands.py with subtle behavioral differences |
Multiple locations |
| Provider inference bug | If config.model = 'claude' (no slash), provider is inferred as 'gpt' not 'claude' |
chat_session_controller.py:119–129 |