H-6788: Port the Petrinaut GAIOS wrapper's diff support and deploy it from Vercel - #160
H-6788: Port the Petrinaut GAIOS wrapper's diff support and deploy it from Vercel#160claude[bot] wants to merge 10 commits into
Conversation
The tool could not be built, so it could not be published. `@hashintel/ds-components` imports `@hashintel/ds-helpers/css`, but `ds-helpers@0.1.1` is a broken publish whose tarball omits the `styled-system` directory its `files` field promises, so the import fails to resolve. `0.1.2` is the only release that ships it; later ones, `0.2.1` included, are broken the same way, which rules out moving to a newer `@hashintel/petrinaut` until the release is fixed upstream. Pin `ds-helpers` to `0.1.2` as both a direct dependency and a `pnpm.overrides` entry. The override alone has no effect, because `ds-helpers` reaches this package as an auto-installed peer of `ds-components` rather than as a dependency. Adopt pushwork as the publishing path, matching `packages/gaios` in CatColab: take it as a devDependency and point the `push` script at `pushwork sync`, replacing the `patchwork push` command that no longer exists. Pushwork always ignores `node_modules` and reads `.pushworkignore` rather than `.gitignore`, so `dist` still syncs as the artifact directory while staying out of git. Move `@inkandswitch/patchwork-bootloader` to devDependencies, where it belongs now that it only supplies the build-time externals list, and bump it to ^0.6.2 so that list matches the importmap the Patchwork hosts actually serve. Under ^0.0.4 the list was a stale subset, which bundled second copies of modules the host already provides.
0.0.16 redesigned the editor's props. It no longer takes a net definition plus a mutation callback; it takes a `PetrinautDocHandle`, Petrinaut's own interface over a bare SDCPN. Adapt the Automerge handle Patchwork supplies into that shape, projecting the net out of `petriNetDefinition` and writing edits back in place so the surrounding `title` and `@patchwork` metadata are untouched. This also retires the React Automerge hooks and the `RepoContext` wrapper, which resolves the duplicate-`Repo` type conflict they carried. Pass the simulation, Monte Carlo and language-server workers explicitly from `@hashintel/petrinaut-core/workers/*`, which is what consumers of the published dist are meant to do — the bundled fallback workers are only reliable for source builds. Those exports are factory functions rather than worker entry scripts, so importing them with Vite's `?worker` suffix builds without complaint but emits empty 1-byte workers. Follow the data model where it moved: input arcs now carry a `type` of "standard" or "inhibitor", and a differential equation's `colorId` is nullable. The skill API gains inhibitor arcs as a result, since they are new capability rather than only a type change. Pin `@hashintel/ds-components` forward to ^0.2.2 to match what 0.0.16 expects, while holding `@hashintel/ds-helpers` at the broken-publish workaround of 0.1.2 — the new chain only needs its `css` and `tokens` entry points, both of which 0.1.2 ships. Both have to be direct dependencies: they arrive as auto-installed peers, which pnpm resolves before overrides apply, so an override alone does not bite. Bump `@inkandswitch/patchwork-plugins` to ^1.2.2 and move it to devDependencies alongside the bootloader. It is externalized through the host's importmap, so it is a build-time type dependency only, and the old version pinned automerge-repo to 2.5.0 against the 2.5.4 used elsewhere.
The existing `patchwork:skill` pairs SKILL.md with the typed API in skill-api.ts, which only helps an agent that can call that API. Patchwork's chat computer has no such surface — it edits documents through generic read_doc and automerge_op calls — so it needs the net's schema written out to do anything useful with a Petrinaut document. Register an `llm:skill` carrying the SDCPN shape, the automerge_op recipes for adding and removing entities, and the exact module contracts for the code surfaces (lambdas, transition kernels, dynamics, visualizers, metrics). It names the traps that are invisible from the document alone: place names are part of the code surface, so renaming one breaks every lambda that reads it, and deleting a place leaves arcs pointing at nothing. The skill declares the petrinaut-petrinet datatype, so it activates on its own whenever such a document is focused. The domain content is adapted from `petrinautAiPrompt`, which petrinaut-core now exports, rather than reused verbatim: that prompt directs the model at Petrinaut's own in-app tools, which do not exist in the Patchwork chat.
Subscribe to Patchwork's `draft:baseline` provider and diff the net at the draft's fork point against the live one, the way the gaios tool does for CatColab notebooks. Petrinaut takes no diff prop, so the result is drawn from the outside: added and edited places, transitions and arcs glow via a stylesheet keyed on the ids React Flow stamps onto its nodes and edges, and removed ones are redrawn as ghosts in React Flow's viewport portal, which pans and zooms with the canvas. Nothing is written back into the net, so a removed place cannot turn up in the sidebar, the compiler or a simulation.
The build stages package.json next to dist/ in vercel-static/ and serves that directory, because a Patchwork host fetches package.json at the root of the URL it is given and resolves that file's exports entry relative to the same root. The Access-Control-Allow-Origin header is needed because the host loading the module is a different origin.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency ReviewThe following issues were found:
|
|
The
It isn't this branch: the symlink blob is byte-identical on No fix for it exists anywhere to port into this PR, and repointing the symlink needs someone who knows whether
Generated by Claude Code |
|
Where it comes from: There is nothing to port: The fix belongs upstream in Actual exposure here is nil, which is why this isn't being treated as urgent: both advisories are a Node filesystem read triggered by parsing untrusted CSS, this package has no Deliberately not doing two things: no global One caveat for whoever does the bump: the Generated by Claude Code |
`@pandacss/core` exact-pins `postcss` 8.5.14, which carries GHSA-r28c-9q8g-f849 and GHSA-fxqj-rqcc-2cmp, and `@pandacss/dev` reaches the wrapper through `@hashintel/ds-components`' runtime dependencies. Panda's own pin was itself a CVE bump rather than a compatibility constraint, so moving it forward is safe. `hashintel/hash` carries the same override in its root manifest.
Bump @hashintel/petrinaut to 0.0.19, @hashintel/petrinaut-core to 0.0.4, @hashintel/ds-components to 0.3.1 and @hashintel/ds-helpers to 0.2.2. The ds-helpers override is no longer needed because 0.2.2 ships its styled-system directory again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K4q91RTouLDQUpcwnTPfjN
petrinaut-core 0.0.4 made an arc's endpoint optional so that an arc can target a component-instance port instead of a place, and added a "read" input-arc type. The diff overlay and the skill API stay place-only, so arcs targeting a component port are excluded. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K4q91RTouLDQUpcwnTPfjN
fast-uri and qs re-resolve on their own, because ajv and express already allow the patched versions. browserslist and postcss-selector-parser need overrides, because @pandacss/* exact-pins both in every published release, including 1.12.0, and Panda only drops those pins in its v2 line, which is still in beta. Overriding browserslist also collapses the dev-only copy that @vitejs/plugin-react pulls in, since its range admits the patched version. All four reach the graph as runtime dependencies only because @hashintel/ds-components lists @pandacss/dev in dependencies, and none of them appear in the built bundle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K4q91RTouLDQUpcwnTPfjN
Petrinaut core supports a third input arc type, "read", which the chat computer's instructions did not mention. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K4q91RTouLDQUpcwnTPfjN
<!-- ccr-slack-attribution -->
Requested by Ciaran Morinan · Slack thread
Before:
pocs/petrinaut-patchworkpinned Petrinaut 0.0.11 and prop-drilled the net into the editor, published through thepatchworkCLI, and offered a chat host no way to author a net beyond the existingpatchwork:skill. Opening a draft showed the net exactly asmaindid, with nothing to indicate what the draft had changed. Nothing built or deployed the package: publishing was a manualpnpm pushfrom someone's laptop.After: the wrapper tracks Petrinaut 0.0.16 through its handle-driven editor API, publishes with
pushwork, registers anllm:skillso Patchwork's chat computer can build nets against the raw document, and lights up on the canvas whatever the current draft added, changed or removed. Avercel.jsonbuilds the package on push and servespackage.jsonalongsidedist/, so a Patchwork host can load the tool from a stable URL.How
The first four commits are ported unchanged from
inkandswitch/hash-labs@petrinaut-with-diffs, cherry-picked with Paul Sonnentag's authorship intact. That branch is a four-commit descendant of4c1a5fdon this repo'smainwith no file overlap against anything since, so the port is a clean fast-forward ofpocs/petrinaut-patchworkand touches nothing else.The fifth commit adds
vercel.json. The build stages avercel-static/directory holdingpackage.jsonnext todist/, and serves that as the output directory, because a Patchwork host fetchespackage.jsonat the root of the URL it is given and resolves that file'sexportsentry relative to the same root — so the deployment has to serve/package.jsonand/dist/index.js, which is also the layoutpushwork syncmirrors into an Automerge folder doc. TheAccess-Control-Allow-Origin: *header is required because the host loading the module is a different origin, and Vercel sends no CORS header by default.Setting up the Vercel project
Two things cannot be expressed in
vercel.jsonand have to be set on the project:pocs/petrinaut-patchwork. There is norootDirectoryproperty in thevercel.jsonschema, so this is dashboard-only. Install command, build command and output directory all come from the committedvercel.jsonand should be left unset.PROJECT.vercel.app), not a deployment-specific URL. Vercel protects every deployment except the most recent production one by default, so a preview URL answers the host'spackage.jsonfetch with a 401. The URL must also not end in.js, or the host skipspackage.jsonresolution entirely.There is deliberately no
ignoreCommand: the documented pattern (git diff --quiet HEAD^ HEAD -- ., where exit 0 means skip) only inspects the tip commit, and this repo merges through a merge queue that can advancemainby several commits at once — so a batched merge group could silently skip a deploy that should have happened. Worth adding later if the build volume becomes annoying, but a wasted build is cheaper than a missed one.Notes
pnpm install --frozen-lockfileandpnpm buildboth pass on pnpm 10.6.0 / Node 22, producing 27 files and 25 MB indist/, and the stagedvercel-static/has the intended layout. No CI in this repo builds JS, so that check was manual.tsc --noEmitreports one error,src/skill-api.ts:2importing the undeclared@patchwork/llm. It is identical onmain, type-only, and stripped by esbuild, so the build is unaffected. Left alone as pre-existing; worth a follow-up to either declare the dependency or drop the import.@hashintel/ds-helpers@0.1.2and@hashintel/petrinaut@0.0.16pins are load-bearing, for the reasons the README now records. Renovate runs on this repo and no workflow builds this package, so a bump here will break the deployment silently.src/SKILL.mdstill documents no inhibitor arcs, althoughskill-api.tsnow reads and writes an input-arctype. Ported as-is.