Skip to content

FE-1828: Add interview length controls to Brunch - #10053

Merged
lunelson merged 8 commits into
mainfrom
ln/fe-1828-interview-length
Oct 22, 2026
Merged

lunelson merged 8 commits into
mainfrom
ln/fe-1828-interview-length

Conversation

@lunelson

@lunelson lunelson commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

🌟 Purpose

People can choose how much questioning Brunch does before it wraps up, through an experimental Interview length setting in Chat and Voice. Minutes are an estimate derived from replies remaining, not a timer.

To see it working:

  1. Run yarn dev:brunch, then enable Use Brunch and Interview length in User settings → Labs.
  2. Open Chat, pick each stop from the icon at the left of the composer, and check Escape returns focus to the trigger.
  3. Check the estimate moves with replies, not time, and that lowering the level keeps earlier replies counted.
  4. In Voice, change the level mid-session and confirm speech is not interrupted and the collapsed dock keeps its height.
  5. Select Off, then disable the experiment; the control disappears and re-enabling restores the saved level.

🔍 Changes

  • Add a default-off Labs setting and five-stop picker: Off, Quick (~5 min), Standard (~10 min), Thorough (~20 min) and Deep (no limit). Completed replies count against mode-specific caps: text 3 / 6 / 10, Voice 2 / 4 / 7. Counts survive level changes and reloads; the wrap-up summary does not spend a question.
  • Send the current allowance with each submission as submissionContext.interviewBudget in a version-two contextual user message. Missing or malformed allowances mean Off. Off leaves the request and guidance unchanged; projection keeps submission context out of visible history and model user turns.
  • Put the allowance instruction and level guidance in the agent. At the cap, the guidance asks Brunch to settle the latest answer and read back stated facts, assumed claims and open items. Deep offers pauses instead of closing. The host's remaining count takes precedence over the Ledger's estimate.
  • Give Voice a validated startup header and quiet mid-session pacing updates. Level changes without an intervening message replace the previous display note; Live receives one update per turn, without interrupting speech. Voice reports its input mode before submission rather than the transport guessing it from message metadata.
  • Add generic Petrinaut extension points for composer status, system notes and input mode. The website owns the interview UI and counting; @hashintel/brunch-agent/interview-budget owns the allowance schema and builder, including the leaf entry needed by NodeNext Voice server code.

This replaces #9894 after the Ledger and website-layout changes. The guidance now uses Ledger appetite and assumed claims rather than retired workpiece headings. Persona runs accept --interview-length quick|standard|thorough|deep and record the choice. The old slider hover-position preview, note animation and trigger-refocus workaround were not carried over; failed quiet Live updates are logged rather than retried or shown as warnings.

The assistant-panel reconciliation was conflict-free. git range-diff matched every original feature commit after restacking. Brunch still uses the built-in chat: the empty-canvas prompt reaches the same feature-aware submission path as composer text, rather than using the plugin's new onPrompt callback. No chat migration was pulled forward.

The PR includes a patch changeset for @hashintel/petrinaut, a website user guide at apps/petrinaut-website/docs/interview-length.md, and updates to the library assistant guide and Brunch architecture docs. It does not change the Turbo graph.

Verification

The following command passed independently on this branch after reconciliation: all 54 tasks passed, exit 0. The website type check covers both browser and NodeNext API projects.

mise exec -- turbo run build test:unit lint:tsc lint:eslint \
  --filter @hashintel/petrinaut \
  --filter @hashintel/petrinaut-core \
  --filter @apps/petrinaut-website \
  --filter @hashintel/brunch-agent \
  --filter @apps/brunch-agent \
  --force --continue=dependencies-successful --output-logs errors-only

Repository-wide mise exec -- yarn lint:format also passed. Coverage includes envelope bounds and version-one byte equality, Off preserving requests and instructions, malformed allowances, remaining-count guidance, mode-specific caps, counting across wrap-up and reload, level-change note placement, context projection and quiet Voice updates.

The combined interview-length/Words empty-canvas regression test is added by the custom-words PR, not by this branch. It mounts the real website/editor/chat path and checks submission context, visible refusal, close/reopen without resubmission and subsequent composer context.

⚠️ Known issues

  • Caps are model instructions, not a hard cutoff. Real-model persona counts, live-audio behavior and the manual browser scenarios above remain unverified on the reconciled branch. No screenshot or recording is attached yet.
  • The built-server Words check on the custom-words branch fails before reaching the agent: Winston throws TypeError: isStream is not a function in DerivedLogger.add during Brunch logger construction. A fresh forced build of main passed all 29 build tasks, but loading that built application reproduced the identical startup failure. The feature stack changes neither the logger, its build configuration, backend-utils nor the lockfile. Whether to fix this here or separately is not yet decided; no logger/bundler fix is included.
  • Level-change display notes live only in the mounted session.
  • The agent reads the allowance from the current delivery, so a signal delivery carries none. In-band browser results are not signals on this base. The later ledger reconciliation still needs to settle how per-submission feature context survives its transport changes.

