Skip to content

FE-554: Structured interview: scope phase#17

Merged
lunelson merged 8 commits into
mainfrom
ln/fe-554-structured-interview
Apr 2, 2026
Merged

FE-554: Structured interview: scope phase#17
lunelson merged 8 commits into
mainfrom
ln/fe-554-structured-interview

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

@lunelson lunelson commented Apr 1, 2026

feat: structured interview scope phase with SDK MCP tools

Replace generic chat with scope-phase structured interview. Core
changes:

  • interview.ts: phase-specific system prompts, Zod schema for
    structured questions, in-process MCP server with ask_question tool
    that persists question/why/impact/options via closure
  • core.ts: conductTurn uses getSystemPrompt + createInterviewMcpServer
    per turn, formatHistory includes structured context (why, impact)
  • db.ts: getOptionsForTurn, selectOption, updateTurn accepts why/impact

14 new tests (86 total): schema validation (5), system prompts (2),
MCP server creation and tool handler persistence (2), conductTurn
config (2), history formatting (1), option CRUD (2).

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

refactor: address ln-review findings for slice 4

  1. Phase parameter on conductTurn (was hardcoded 'scope')
  2. interview.ts docstring clarifies shell boundary
  3. Deduplicate Zod schema — tool uses structuredQuestionSchema.shape
  4. formatHistory includes options with recommendation/selection markers
  5. getTurn replaces redundant getActivePath call for single-turn check
  6. A13 revised in SPEC.md — validated via system prompt + MCP tools,
    not SDK AgentDefinition skills
  7. Round-trip oracle test: structured turn → persist → active path

88 tests passing (2 new: options-in-history, round-trip persistence).

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

@linear
Copy link
Copy Markdown

linear Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

lunelson commented Apr 1, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@lunelson lunelson force-pushed the ln/fe-554-structured-interview branch from 3cab7ca to 2d37ff7 Compare April 1, 2026 15:58
@lunelson lunelson force-pushed the ln/fe-553-multi-project-routing branch from 231bff6 to 1e4e403 Compare April 1, 2026 15:58
@lunelson lunelson changed the base branch from ln/fe-553-multi-project-routing to graphite-base/17 April 2, 2026 06:29
lunelson and others added 6 commits April 2, 2026 09:33
Replace generic chat with scope-phase structured interview. Core
changes:
- interview.ts: phase-specific system prompts, Zod schema for
  structured questions, in-process MCP server with ask_question tool
  that persists question/why/impact/options via closure
- core.ts: conductTurn uses getSystemPrompt + createInterviewMcpServer
  per turn, formatHistory includes structured context (why, impact)
- db.ts: getOptionsForTurn, selectOption, updateTurn accepts why/impact

14 new tests (86 total): schema validation (5), system prompts (2),
MCP server creation and tool handler persistence (2), conductTurn
config (2), history formatting (1), option CRUD (2).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Phase parameter on conductTurn (was hardcoded 'scope')
2. interview.ts docstring clarifies shell boundary
3. Deduplicate Zod schema — tool uses structuredQuestionSchema.shape
4. formatHistory includes options with recommendation/selection markers
5. getTurn replaces redundant getActivePath call for single-turn check
6. A13 revised in SPEC.md — validated via system prompt + MCP tools,
   not SDK AgentDefinition skills
7. Round-trip oracle test: structured turn → persist → active path

88 tests passing (2 new: options-in-history, round-trip persistence).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PLAN.md: mark slice 4 in-progress (server done, client pending)
- SPEC.md: add I16 (schema validation on agent tool output)
- SPEC.md: add ask_question tool and interview MCP server to Lexicon
- SPEC.md: update phase term with concrete mechanism
- SPEC.md: update coverage table (app.test.ts 15→17, +interview.test.ts)
- PLAN.md: retire slice 4 parallelism note

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…bserver sync)

- New decision D22: in-band data parts on existing SSE (default), out-of-band
  EventSource (fallback). TanStack DB evaluated and rejected.
- New assumptions A20 (observer latency in-band), A21 (onData stale closure)
- New constraint: No TanStack DB
- Promote observer-complete from future to planned in D19
- Add lexicon: in-band sync, out-of-band sync, cache invalidation
- Slice 5: trace to D22, A20; post-commit event requirement
- Slice 6: trace to D22, A21; TanStack Query cache population via onData

Amp-Thread-ID: https://ampcode.com/threads/T-019d4d56-9083-7259-865e-7bd338bbe27e
Co-authored-by: Amp <amp@ampcode.com>
…ing, round-trip sync

Inner loop: observer-complete post-commit + entity ID consistency + SSE data-part encoding
Middle loop: round-trip oracle — conductTurn with observer → event ordering → DB match
Outer loop: onData → setQueryData sidebar reactivity (manual, validates A21)
Blind spot: onData stale-closure risk (ai-sdk#550); fallback to EventSource if broken

Amp-Thread-ID: https://ampcode.com/threads/T-019d4d56-9083-7259-865e-7bd338bbe27e
Co-authored-by: Amp <amp@ampcode.com>
@lunelson lunelson force-pushed the ln/fe-554-structured-interview branch from 229ed2d to a36f0d5 Compare April 2, 2026 10:30
@lunelson lunelson changed the base branch from graphite-base/17 to main April 2, 2026 10:30
lunelson and others added 2 commits April 2, 2026 12:34
…xt builders)

