FE-1573: Add workpiece, construction and explanation groundwork (Mission 7a) - #9562
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
2506ec5 to
03bbac5
Compare
03bbac5 to
7fed841
Compare
7fed841 to
bba337a
Compare
|
Semgrep found 3
Possibility of prototype polluting function detected. By adding or modifying attributes of an object prototype, it is possible to create attributes that exist on every object, or replace critical attributes with malicious ones. This can be problematic if the software depends on existence or non-existence of certain attributes, or uses pre-defined attributes of object prototype (such as hasOwnProperty, toString or valueOf). Possible mitigations might be: freezing the object prototype, using an object without prototypes (via Object.create(null) ), blocking modifications of attributes that resolve to object prototype, using Map instead of object. Semgrep found 2
Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead. |
PR SummaryHigh Risk Overview Petrinaut / website: Hosts can add an AI / Workpiece (or other) additional assistant tab that keeps chat, composer, Voice, and resize behavior mounted across switches. Construction mode gains an optional synchronous Runtime / provider stack: Patched
Ops: Deploy workflow writes changed paths to a temp JSON file to avoid Reviewed by Cursor Bugbot for commit e4490ae. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
🟡 Changes recommended
Result reconciliation incorrectly treats reordered JSON keys as conflicting, and duplicate Petrinaut changesets must be consolidated.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds Mission 7a’s revisioned workpieces, bounded Petrinaut construction operations, provenance-backed explanations, and tabbed assistant-panel integration.
Changes:
- Adds durable workpiece revisions, evidence links, mutation recording, and
brunch_why. - Integrates AI/Workpiece tabs while preserving chat and Voice state.
- Expands construction operations, tests, documentation, and runtime patches.
File summaries
| File | Description |
|---|---|
.changeset/* |
Adds Petrinaut and core release notes. |
.github/workflows/deploy.yml |
Handles large changed-file lists safely. |
.yarn/patches/* |
Extends Pi/Flue schema validation and recovery behavior. |
apps/brunch-agent/** |
Implements agent orchestration, provenance, ownership, accounting, persona tooling, and integration tests. |
apps/petrinaut-website/** |
Connects Brunch transport, mutation recording, history, and the Workpiece pane. |
libs/@hashintel/brunch-agent/** |
Adds workpiece, transport, SDCPN construction, evidence, and supporting documentation. |
libs/@hashintel/petrinaut/** |
Adds assistant tabs, mutation execution boundaries, history following, and UI tests. |
libs/@hashintel/petrinaut-core/** |
Preserves place capacity and extends canonical mutation support. |
| Mission and evidence documents | Reframes Mission 7a and archives or removes superseded evidence. |
| Workspace configuration | Updates package wiring, tasks, and dependency metadata. |
Review details
- Files reviewed: 107/560 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Self-note: After this rebases post #9619 merge: test (and possibly extend voice-browser-tools.integration.test.tsx) to verify playback-only cancellation, one completed mutation, one retained submission, stable Voice state across Workpiece tabs, and no spoken tool/workpiece payloads. |
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 aaa135f. Configure here.
kostandinang
left a comment
There was a problem hiding this comment.
Looks good, but may need to check these durability risks:
-
Write ordering: persistence follows asynchronous tool completion rather than setter invocation. Parallel A→B updates could therefore be stored as B→A, restoring stale state after restart.
-
Provenance loss: the browser document is mutated before the corresponding result metadata is durably admitted. If admission fails and the page reloads, the change remains but brunch_why can no longer explain it.
-
Concurrent tabs: tabs share the persisted conversation and incarnation while holding independent document handles. Concurrent edits can fork state, with localStorage resolving them last-writer-wins.
There are also stale references to moved integration fixtures, which currently break website checks.
|
@kostandinang Thanks — I checked all four points against the current implementation.
Current parent head: |
TimDiekmann
left a comment
There was a problem hiding this comment.
Two clarification questions, but none-blocking, they can easily be addressed later.
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?
Deliver Mission 7a's workpiece, native construction and record-backed explanation groundwork. Brunch can save an evolving account, apply a bounded set of Petrinaut edits through the browser, and retrieve an edit's declared workpiece basis and linked conversation evidence through chat.
This is now an implementation PR, not the original authority-only cut. The workpiece appears in a Workpiece tab beside AI inside the existing assistant panel, replacing the intrusive overlay. Tab switches preserve the conversation, draft and active controls. The result establishes mechanical integration, not semantic model quality or the complete September demo.
Lu has split the remaining demo work into Mission 7b under the same FE-1573 issue. This PR remains draft pending UI review and integration with FE-1645.
🔗 Related links
🚫 Blocked by
🔍 What does this change?
brunch_why. Current versus historical observation, missing basis and outside changes remain explicit.aiAssistant.additionalTabhost content using Petrinaut's existing horizontal tabs. Brunch owns document rendering; raw IDs/Markdown/why JSON are expandable details. Composer, Stop, Voice and resizing remain the existing controls.🏗️ Agent notes
The current six-section mission contract follows. Code/tests and native local records carry implementation evidence; no new repository run packet is introduced.
Mission 7a — Workpiece, construction and explanation groundwork
Status
Part A closeout in progress; tabbed workpiece implemented, pending Lu's UI review and FE-1645 integration before merge. Not a demo or semantic-quality acceptance. Lu has directed a split: this branch and PR #9562 carry the mechanical groundwork; Mission 7b continues under the same FE-1573 issue on a child branch. The former full-region/100%-useful-explanation acceptance programme is not a prerequisite to this engineering split. Its surviving evaluation obligations live in the after-demo evaluation draft; the focused demo successor is the Mission 7b draft.
The current implementation saves and displays evolving workpieces, observes a bounded set of native Petrinaut mutations, and resolves their recorded basis through chat. Controlled browser tests exercise the broader surface. The retained persona session contains one parameter, one type and one equation, not a connected process model. Its lineage queries and original-store reopening were observed; semantic correspondence, automatic citation coverage, a complete construction flow, portability and demo readiness are not established. No persona, browser or paid run is active.
Local-only / not portable: the actual-session oracle is
apps/brunch-agent/.data-wipe-me/persona-runs/run-7ceo9j/and the originalapps/brunch-agent/.data-wipe-me/conversations.db. Inspect the native history, saved revisions and observed definitions, not an invented reconstruction. These local records establish observed behaviour without claiming repository-reproducible fixtures or teammate access. Commits, tests and the PR are the engineering record.Imperative
Deliver the working integration from conversation to saved workpiece, browser-applied net edits and record-backed explanation, with a usable workpiece surface rather than an intrusive debug overlay. Make that bounded result reviewable and landable independently of the complete September demo and evaluation of the prompt/skill architecture's modelling effectiveness.
The harness is structurally checked, not a semantic acceptance engine. A valid reference, applied edit or successful lookup is a mechanical result; a good model or persuasive rationale is a different judgment. Preserve that distinction without making the latter a universal execution gate.
Throughline
Delivered construction boundary
In conversation-bound construction mode, the observed mutation catalog is:
addPlace,updatePlace,addTransition,updateTransitionaddArc,updateArcWeightaddType,updateType,addTypeElement,updateTypeElementaddScenario,updateScenarioaddParameter,addDifferentialEquationThese fourteen operations are not stock-tool parity or fourteen genuine-persona demonstrations. Deletion, parameter/equation update, nested nets/components and component-port arcs are outside this observed surface. Typed-state operations also reject documents containing subnets/components. Canonical input/refinement rules still apply. Necessary native reads and compilation checks accompany this surface; compilation does not prove simulation.
UI closeout before merge
FE-1645 / PR #9634 gates the existing prepared-fixture selector behind an opt-in Brunch demo setting and moves it below the top bar. That selector is distinct from this branch's fixed
BrunchWorkpiecePane. Preserve the colleague's selector/provider behaviour when integrating; do not restore default fixture chrome or copy a competing settings mechanism.The workpiece now uses AI / Workpiece tabs in the existing assistant panel, selected by Lu in place of the separate dock. Reuse Petrinaut's tab patterns and the assistant's existing resize/collapse behaviour. Keep chat mounted across tab switches so drafts, requests and Voice lifecycle survive; maintain reachable active controls. The additional-tab extension point is generic, while workpiece/provenance semantics stay in the website host. The surface remains readable as it evolves and does not obstruct the canvas, top bar, assistant opener or composer. Keep engineering IDs, hashes and raw why payloads out of the primary reading surface while preserving inspectable provenance and honest freshness/unknown-state reporting. Hiding the useful workpiece together with fixture controls is not the fix. Inspect integration against #9634 without rewriting the colleague's branch; no full editor redesign or construction-tool rewrite belongs in this closeout.
What is linked
Petrinaut references connect net objects; they do not propagate provenance. Separately, workpiece evidence relations link revision-local text spans to authorized conversation message IDs. A construction request cites a saved revision/hash, passage locators and an operation-level rationale, or an explicit absent-basis reason. The matching browser result records actual changes. Why traverses those records; it does not infer source links from adjacency, graph connectivity or plausible prose. Brunch metadata remains outside canonical Petrinaut documents.
The implemented positive declared-basis path reports
partially-supported: operation-level links are not independently established field-level intention mappings or semantic grades. Queries can identify an object/field by unique name or ID; canvas-selection-to-source-navigation UX is not claimed by this part.Proof
Review the existing code/tests and actual-session records under their respective claim scopes. No new model-quality campaign is required to submit Part A.
packages/core/test/update-workpiece.test.ts,apps/brunch-agent/test/workpiece-revisions.test.ts, websitebrunch-workpiece-pane.test.tsx, and actual persona history/display observations. Pointer-only historical results remain readable but do not invent Markdown.test/root-node.test.ts,test/root-state.test.ts,test/declared-basis.test.ts; apptest/root-creation.integration.tsandtest/typed-state.integration.ts. Broader controlled-browser evidence, not a claim of a complete persona-built model.test/reconciliation.test.ts,test/reopened-why.integration.tsand the retained ordinary persona-session why results. Source linkage may be absent; prose quality is not guaranteed by the structured result.test/update-workpiece.test.tsand apptest/reopened-why-retention.integration.ts, implemented in367d4994fa. Source text may be clipped; IDs are not windowed.src/evaluations/persona/launch.test.ts,test/persona-browser.integration.ts, actual launcher cleanup observations. Run-local Pi trust does not add persona tools or persistent trust.Before the branch transition, retain unresolved obligations in the future record, remove the consumed ownership side quest after recording its outcome, and archive this contract with the engineering-split status explicit. Do not mark the former full Step A acceptance programme passed.
Constraints
Earned data and execution contracts
brunch_mark_question, durable nonterminatingupdate_workpieceand current-workpiece query semantics. Keep one current revision: native tool-call ID, Markdown/hash and display ordinal. A saved version is not an owner-approved meaning.brunch_workpiecereturns every authorized source ID; per-source text may be truncated. Unique unchanged same-span carry is bounded; candidate locator queries create no revision, authority or semantic-continuity claim.useBrunchAgent()plususeSdcpnPlugin(), inward dependencies and dedicated./flueresources. Prepared fixtures stay test-authored; diagnostic exports are not restoration APIs. No content-bearing telemetry, hidden persona-pack leakage or guessed operational facts labelled as testimony.Continuing operating limits
The persona's pack grounds a realistic role, not a closed factual whitelist. Natural improvisation, uncertainty and correction are allowed. Only the actor receives private background; it supplies interview utterances, not construction instructions. Keep persona and operator submissions serial, distinguish operator technical choices from testimony, and never replay old unanswered browser requests.
The maintained launcher uses Pi's run-local
--approvewith its explicit tool/extension allowlist and disabled context/skill/template discovery. Both persona and ChatAgent useanthropic/claude-sonnet-4-6withBRUNCH_STEP_A_ACCOUNTINGunset. Do not revive retired per-request holds, response deadlines, call-count gates or ledger writes; the historical ledger retains its unresolved row and released hold. Existing owner spending/escalation policy remains; this documentation split starts no provider run. Remote writes, release and Linear writes remain separately authorized.Owner decisions
Fog-line
Stop or reorient
Stop Part A expansion if a task is building the full demo rather than fixing the explicitly admitted UI blocker or a defect in the PR's stated mechanical claim. Preserve and report source/identity corruption, false effect attribution and unavailable native state; a fluently explained result must not conceal them. Do not gate this engineering split on full model fidelity, a new persona campaign, an optimiser, a new tool design or every historical proof-matrix row. Do not claim the deferred evaluation or demo passed.
Deferred
Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
The assistant guide covers the Workpiece tab and retained controls. Screenshots pending: maintainer capture/upload for the opening-panel and Workpiece sections.
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
turbo.json's have been updated to reflect thispartially-supported, not a semantic quality score.🐾 Next steps
ln/fe-1573-mission-7bfrom the inspected Part A boundary under the same issue, with one live mission on that branch.🛡 What tests cover this?
@hashintel/petrinaut,@apps/petrinaut-website,@apps/brunch-agent, with their dependencies.❓ How to test this?
VITE_BRUNCH_CHAT_ENDPOINT=/agents/chat turbo run build test:unit lint:tsc lint:eslint --filter @hashintel/petrinaut --filter @apps/petrinaut-website --filter @apps/brunch-agent.node --experimental-transform-types test/persona-browser.integration.tsfromapps/brunch-agentafter building with that endpoint. The test uses a local faux provider, writes screenshots/native test records to its reported temporary directory, and makes no live model call.📹 Demo
The local browser witness includes screenshots of the new Workpiece tab and a long document; maintainer upload is pending. The complete elicitation/construction recording and live review/correction demo are Mission 7b targets, not completed results of this PR.
Stack generated by Git Town