🚫 Blocked by

  • Run the support-desk-staffing persona at Quick, Standard and Thorough and check observed question counts. Real-model adherence to the Ledger-oriented guidance is not yet verified.

@vercel

vercel Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hash Ready Ready Preview Oct 21, 2026 2:58pm UTC
petrinaut Ready Ready Preview Oct 21, 2026 2:58pm UTC
petrinaut-docs Ready Ready Preview Oct 21, 2026 2:58pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
hashdotdesign-tokens Ignored Ignored Preview Oct 21, 2026 2:58pm UTC

Request Review

@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps labels Oct 15, 2026
@lunelson
lunelson added this pull request to stack #10056 October 15, 2026 14:08
@lunelson lunelson self-assigned this Oct 15, 2026
@lunelson
lunelson marked this pull request as ready for review October 15, 2026 14:08
@lunelson
lunelson requested a review from a team as a code owner October 15, 2026 14:08
@cursor

cursor Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches agent prompting, message envelopes, and Voice session instructions; caps are advisory to the model rather than enforced server-side, so behaviour depends on model adherence.

Overview
Adds an experimental Interview length flow so people can cap how many Brunch questions run before wrap-up in Chat and Voice, with minutes shown only as an estimate from replies left.

The website persists a Labs toggle and level, renders a five-stop picker and status pill via new Brunch assistant hooks (renderComposerStatus, level-change system notes), and attaches submissionContext.interviewBudget on each send using mode-specific caps (text vs Voice). @hashintel/brunch-agent gains the allowance schema, a leaf interview-budget export, and v2 contextual messages; the Petrinaut agent reads the budget from the current delivery (not initial data), strips submission context in Brunch context projection, and mounts a conditional interview-budget instruction plus Interview length guidance in eliciting. Live Voice passes a validated startup header and sends quiet mid-session pacing notes without interrupting speech. Persona evals gain --interview-length. Brunch panel transport drops sweep-stream decoration; @hashintel/petrinaut adds generic composer/Voice layout slots (per changeset).

Reviewed by Cursor Bugbot for commit 4d1fdc8. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

kostandinang
kostandinang previously approved these changes Oct 16, 2026
lunelson and others added 8 commits October 21, 2026 16:36
Carry an optional question allowance in a version-two contextual user
message, read it from the current delivery, and restate it as the agent's
one conditional instruction. The eliciting skill says how each level
changes questioning and records the level on the `appetite` entity; the
context projection keeps submission context out of the model's view of
user turns. Without an allowance, requests and guidance are unchanged.

Co-authored-by: Kostandin Angjellari <kostandinangjellari@gmail.com>
Add a default-off Interview length Labs setting and a five-stop picker in
the composer and Voice dock. Brunch counts completed replies against a
per-mode cap, sends the allowance with each submission, shows an estimate
from questions left, notes level changes in the transcript, and passes the
level to Live without interrupting speech. Petrinaut gains generic
`renderComposerStatus`, `renderSystemMessage` and `inputMode` slots.

Co-authored-by: Kostandin Angjellari <kostandinangjellari@gmail.com>
Tell the agent that the host's remaining count replaces its own estimate of
turns left and to record the level only until the appetite entity has it.
Give the library a dependency-free interview-budget entry that owns the
levels and the allowance builder, so the website derives its levels, caps
and allowance from it. Send Live a quiet note per level change without
pending or failed states, drop the note animation, slider hover preview
and trigger refocus workaround, and correct the changeset and docs.
Add `--interview-length` to the persona launcher: it turns on the
website's Interview length at that level through the panel's storage and
records it in `run.json`, so Quick, Standard and Thorough runs of a case can
be compared. The transport no longer guesses Voice from a message's source:
Voice reports its input mode when it mounts, before it can submit.
The share dropdown renders inside the full editor, which takes over a
second under CI load, past Testing Library's one-second default. It failed
intermittently on unrelated branches; wait up to five seconds for each step.
Without it, re-hovering the trigger showed the tooltip over the picker's description. Disabling the tooltip remounts the trigger, so restore focus to it after Escape, as #9894 did.
Only the Off note carried the guard; the notes for Quick, Standard, Thorough and Deep reused the startup instruction without it.
Dragging the rail, stepping with the keys or clicking stops set the level
at every stop, so the transcript stacked a note per stop and Live got a
quiet note per stop. A change with no message since the last note now
replaces it, and returning to the earlier level removes it. Live hears the
level once per turn: when the person's utterance is finalized or before
Brunch's next reply, only if it differs from what Live last heard.
@lunelson
lunelson added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit 7acf93b Oct 22, 2026
72 checks passed
@lunelson
lunelson deleted the ln/fe-1828-interview-length branch October 22, 2026 10:03
@hash-release hash-release Bot mentioned this pull request Oct 22, 2026

This branch was successfully deployed

3 active deployments
Preview – hash — 4d1fdc80 Deployed Oct 21, 2026 by vercel[bot]
Preview – petrinaut-docs — 4d1fdc80 Deployed Oct 21, 2026 by vercel[bot]
Preview – petrinaut — 4d1fdc80 Deployed Oct 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

3 participants