FE-1406, FE-1431, FE-1504, FE-1506, FE-1505, FE-1431, FE-1507, FE-1521, FE-1522, FE-1524: Consolidate the Brunch harness mission stack - #9463
Conversation
Squashes the changes reviewed in #9327.
Squashes the changes reviewed in #9337.
Squashes the changes reviewed in #9345.
Squashes the changes reviewed in #9346.
Squashes the changes reviewed in #9347.
Squashes the changes reviewed in #9348.
Squashes the changes reviewed in #9349.
Squashes the changes reviewed in #9381.
Squashes the changes reviewed in #9382.
Squashes the changes reviewed in #9384.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
PR SummaryMedium Risk Overview Server and identity: Flue instance ids are SHA-256 hashes of Petrinaut panel: The local-storage demo drops the Docs, deps, CI: App dependencies drop direct elicitor plugins/core harness in favor of binding-flue + transport + petrinaut-core; OpenTelemetry is instrumented. Reviewed by Cursor Bugbot for commit 58058c7. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3704688. Configure here.
Carry transport idempotency keys into Flue dispatch so repeated initial and client-tool-result POSTs converge on their original submissions. Project an awaiting browser tool as input-available until its correlated client-tool-result signal exists.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9463 +/- ##
==========================================
- Coverage 61.01% 61.01% -0.01%
==========================================
Files 1448 1449 +1
Lines 144648 144663 +15
Branches 6692 6692
==========================================
Hits 88262 88262
- Misses 55282 55297 +15
Partials 1104 1104 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Remove the cache opt-outs introduced during the monorepo import. All six builds declare dist outputs and hit the local Turbo cache on an unchanged second run.
|
Enabled normal Turbo caching for all six Brunch build tasks in |
Note, that on |
Benchmark results
|
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2002 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 1002 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 3314 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 1527 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 2078 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 1033 | Flame Graph |
policy_resolution_medium
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 102 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 269 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 108 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 133 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 63 | Flame Graph |
policy_resolution_none
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 8 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 3 | Flame Graph |
policy_resolution_small
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 26 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 94 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 27 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 66 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 29 | Flame Graph |
read_scaling_complete
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id;one_depth | 1 entities | Flame Graph | |
| entity_by_id;one_depth | 10 entities | Flame Graph | |
| entity_by_id;one_depth | 25 entities | Flame Graph | |
| entity_by_id;one_depth | 5 entities | Flame Graph | |
| entity_by_id;one_depth | 50 entities | Flame Graph | |
| entity_by_id;two_depth | 1 entities | Flame Graph | |
| entity_by_id;two_depth | 10 entities | Flame Graph | |
| entity_by_id;two_depth | 25 entities | Flame Graph | |
| entity_by_id;two_depth | 5 entities | Flame Graph | |
| entity_by_id;two_depth | 50 entities | Flame Graph | |
| entity_by_id;zero_depth | 1 entities | Flame Graph | |
| entity_by_id;zero_depth | 10 entities | Flame Graph | |
| entity_by_id;zero_depth | 25 entities | Flame Graph | |
| entity_by_id;zero_depth | 5 entities | Flame Graph | |
| entity_by_id;zero_depth | 50 entities | Flame Graph |
read_scaling_linkless
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | 1 entities | Flame Graph | |
| entity_by_id | 10 entities | Flame Graph | |
| entity_by_id | 100 entities | Flame Graph | |
| entity_by_id | 1000 entities | Flame Graph | |
| entity_by_id | 10000 entities | Flame Graph |
representative_read_entity
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1
|
Flame Graph |
representative_read_entity_type
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| get_entity_type_by_id | Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba
|
Flame Graph |
representative_read_multiple_entities
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_property | traversal_paths=0 | 0 | |
| entity_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=0 | 0 | |
| link_by_source_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true |
scenarios
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| full_test | query-limited | Flame Graph | |
| full_test | query-unlimited | Flame Graph | |
| linked_queries | query-limited | Flame Graph | |
| linked_queries | query-unlimited | Flame Graph |

