Skip to content

FE-1524: Prove idempotent capture sweep on the live Flue chat path - #9384

Open
lunelson wants to merge 2 commits into
ln/fe-1522-mission-1from
ln/fe-1524-mission-2
Open

FE-1524: Prove idempotent capture sweep on the live Flue chat path#9384
lunelson wants to merge 2 commits into
ln/fe-1522-mission-1from
ln/fe-1524-mission-2

Conversation

@lunelson

@lunelson lunelson commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

🌟 What is the purpose of this PR?

Re-enter durable, source-linked capture as a pipe on the live Petrinaut ↔ Flue chat door, not as elicitation intelligence. An explicit settled Flue history range is applied into a capture store keyed by Flue conversation identity; applying the same range again yields the same capture identities. This establishes that the ledger pipe works. It does not establish extraction quality, a typed IR, a runbook, session-as-net, or two brains.

🔗 Related links

  • Linear: FE-1524
  • Continues FE-1522 / #9382 (Mission 1 chat door)
  • Mission archive: libs/@hashintel/brunch-agent/docs/mission-archive/2-mechanical-capture-sweep.md

🚫 Blocked by

  • #9382 — stacked on Mission 1 (ln/fe-1522-mission-1)

🔍 What does this change?

  • The app depends on binding-flue for this pipe only. applyCaptureSweep reads Flue history in-process, writes stub envelopes (quote = user text, payload {}), and re-applies without minting new ids.
  • Capture JSON lives beside the Flue sqlite file, named <flueInstanceId>.json.
  • ChatAgent mounts one stub skill (confirm-path) so activate_skill appears in history. The interviewer has no sweep tool.
  • The Mission 1 production-path test now also proves skill activation, idempotent apply-sweep, and empty payloads.
🏗️ Agent notes

Branch mission (closed)

Imperative: Re-enter durable, source-linked capture as a pipe, not as elicitation intelligence.

Throughline: settled Flue history range → harness apply-sweep → capture store keyed by Flue conversation identity → same range applied again → same capture identities. Stub skill on the same ChatAgent. Interviewer does not call a sweep tool. Stub extraction: one envelope per user utterance, quote = that text, payload {}.

Proof (one production-path test on the Mission 1 /api/chat door):

  1. After an explicit settled range, apply-sweep writes envelopes with evidence spans and empty payload, one per user utterance in that range.
  2. Applying the same range again yields the same capture identities and does not duplicate.
  3. The stub skill is mounted; activate_skill appears in Flue history.
  4. The interviewer never called a sweep tool; producing captures did not require a model call.

Constraints: Adapter still must not depend on core, binding, or plugins. App may depend on core/binding for this pipe only. No plugins, repertoire, kinds, slots, fold, completion, issues, or correction. No extraction LLM, sweep tool, token-threshold observer, or join to a runbook/IR template. Flue history remains the conversation log. Store key is the existing Flue conversation identity.

Observed proof

Witnessed 2026-08-27. Test: apps/brunch-agent/test/petrinaut-chat.test.tspetrinaut-chat.integration.ts.

  1. One user utterance → one envelope, excerpt is that text, payload {}.
  2. Same named user-entry ids again → same capture ids, non-empty skippedDedupKeys.
  3. defineSkill / useSkill mounted confirm-path; activate_skill { name: "confirm-path" } in history and the AI SDK stream.
  4. Interviewer tools: activate_skill, ping, readPetrinautDoc. No sweep / brunch_sweep. Stub proposals built from history text in-process.

Fog-line answers

  • apply-sweep home. In-process in the app via binding-flue (createLocalCaptureStore + createFlueHistoryReader + store.execute({ type: "apply-sweep" })). Not useElicitation, not HTTP, not useAgentFinish. Evidence-bearing apply archives quotes before execute. Session id = Flue instance id.
  • Empty payload. {} persisted with existing CaptureInputProposalSchema. No plugin catalog / trivial proposal schema.
  • Capture path. Sibling of conversations sqlite, <flueInstanceId>.json. Hermetic test: beside BRUNCH_CHAT_DB_PATH. Internal JSON remains binding's TargetDocumentRecord; app API does not expose that ontology.
  • Skill declaration. defineSkill + useSkill is enough for activate_skill in history() under node --experimental-strip-types. SKILL.md / Vite not needed.

