Skip to content

FE-555: Parts-based persistence + context builders#19

Merged
lunelson merged 2 commits into
mainfrom
ln/fe-555-parts-persistence
Apr 2, 2026
Merged

FE-555: Parts-based persistence + context builders#19
lunelson merged 2 commits into
mainfrom
ln/fe-555-parts-persistence

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

@lunelson lunelson commented Apr 2, 2026

feat: parts-based persistence + context builders

Schema migration adds user_parts and assistant_parts JSON columns to
turn table. Parts assembler converts DomainEvents into typed UIMessage
parts (reasoning, text, tool-invocation) persisted on stream finish.

Data Part schemas (data-option-selection, data-confirmation) defined
with Zod validation. Context builders (buildInterviewerContext,
buildObserverContext) replace monolithic formatHistory — different
consumers get different projections from the same turn tree.

Establishes I17 (Data Part schema validation), I18 (parts round-trip
fidelity), I19 (context builder equivalence). 24 new tests (112 total).

Made-with: Cursor

spec/plan: traceability for slice 4a — A22/A23 validated, I17-I19 established

Mark slice 4a done in PLAN.md. Graduate A22 and A23 to validated in
SPEC.md. Update invariant table with test file references and current
coverage section with new test files (parts.test.ts, context.test.ts).

Made-with: Cursor

@linear
Copy link
Copy Markdown

linear Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

lunelson commented Apr 2, 2026

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

@lunelson lunelson marked this pull request as ready for review April 2, 2026 12:25
@lunelson lunelson changed the title feat: parts-based persistence + context builders FE-555: Parts-based persistence + context builders Apr 2, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Apr 2, 2026

🤖 Augment PR Summary

Summary: This PR introduces parts-based persistence for turns and splits prompt construction into dedicated context builders.

Changes:

  • Added `user_parts` and `assistant_parts` columns to the `turn` table (migration + Drizzle schema updates).
  • Implemented a parts assembler to convert `DomainEvent`s into persisted assistant `parts[]` (reasoning/text/tool-invocation) plus JSON (de)serialization helpers.
  • Defined Zod schemas for custom Data Parts (`data-option-selection`, `data-confirmation`) and added unit coverage.
  • Updated `conductTurn()` to collect stream events and persist `assistant_parts` after a successful stream finish.
  • Added `buildInterviewerContext()` (drop-in for `formatHistory`) and `buildObserverContext()` for extraction-optimized prompts.
  • Added new tests (`parts.test.ts`, `context.test.ts`) and expanded core tests to validate `assistant_parts` persistence.
  • Updated SPEC/PLAN traceability to mark slice 4a complete and reference the new invariants/tests.

Technical Notes: Client hydration still uses scalar question/answer today; persisted parts lay the groundwork for later UI resume from stored parts[].

🤖 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. 2 suggestions posted.

Fix All in Augment

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

describe('interviewer-context-equivalence', () => {
it('returns prompt as-is when no turns — matches formatHistory', () => {
const result = buildInterviewerContext([], 'hello');
const expected = formatHistory([], 'hello');
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/context.test.ts:12 — Since formatHistory() now delegates to buildInterviewerContext(), these comparisons are effectively testing a function against itself and won’t catch behavior drift from the pre-refactor formatter. Consider asserting against an explicit expected string/snapshot (or keeping the old formatter in-test) so I19 is actually exercised.

Severity: medium

Fix This in Augment

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

Comment thread src/server/parts.ts
}
break;
}
case 'stream-end': {
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/parts.ts:110 — assembleAssistantParts() currently drops any in-progress tool call if a stream ends without a matching tool-call-end (the toolArgs map is never flushed). That could make persisted assistant_parts miss tool state on early termination/cancellation; consider emitting a partial tool part on stream-end.

Severity: medium

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:53 PM UTC: Graphite rebased this pull request as part of a merge.
  • Apr 2, 6:54 PM UTC: @lunelson merged this pull request with Graphite.

@lunelson lunelson changed the base branch from ln/fe-554-structured-interview to graphite-base/19 April 2, 2026 18:52
@lunelson lunelson changed the base branch from graphite-base/19 to main April 2, 2026 18:52
lunelson added 2 commits April 2, 2026 18:53
Schema migration adds user_parts and assistant_parts JSON columns to
turn table. Parts assembler converts DomainEvents into typed UIMessage
parts (reasoning, text, tool-invocation) persisted on stream finish.

Data Part schemas (data-option-selection, data-confirmation) defined
with Zod validation. Context builders (buildInterviewerContext,
buildObserverContext) replace monolithic formatHistory — different
consumers get different projections from the same turn tree.

Establishes I17 (Data Part schema validation), I18 (parts round-trip
fidelity), I19 (context builder equivalence). 24 new tests (112 total).

Made-with: Cursor
…ablished

Mark slice 4a done in PLAN.md. Graduate A22 and A23 to validated in
SPEC.md. Update invariant table with test file references and current
coverage section with new test files (parts.test.ts, context.test.ts).

Made-with: Cursor
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