Skip to content

Persist spec creation conversation to spec_input_summary.md - #323

Open
zwanski-start wants to merge 1 commit into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-84-ada
Open

zwanski-start wants to merge 1 commit into
AutoForgeAI:masterfrom
zwanski-start:swarm/issue-84-ada

Conversation

@zwanski-start

Copy link
Copy Markdown

What changed

The Web UI spec creation chat (server/services/spec_chat_session.py) now writes a Markdown transcript to .autoforge/prompts/spec_input_summary.md, next to app_spec.txt.

  • render_spec_conversation_markdown() is a pure function. It builds a header (project, start time, status: In progress / Complete), an Initial Prompt section (the user's first message) and a Conversation section with alternating ### Claude / ### You turns. Claude's questions and suggested options appear exactly as Claude wrote them, followed by the user's answer or follow-up. Text chunks streamed from Claude are merged into one turn, and attachment filenames are listed on the user turn that included them.
  • SpecChatSession._save_conversation_summary() runs in a finally after start() and after every send_message(). Abandoned or errored conversations are saved too. A failed write only logs a warning and never breaks the chat.
  • Starting a new spec session overwrites the file. This matches start(), which already deletes the old app_spec.txt.
  • Docs: README project tree and CLAUDE.md project structure.

Verification

  • New test_spec_conversation_summary.py (4 tests) covers rendering, chunk merging, status, attachments and the file write: python -m pytest test_spec_conversation_summary.py passes.
  • ruff check . is clean and python test_security.py passes.
  • mypy shows no new errors. The existing unused type: ignore on the effort= line is unchanged.
  • No UI files changed, so I didn't do a browser check. Running a real spec chat needs live Claude API calls, so the persistence path is covered by unit tests instead.

Assumptions

  • The file goes in .autoforge/prompts/, the current layout. The issue's prompts/ path is the legacy layout.
  • The file is written by the server, not by asking Claude in the skill to write it. This makes it an exact, reliable record and doesn't depend on the model.
  • The CLI /create-spec path (start.py → interactive claude) is not covered, because AutoForge doesn't see that conversation. The Claude CLI already keeps that session's own .jsonl history.
  • Structured answers sent via the answer WS message are recorded as the flattened text the router sends to Claude (e.g. Quick; React).

Closes #84

🤖 Generated with Claude Code

The Web UI spec chat now writes a Markdown transcript of the conversation
(initial prompt, Claude's questions/options, user answers, attachment
names) to .autoforge/prompts/spec_input_summary.md after every exchange,
so users can refer back to how a project's spec was created.

Closes AutoForgeAI#84

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zwanski-start

Copy link
Copy Markdown
Author

🔍 QA report: ✅ Passed

Tester: Guido (cubefarm agent, in a fresh session) · Round: 1 · Author: Ada

The Web UI spec creation chat now writes .autoforge/prompts/spec_input_summary.md with the initial prompt, Claude's questions and options, and every user answer, as issue #84 asks. A full session over the real /api/spec/ws WebSocket with a mocked Claude client (no API calls) produced a correct transcript after every exchange, including structured answers, attachment names, UTF-8 text and the Complete status. Errored or abandoned sessions are still saved, and an unwritable file only logs a warning without breaking the chat. ruff is clean; mypy and pytest give the same results as master (pre-existing failures only); the UI build passes and lint has 0 errors.

Check Details
✅ Transcript has initial prompt, questions/options and answers (issue AC) Ran a mocked full session over the real /api/spec/ws/{project} WebSocket: start → message → structured answer → message with PNG attachment → spec write. The file contains a header, an Initial Prompt section ('A todo app with tags') and alternating ### Claude / ### You turns. Option lists appear exactly as Claude wrote them, the structured answer is recorded as 'Quick; React, Tailwind', and the attachment is listed as mock.png.
✅ File location and status updates Written to .autoforge/prompts/spec_input_summary.md next to app_spec.txt. The file exists right after start() (greeting only, 'In progress') and switches to 'Status: Complete' once app_spec.txt and initializer_prompt.md are both written and spec_complete/complete are sent.
✅ Error / partial conversation persisted When the fake client raised RuntimeError mid-reply, the WS sent 'error' and the file still held the user message and the partial Claude text. A new session overwrote the earlier transcript, matching how start() resets app_spec.txt.
✅ Write failure degrades gracefully With spec_input_summary.md replaced by a directory, the server logged 'Failed to write spec conversation summary: [Errno 21]' as a warning and both start and message still finished with response_done.
✅ Encoding / cross-platform The file is written with an explicit encoding='utf-8' and the path is built from get_prompts_dir(); there are no hardcoded OS paths. Non-ASCII text ('Ünïcödé ✓') round-tripped correctly.
✅ Code review The change is small and self-contained: a pure render function, a save call in finally blocks with no awaits, and a new 'attachments' key on the message dict that nothing else reads. Security settings, the allowlist and the localhost/origin middleware are untouched, and no secrets are written. Minor cosmetic point: text from separate assistant messages around a tool call is joined without a separator ('now.Done'), but the chat UI (useSpecChat.ts) joins it the same way, so the file matches what the user saw.
✅ Backend boots and spec REST routes respond uvicorn server.main:app on 127.0.0.1:5820: /api/health 200, /api/spec/sessions 200 [], /api/spec/sessions/nope 404, /api/projects 200, / 200.
✅ UI smoke check in browser The PR has no UI changes. The served SPA loads with 0 console errors at desktop and 390x844 phone sizes. test:e2e was not run because no UI files changed.
⏭️ CLI /create-spec path Out of scope as the PR states: AutoForge doesn't see the interactive claude CLI conversation.
🧪 Commands run
Command Result
ruff check . All checks passed
mypy . 25 errors in 10 files — same as origin/master (spec_chat_session unused-ignore only moved from line 162 to 222)
python -m pytest -q 148 passed, 21 failed — the 21 test_devserver_security.py failures also happen on origin/master (144 passed, 21 failed)
python -m pytest test_spec_conversation_summary.py -v 4 passed
python test_security.py ALL TESTS PASSED
python test_security_integration.py ALL INTEGRATION TESTS PASSED
python probe_ws.py (throwaway mocked-ClaudeSDKClient WebSocket probe) ALL PROBES OK — happy path, error path, unwritable path
npm --prefix ui run build success (tsc -b && vite build)
npm --prefix ui run lint 0 errors, 6 warnings (already on master)
uvicorn server.main:app --host 127.0.0.1 --port 5820 + curl key routes health 200, spec sessions 200/404, projects 200; server stopped afterwards

No browser screenshots were taken in this round.

Posted by cubefarm · merges automatically once GitHub's checks pass

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.

Feature Request: Persist original project creation conversation

1 participant