feat: auto-emit journal entries on interview lifecycle (Phase 4b)#30
Conversation
Second slice of Phase 4: hook the CLI `interview start/answer/commit`
commands and the MCP `interview_start`/`_answer`/`_adjust`/`_commit`
tools into the journal so each lifecycle moment of an AI-assisted
design interview gets captured automatically. Per
`docs/journal-spec.md` §9 Phase 4:
| Event | Kind | Notes |
|-------------------|----------|------------------------------------|
| Started | plan | provisional |
| AnswerRecorded | finding | provisional |
| PhaseAdvanced | finding | provisional; emitted when reanaly- |
| | | sis bumps the phase |
| Adjusted | finding | provisional; covers adjust/add/ |
| | | edge tentative-graph mutations |
| Committed | outcome | passed = true, final = true |
Rollback is in the spec but the interview engine has no rollback
operation today — when/if that lands, this module gains a sixth
variant. Until then, "all provisional until session commit" is
honored end-to-end: every event during the interview is provisional,
the commit emits one non-provisional `outcome` that finalizes the
journal session and triggers publish.
Code structure: split the auto_emit module into a directory so task
and interview event mappings live alongside without crowding one
file. New layout:
auto_emit/
mod.rs - re-exports
summary.rs - shared clamp_summary helper (200-char floor,
UTF-8-safe)
task.rs - Phase 4a transitions (no behavior change)
interview.rs - Phase 4b events (new)
CLI plumbing: `interview start/answer/commit` each grow an `--agent`
flag mirroring `tempyr status` (default "claude"). MCP plumbing:
each handler builds an `InterviewEvent` after the operation succeeds
and routes through `self.emit_interview_event(graph_dir, event)`,
which anchors on the resolved project root (NOT the server cwd) and
returns Option<String> for soft-warning callers — same pattern as
the task transition helper.
Tests: 7 new unit tests in `auto_emit::interview::tests` covering
the mapping; 1 new CLI integration test
`test_interview_lifecycle_auto_emits_journal_entries` driving start
→ answer → commit and asserting plan/finding/outcome entries land
plus the .ready marker is written on the final outcome.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds best-effort interview-lifecycle journal auto-emission. CLI and MCP handlers accept an Changes
Sequence DiagramsequenceDiagram
participant User as User / MCP Client
participant Handler as CLI / MCP Handler
participant Engine as Interview Engine
participant Git as Git (repo metadata)
participant Journal as Journal Auto-Emit
User->>Handler: interview start (agent)
Handler->>Engine: create session
Engine-->>Handler: session_id, phase, root info
Handler->>Git: resolve repo/top-level
Handler->>Journal: auto_emit_interview_event(Started)
Journal-->>Handler: write outcome (ok / soft-fail)
Handler-->>User: session_id
User->>Handler: interview answer (session_id, answer, agent)
Handler->>Engine: record answer
Engine-->>Handler: filled_gaps, new_phase
Handler->>Journal: auto_emit_interview_event(AnswerRecorded)
alt phase changed
Handler->>Journal: auto_emit_interview_event(PhaseAdvanced)
Journal-->>Handler: write outcome
end
Handler-->>User: updated session state (includes warnings)
User->>Handler: interview commit (session_id, agent)
Handler->>Engine: commit/finalize
Engine-->>Handler: node_count, edge_count, files_created
Handler->>Git: resolve repo/top-level
Handler->>Journal: auto_emit_interview_event(Committed)
Journal-->>Handler: final outcome entry written
Handler-->>User: commit confirmed (includes warnings)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/tempyr-cli/src/commands/interview_cmd.rs`:
- Around line 295-302: The code currently returns early on any Err from
jpath::git_common_dir and jpath::repo_toplevel, swallowing all errors; change
each match to capture the error (e) and only silently return for the expected
“not a git repo” case, otherwise print the error to stderr (e.g. eprintln!) with
context and the error details before returning. Concretely, replace Err(_) arms
for git_common_dir and repo_toplevel with Err(e) => if e indicates “not a git
repository” (or the library’s equivalent variant/message) { return } else {
eprintln!("failed to resolve git_common_dir/repo_toplevel: {}", e); return },
referencing jpath::git_common_dir, jpath::repo_toplevel, common_dir and
worktree_top to locate the spots to change.
In `@crates/tempyr-mcp/src/handler.rs`:
- Around line 1319-1330: Replace stderr-only warning side-effects with adding
the returned soft-failure string into the MCP response warnings: when calling
emit_interview_event(...) (e.g., the InterviewEvent::Started, ::Answered and
::Adjusted calls inside interview_start, interview_answer and interview_adjust),
capture the Option<String> and if Some(w) push/append it into the operation
result/response warnings collection (the same field used by interview_commit)
instead of calling eprintln!; ensure you update the code paths at the three call
sites so the response exposes those warnings to clients.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 38d2cd67-69bf-4afa-b793-6af02c6f1cc4
📒 Files selected for processing (10)
crates/tempyr-cli/src/commands/interview_cmd.rscrates/tempyr-cli/src/main.rscrates/tempyr-cli/tests/integration.rscrates/tempyr-journal/src/auto_emit/interview.rscrates/tempyr-journal/src/auto_emit/mod.rscrates/tempyr-journal/src/auto_emit/summary.rscrates/tempyr-journal/src/auto_emit/task.rscrates/tempyr-journal/src/lib.rscrates/tempyr-mcp/src/handler.rsdocs/journal-spec.md
Two findings on PR #30 (Phase 4b): 1. The CLI auto-emit helpers were swallowing all errors from `jpath::git_common_dir` / `repo_toplevel` with `Err(_) => return`. `NotAGitRepo` is a distinct enum variant — silently skipping it is the right call (tempyr supports operating outside a git repo) but bundling Io / Git failures into the same arm hides real bugs. Match `NotAGitRepo` explicitly and log anything else to stderr with context. Apply the same fix to `status_cmd.rs` (slice 4a code), which has the identical pattern. 2. MCP `interview_start`, `interview_answer`, and `interview_adjust` were calling `eprintln!` for journal auto-emit failures. MCP clients don't see server stderr, so a write failure was effectively invisible. `interview_commit` already exposes warnings via the response's `warnings` field; mirror that on the other three handlers. Adds a small `attach_warnings` helper that inserts `warnings` into the JSON value `session_state_json` returns; `interview_answer` uses an inline `json!` literal so the field gets added there directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Second slice of Phase 4 from `docs/journal-spec.md` §9: hook the CLI `interview start/answer/commit` commands and the MCP `interview_start`/`_answer`/`_adjust`/`_commit` tools into the journal so each lifecycle moment of an AI-assisted design interview gets captured automatically.
Rollback is in the spec but the interview engine has no rollback operation today — when/if that lands, this module gains a sixth variant. "All provisional until session commit" is honored: every event during the interview is provisional; commit emits one non-provisional `outcome` that finalizes the journal session and triggers publish.
Code structure
Split `tempyr_journal::auto_emit` into a directory:
```
auto_emit/
mod.rs - re-exports
summary.rs - shared clamp_summary helper
task.rs - Phase 4a transitions (no behavior change)
interview.rs - Phase 4b events (new)
```
CLI: `interview start/answer/commit` each grow `--agent` (default "claude"), mirroring `tempyr status`. MCP: handlers build an `InterviewEvent` after the operation succeeds and route through `self.emit_interview_event(graph_dir, event)` — anchored on the resolved project, never the server cwd.
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
start,answer,commit) accept an--agentflag (default: "claude")Behavior Changes
Tests
Documentation