Carried flags

  • Capture remains a provenance ledger with empty payloads. Typed payloads, token-threshold observers, and any join to a runbook or IR stay on the scratchpad.
  • Store key is Flue conversation identity. Net id as discriminator remains the unproven Host-trunk assumption from Mission 1.
  • Live MISSION.md after this close is Mission 3 (runbook / template / headless PN). That path must not wire itself to this store in order to tidy the list.

Re-enters capture-store mechanism from FE-1392 and FE-1419 without executing those issues' typed-statement outcomes. FE-1503 is unchanged.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • require changes to docs which are made as part of this PR

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

⚠️ Known issues

  • yarn workspace @apps/brunch-agent test:unit does not turbo-build workspace deps. Binding-flue must already be built (yarn workspace @hashintel/brunch-agent-binding-flue build) or CI turbo test:unit (dependsOn: ["build", "codegen", "^build"]) must run. This is existing workspace behavior, not introduced as a new mechanism.

🐾 Next steps

  • Mission 3 (cut in this PR as live MISSION.md): runbook + IR template + headless JS-API drive + off-canvas PN generation. Independent of this ledger; do not join them to tidy the list.
  • Host trunk, typed map / Petrinaut read-write, capture improvement: still on MISSION.next.md.

🛡 What tests cover this?

  • apps/brunch-agent/test/petrinaut-chat.test.ts — the Mission 1 production-path test, extended with skill activation, no sweep tool, and apply-sweep twice with identical capture ids.
  • apps/brunch-agent/test/db-path.test.ts — capture file lives beside the conversation db, named by instance id.

❓ How to test this?

  1. From repo root, after binding-flue is built: yarn workspace @apps/brunch-agent test:unit
  2. Confirm the petrinaut-chat test passes: activate_skill in history, one envelope per user utterance, second apply returns the same ids.
  3. Optional human check: yarn dev:brunch, send a panel message, then inspect <instanceId>.json beside apps/brunch-agent/.data-wipe-me/conversations.db. Capture is harness-side; the interviewer will not offer a sweep tool.

📹 Demo

No panel recording for this close. The throughline is the production-path unit test against the same /api/chat door Mission 1 named.

@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview Aug 27, 2026 5:57pm
petrinaut Ready Ready Preview Aug 27, 2026 5:57pm
petrinaut-docs Ready Ready Preview Aug 27, 2026 5:57pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview Aug 27, 2026 5:57pm

Request Review

@github-actions github-actions Bot added area/deps Relates to third-party dependencies (area) 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/tests New or updated tests area/apps labels Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

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

@lunelson lunelson changed the title Prove idempotent capture sweep on the live Flue chat path. FE-1524: Prove idempotent capture sweep on the live Flue chat path Aug 27, 2026
@lunelson
lunelson marked this pull request as ready for review August 27, 2026 17:37
@cursor

cursor Bot commented Aug 27, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Introduces a new on-disk capture store and an app→binding-flue dependency for apply-sweep, but capture stays off the chat/interviewer path and is covered by the extended hermetic integration test.

Overview
Adds Mission 2 capture as a harness-only pipe on the existing Petrinaut /api/chat door: a named range of Flue user entries is projected into stub envelopes (excerpt = user text, payload {}) and written via binding-flue apply-sweep, with idempotent re-apply (same capture ids, dedup skips). The interviewer still has no sweep tool; capture is not driven by the model.

apps/brunch-agent now depends on @hashintel/brunch-agent-binding-flue for applyCaptureSweep, which reads owned Flue history in-process and persists to <instanceId>.json beside the conversation SQLite (captureStorePath, honoring BRUNCH_CHAT_DB_PATH in hermetic tests). ChatAgent mounts a stub confirm-path skill so activate_skill shows up in history/stream; system prompt asks to activate it before ping.

The Mission 1 production-path test (petrinaut-chat) is extended to assert skill activation, absence of sweep tools, and two sweeps with stable ids. Docs/README describe capture layout; Mission 2 is archived and live MISSION.md advances to Mission 3 (runbook/template/headless PN).

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

lunelson and others added 2 commits August 27, 2026 19:41
Re-enter capture as a harness-side pipe so a named settled range can be applied twice without duplication or a model extraction call.

Co-authored-by: Cursor <cursoragent@cursor.com>
The capture pipe is proven; the next live mission is the independent prompting experiment, not a join onto the ledger.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Development

Successfully merging this pull request may close these issues.

1 participant