- D23: UIMessage/ModelMessage split — persist parts[] JSON alongside turn
  scalars for faithful UI resume; inference context derived by builders
- D24: Custom Data Parts for structured user input (option-selection,
  confirmation) and domain-specific assistant output (phase-summary,
  observer-result)
- D25: Typed context builders replace monolithic formatHistory() —
  different projections per consumer (interviewer, observer, phase judge)
- D15 superseded by D23 (transitional turn-field inversion → parts-based)
- A22, A23 added for parts persistence assumptions
- Slice 4 split into 4 (server, done), 4a (parts+context), 4b (client UI)
- Lexicon updated: UIMessage, ModelMessage, parts[], Data Part, context builder
- Research ref: docs/research/Chat Application Data Models...

Amp-Thread-ID: https://ampcode.com/threads/T-019d4d58-261d-706a-90e9-6987dbd162ff
Co-authored-by: Amp <amp@ampcode.com>
- I17: Data Part schema validation (Zod on structured user input)
- I18: Parts round-trip fidelity (DomainEvents → persist → hydrate)
- I19: Context builder equivalence (buildInterviewerContext matches formatHistory)
- Inner loop: fast unit tests — parts added to oracle strategy
- Blind spot: parts/scalar consistency deferred as metamorphic oracle
- Slice 4a: drop backward-compat fallback (DB re-init is safe),
  oracle-informed acceptance criteria and verification approach

Amp-Thread-ID: https://ampcode.com/threads/T-019d4d58-261d-706a-90e9-6987dbd162ff
Co-authored-by: Amp <amp@ampcode.com>
@lunelson lunelson marked this pull request as ready for review April 2, 2026 12:25
@lunelson lunelson changed the title feat: structured interview scope phase with SDK MCP tools FE-554: Structured interview: scope phase Apr 2, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Apr 2, 2026

🤖 Augment PR Summary

Summary: Implements the server-side “scope phase” structured interview flow using an in-process MCP tool with schema validation, replacing generic chat prompting.

Changes:

  • Added src/server/interview.ts with phase-specific system prompts and a Zod structuredQuestionSchema for the ask_question tool
  • Created a per-turn MCP server (createInterviewMcpServer) whose tool handler persists question/why/impact and option rows via a db + turnId closure
  • Updated conductTurn to accept a phase parameter, use getSystemPrompt(phase), and pass the interview MCP server into SDK query()
  • Enhanced formatHistory to include grounding (why), impact, and option markers (recommended/selected) for better multi-turn context
  • Extended the DB layer with getTurn, getOptionsForTurn, selectOption, and updateTurn support for why/impact
  • Added interview-focused unit tests (schema validation, prompts, MCP tool persistence, conductTurn config, history formatting, option CRUD) and introduced zod as a dependency

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/server/interview.ts
why: args.why,
impact: args.impact as Impact,
});
for (let i = 0; i < args.options.length; i++) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/server/interview.ts:91 — The ask_question handler always inserts options at positions starting from 0 without clearing existing rows; because option_turn_position_unique enforces (turn_id, position), a second tool invocation/retry for the same turn can throw and leave the turn partially persisted.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/server/interview.ts
import { createOption, updateTurn, type DB, type Impact, type Phase } from './db.js';

/** Zod schema for the ask_question tool output. */
export const structuredQuestionSchema = z.object({
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/server/interview.ts:14 — The scope system prompt requires marking exactly one option as recommended, but structuredQuestionSchema doesn’t validate that invariant (0 or multiple is_recommended: true are accepted), which could make “recommended” ambiguous downstream.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/server/db.ts
.all() as Option[];
}

export function selectOption(db: DB, turnId: number, position: number): void {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/server/db.ts:150 — selectOption clears all selections for the turn before ensuring an option exists at the requested position; if an invalid position is passed, the prior selection is lost and the turn ends up with no selection.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread memory/PLAN.md
- Branch: `ln/fe-541-rich-chat-ui`

4. **Structured interview: scope phase** — Replace flat chat with structured turns. Implement the scope phase as an agent skill — the agent generates a question with options, grounding ("why this matters"), and impact signal. User selects an option or types a response. Turn persists with phase provenance. UI renders the turn card (question + options + grounding). `not-started`
4. **Structured interview: scope phase (server)** `FE-554` — Replace flat chat with structured turns. Implement the scope phase as an agent skill — the agent generates a question with options, grounding ("why this matters"), and impact signal via `ask_question` MCP tool. Turn persists with phase provenance (question, why, impact, options). `done`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR metadata: the PR title doesn’t follow the repo naming rule for issue-scoped PRs (expected FE-554: … per (Rule: AGENTS.md)); consider aligning it so stack/issue traceability stays consistent.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Contributor Author

lunelson commented Apr 2, 2026

Merge activity

  • Apr 2, 6:52 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 2, 6:52 PM UTC: @lunelson merged this pull request with Graphite.

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