🌟 What is the purpose of this PR?
Land the accepted Brunch work from FE-1406 through FE-1524 through one stable review and merge surface. The ten-PR Graphite stack repeatedly lost approvals when a parent merged and GitHub rebased the remaining branches, so this PR preserves the sequence as ten ordered commits plus three follow-up fix commits on current
mainwithout making the consolidation branch part of another Graphite stack.The final production throughline is the one established by the accepted missions:
Petrinaut assistant panel → AI SDK /api/chat → Brunch-hosted plain Flue ChatAgent → model and tools → AI SDK stream → same Flue conversation, followed by an explicit harness-side capture sweep over a settled history range. The proof establishes that this integrated path is durable and that reapplying the range does not duplicate captures. It does not establish Mission 3's runbook/template/headless-PN path, extraction quality, a typed IR, session-as-net, or two brains.The Brunch context root is
libs/@hashintel/brunch-agent/. ItsAGENTS.mddefines the mission and PR-writing contract used below.🔗 Related links
libs/@hashintel/brunch-agent/docs/mission-archive/1-bare-petrinaut-flue-chat.mddocs/mission-archive/2-mechanical-capture-sweep.mdMISSION.md🚫 Blocked by
🔍 What does this change?
main.{ awaiting: "client" }sentinel as a pending browser tool until a correlatedclient-tool-resultsignal supplies the actual output.dist/**outputs, and no evidence-backed non-hermetic reason for the import-era opt-outs remains.🏗️ Agent notes
Consolidation mission
Imperative: Get the accepted Brunch sequence through CI, review, and merge without another parent-merge rebase dismissing approvals. This is a delivery repair for the existing work, not a new product mission.
Throughline:
current main → ten original branch deltas in order → one plain Git branch → one GitHub CI/review/merge surface. At the production boundary carried by those deltas:Petrinaut panel → transport-aisdk → Flue ChatAgent and canonical history → explicit harness apply-sweep → capture store keyed by Flue conversation identity → same range reapplied → same capture identities.Proof: (1) the branch is based directly on current
origin/main; (2) each original branch has one corresponding ordered commit; (3) the affected package tests, type checks, lint, builds, and architecture checks pass; and (4) the final Mission 1/2 throughline tests observe durable chat, tool return, history hydration, skill activation, capture creation, and idempotent reapplication. This proves a mergeable representation and the claims already closed by Missions 1 and 2. It does not prove Mission 3, improve extraction, join capture to an IR, or validate the approval workaround until GitHub actually merges this PR without rewriting it.Constraints: Preserve semantic order and final content; keep FE-1525 out; keep this branch untracked by Graphite; retain the original PRs as review evidence until acceptance; preserve the topology gates in the Brunch context root; make no new harness mechanism for the sake of consolidation.
Fog-line: GitHub CI and merge behavior are still live evidence. Do not claim the approval-reset problem resolved until this plain branch passes required checks and merges without a history rewrite. Any failure must be discriminated as stack integration, current-
maindrift, or unrelated CI infrastructure before changing product code.Stop or reorient: Stop if current
mainrequires a semantic conflict resolution, if a correction changes an accepted mission's product behavior, if FE-1525 enters the branch, or if GitHub/Graphite begins rewriting this plain branch.Observed proof and fog-line answers
mainwithout merge conflicts and remain ten commits in their original order, followed by three fix commits rather than a history rewrite.mainchanges and the two test/lint corrections named above. The additional commit now pins retry convergence and truthful pending-client-tool projection.Carried flags
MISSION.md, but FE-1525 and its implementation are intentionally excluded.Included stack
Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
The affected Brunch packages are private
0.0.0-privateworkspaces.📜 Does this require a change to the docs?
The changes in this PR:
User-facing guidance, ADRs, specifications, evidence, mission archives, and the context-root mission declaration are updated with the behavior they accompany.
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
turbo.json's have been updated to reflect thisyarn workspace @apps/brunch-agent test:unitdirectly does not build workspace dependencies. Build@hashintel/brunch-agent-binding-fluefirst, or use the root Turbotest:unittask, whose dependency graph builds prerequisites.input-available, but AI SDK does not invokeonToolCallmerely because an initial/hydrated message contains such a part. Full hard-reload execution and resume whilereadPetrinautDocis pending remains unproven; this PR does not blanket-replay hydrated client tools because mutating tools would make that unsafe.🐾 Next steps
MISSION.next.mduntil separately cut and re-earned.🛡 What tests cover this?
apps/brunch-agent/test/petrinaut-chat.test.tsdrives the real Mission 1/2 entrypoint and covers the plain Flue chat door, server/client tools, canonical history, mounted skill, no interviewer sweep tool, capture creation, idempotent reapplication, duplicate initial/resume delivery convergence, and pending-client-tool history projection before resume.@apps/petrinaut-websiteunit tests cover principal/conversation identity, panel transport, and Flue-history hydration.apps/brunch-agent/test/flue-transcript.test.tspins pending and completed browser-tool projection, including a completednullresult..github/actions/prune-repository/prune_test.pypins the requested-scope extras, and a local reproduction of the CI prune followed byturbo run test:unit --env-mode=loose --filter @hashintel/brunch-agentpasses all 18 files and 198 tests (197 passed, one skipped).turbo run buildinvocations prove the cache change: the first run built all six Brunch tasks with cache misses; the second reported cache hits for all six (6 cached, 7 total, with the unrelated@hashintel/petrinaut-corebuild still opting out independently).All
test:unit,lint:eslint, andlint:tsctasks pass for@hashintel/brunch-agent,@hashintel/brunch-agent-binding-flue,@hashintel/brunch-agent-transport-aisdk,@hashintel/brunch-agent-plugin-gherkin,@hashintel/brunch-agent-plugin-sdcpn,@apps/brunch-agent, and@apps/petrinaut-website.@hashintel/petrinautalso builds successfully.❓ How to test this?
yarn install.turbo run test:unit lint:eslint lint:tsc --filter=@hashintel/brunch-agent --filter=@hashintel/brunch-agent-binding-flue --filter=@hashintel/brunch-agent-transport-aisdk --filter=@hashintel/brunch-agent-plugin-gherkin --filter=@hashintel/brunch-agent-plugin-sdcpn --filter=@apps/brunch-agent --filter=@apps/petrinaut-website.yarn workspace @local/petrinaut-arch-docs lint:arch-docs.apps/brunch-agent/test/petrinaut-chat.test.ts: the same production door must showactivate_skill, one capture envelope per named user entry, and the same capture ids with non-emptyskippedDedupKeyson reapplication.<flueInstanceId>.jsoncapture file. The interviewer must not expose a sweep tool.📹 Demo
No new recording was made for this delivery-only consolidation. The durable proof is the production-path test and the accepted Mission 1 human-run record linked above.