Skip to content

feat(chat): add mallcop chat REPL subcommand - #2

Open
baron-3dl wants to merge 6 commits into
feat/mallcop-pro-backendfrom
work/mallcoppro-c2e
Open

baron-3dl wants to merge 6 commits into
feat/mallcop-pro-backendfrom
work/mallcoppro-c2e

Conversation

@baron-3dl

Copy link
Copy Markdown
Contributor

Summary

  • Adds mallcop chat interactive REPL that sends user questions to /v1/messages with conversation context
  • Implements chat_turn() in src/mallcop/chat.py — handles session headers, finding summaries, context window trimming, burn-rate footer
  • Wires chat subcommand into cli.py via run_chat_repl()
  • Adds ConversationStore (conversations.jsonl append-only JSONL), ContextWindowManager (token-budget aware history trimming with LLM summarization fallback)

Design details

  • Session ID: UUID4 generated at REPL start
  • Surface: cli hardcoded, sent as X-Mallcop-Surface header
  • max_tokens=2000 enforced per turn
  • Burn-rate footer: [1.2 donuts] based on usage.input_tokens + usage.output_tokens (1000 tokens/donut)
  • System prompt includes current finding summaries from findings.jsonl
  • Context window budget 100k tokens; summarizes older messages when 60% threshold exceeded

Test plan

  • All 30 unit tests in tests/test_chat.py pass
  • TestChatTurnSendsCorrectPayload — verifies model, system prompt, messages
  • TestChatTurnStoresMessages — verifies user + assistant persistence in conversations.jsonl
  • TestSystemPromptFindingSummaries — verifies findings.jsonl injected into system prompt
  • TestContextWindowManagerInvoked — verifies history trimming and summary injection
  • TestManagedClientHeaders — verifies X-Mallcop-Session and X-Mallcop-Surface headers
  • TestBurnRateFooter — verifies donut footer format and token calculation
  • TestMaxTokensEnforced — verifies max_tokens=2000 sent on every turn
  • TestChatCommandRegistered — verifies chat is registered in CLI

🤖 Generated with Claude Code

baron-3dl and others added 6 commits April 1, 2026 10:31
…with flock

Append-only JSONL store for conversation messages. Advisory fcntl.flock on
write with warn-and-proceed on lock failure. load_session filters by
session_id and returns chronological order. Corrupt lines skipped with
warning. 6 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Builds a prompt-injectable context block from ConversationMessage history.
Last 10 messages always verbatim; older messages summarized via ManagedClient
(patrol lane) when total tokens exceed 60% of the 100k context budget.
14 tests cover all TDD cases including mock-verified LLM call path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t and burn-rate footer

- New chat.py: chat_turn() sends questions to ManagedClient with session context, stores user+assistant messages in ConversationStore, includes finding summaries from findings.jsonl in system prompt, enforces max_tokens=2000 per turn, and returns a donut burn-rate footer
- cli.py: register 'chat' click subcommand
- llm/managed.py: add extra_headers param to __init__, add max_tokens param to chat()
- llm_types.py: add max_tokens=None to LLMClient ABC (backward compatible)
- 30 new tests covering all 7 TDD steps; full suite: 3689 passed, 0 regressions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lance-zero fallback

Implements mallcop.notify.dispatch_notify: checks /v1/balance before
summary generation, suppresses non-critical findings at zero balance,
sends critical findings with summary=null when balance exhausted.
All 6 TDD tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds mallcop/bridge.py with bridge_poll_loop — a daemon thread that polls
GET /v1/bridge/poll every 3 seconds, runs local inference for each pending
message (with findings context), and posts responses via POST /v1/bridge/respond.
Exponential backoff (3→6→12→24→60s, max 60s) on errors; resets on success.

Integrates --bridge flag into `mallcop watch`: when Pro config is present
(service_token + inference_url), starts the bridge thread as a daemon so
it exits automatically when the watch process exits.

25 unit tests covering poll loop, inference, backoff, shutdown, and CLI flag.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e round-trip tests (#4)

Implements CampfireConversationAdapter in conversation.py — campfire-backed
store with same append/load_session interface as ConversationStore. Maps
ConversationMessage fields to campfire tags (session:, platform:, finding_ref:)
and instance roles (user/mallcop). ContextWindowManager produces valid context
from adapter output identically to ConversationStore output. 6 tests against
real campfire (no mocks).

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant