Repository navigation
build: publish process-graph alone, bundling the private building blocks - #41
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (3)
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
The process-graph command line as a composition root over the other packages: sync from GitHub issues into the SQLite store through sqlite-node, then ready, blocked, impact, path, cycles, handoffs and why over the stored model, show for every view in Mermaid, DOT or the projection as JSON, add and set to author a model and its run state, and validate for the stored model or a model document. runCli takes injected ports (output streams, store opener, sources by prefix, file reads, facts and an abort signal) and resolves with an exit status, so the whole command surface runs in tests and inside a host such as Switchboard without a process; nodePorts wires the real ones, with the GitHub token from the adapter's environment helper. Each command's operation returns plain data, every command writes JSON with --json, and exit statuses separate usage errors, missing identifiers, invalid models and source refusals. A sync merges every page into the model in one write; when a source fails part way the pages already read are saved and the error prints the command that resumes with --after.
The bin runs the command line when it is loaded, so a bundler must not treat it as free of side effects; every other module is.
The entry point now installs the command line as process-graph, delegating to the CLI package's library entry with its own name and version. The library it exports stays isomorphic, because the bin is excluded from the web-only typecheck program and exempt from the import ban, since it is run rather than imported, and the CLI is not re-exported.
The pins named versions the workspace has since released past, so pnpm resolved registry copies instead of linking the siblings, and syncpack reported the drift.
The package is now built with tsdown, which inlines the workspace packages it re-exports, their declarations included, and keeps every third-party library an import. Besides the root entry, which is unchanged, each building block is reachable through its own subpath: layout, source/github and its node token helper, store, store/node, store/wasm and its worker module, and cli. Each subpath loads only the chunks and libraries it reaches. The workspace packages move to devDependencies, since nothing of them ships but the inlined code. zod and trilean, which the root entry needs, are dependencies; the libraries only other subpaths reach are optional peer dependencies, so installing the package for its root entry stays light.
knip takes the package's entry points from its tsdown configuration. The bundle's optional peers that only the built output imports are named, since knip traces src/, which reaches them through the workspace packages the bundle inlines.
The headless hooks and components, the styled components and the React Flow views are bundled as process-graph/react, process-graph/ui and process-graph/react-flow. They stay three subpaths because the styled components reuse the headless components' names. The bundler carries no CSS across, so the two compiled stylesheets are copied beside their subpaths and exported as ui/style.css and react-flow/style.css, and stylesheets are listed as side effects. React, React DOM, React Flow and Vanilla Extract are optional peer dependencies.
A scenario through a decision's branch now projects that branch as an alt fragment, which the Mermaid emitter draws as a block and the DOT emitter as a message label prefix.
Projected flowchart edges and state machine transitions now carry the model transitions they stand for, so the emitter fixtures state them.
Only process-graph is published; it bundles the others, so they need no place on the registry of their own. The versions already published stay where they are.
A private package now runs only the npm plugin, which bumps its version and skips publishing, so it writes no changelog and creates no GitHub Release. It keeps its tag, which the orchestrator reads to find its last release, and its release still cascades to process-graph through devDependencies.
…workspace With only process-graph published, the private packages need not name installable versions. Each now takes its third-party versions from the one catalog in pnpm-workspace.yaml and its siblings through workspace:*, so a version is written once. The published manifest keeps exact literals, because @semantic-release/npm publishes with npm publish, which ships a catalog or workspace protocol specifier verbatim. syncpack enforces the catalog and the workspace protocol in private manifests. scripts/check-published-manifests.ts, now part of deps:lint, fails on a protocol specifier or a range in a published manifest, on a version there that differs from the catalog's or the sibling's own, and on a catalog entry that is not exact. The process-graph packages leave the install age exclusions, since nothing installs them from the registry any more.
…alls it The smoke test now packs the package with pnpm pack, installs the tarball and its peer dependencies with npm into a throwaway project outside the repository, and imports every subpath from there, running real work through each: a model projected and reasoned over, a flowchart laid out, a store saved and loaded on node:sqlite, a command run through the Node ports, and the bin's help and version. It also checks that the packed manifest ships no catalog or workspace specifier, that no shipped file names a private workspace package, and that both stylesheets resolve through their subpaths.
…m store A browser integration test starts workers on the bundle's store/wasm/worker entry and connects through its store/wasm entry in Chromium, with no cross-origin isolation, and runs the store contract's conformance kit and a reopen check against them. Integration tests now wait for the package's own build, since this one runs its built output.
… packages The package table separates process-graph from the internal packages, the release section says what a private package gets, and adding a package now means a private package exposed through a subpath of process-graph, with no npm name to reserve.
Each internal package's README drops its npm and release badges and says where process-graph exposes it.
npm 11.19.0, which the pinned Node ships, fails with ERESOLVE on drizzle-orm 1.0.0-rc.4's optional effect peer range even when drizzle-orm is installed on its own; npm 11.19.1 resolves it.
They count reads at a size and its double, so their duration is the machine's, not a property of the code. The largest diffFlowchart case sat near the default per-test timeout under coverage and crossed it whenever CI ran every package uncached. Fixes #42
The process-graph bin exits with it when the optional peers the command line imports are not installed. exit-codes is its own entry so the bin can read the status without loading the command line.
Before loading the command line, the bin checks that the optional peers it imports resolve. When any do not, it prints one message naming them and the command that installs them at their declared versions with the package manager that ran it (npm when none did), and exits with the missing-peers status without a stack trace. The smoke test installs the packed package without its peers and checks that message and status.
fa9827d to
698f86c
Compare
…napshot that exists The lockfile resolved @vitest/browser-playwright for process-graph against a vite peer variant with no snapshot entry, so a clean install on Linux left the package unlinked.
|
@codex security review |
1 similar comment
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 1afd16a454
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
…d line writes
Synced titles, labels and identifiers reached the terminal verbatim, so an ESC
sequence in an issue title could clear the screen or set the clipboard (OSC
52), and a bidirectional override could reorder what is shown. Every write now
crosses one boundary that writes C0 controls other than line feed and tab, DEL,
C1 controls and the Unicode bidirectional and invisible format controls as
visible escapes of their code points (\u{1b}). The Mermaid and DOT emitters
escape inside their own label escaping, so diagrams stay well-formed, and
--json writes the same characters as JSON escapes, leaving parsed values
unchanged.
|
@codex security review |
1 similar comment
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 8d240651ce
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
The default data directory, the database and the -wal and -shm files took the process umask, so under the usual umask other users on the host could read synced titles and relationships from a predictable path. On Unix the command line now creates its default directory, and the directories it creates above it, as 0700, and creates the database as 0600 before SQLite opens it, which gives the sidecars the same mode. An existing default store readable by others is narrowed, and the port returns a warning the command line prints once on standard error. At a user-named path only a database the command line creates is made private; the user's directory and files are left alone.
|
@codex security review |
1 similar comment
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 176c3ea4bb
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
Enumerated ranges missed bidirectional controls such as U+061C, the Arabic letter mark, which reached human and --json output raw. Everything in Cc, Cf, Zl, Zp, Cn and Co is now escaped, by code point, apart from line feed, tab and the zero-width non-joiner and joiner, which emoji sequences and several scripts need. Escapes beyond the Basic Multilingual Plane are written whole in text and as surrogate pairs in JSON.
It types the React and Next.js configs as the arrays they are, so the React config is spread rather than nested. eslint-plugin-json-canonical, which it now depends on, is ExaDev's own and joins the install age exclusions.
packageLintConfig takes the package's other entry files and passes them to exadev/barrel-policy's entries option, so process-graph's subpath modules are held to re-exports like src/index.ts instead of having the rule turned off.
|
@codex security review |
1 similar comment
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Only a main thread may set the umask, and Vitest runs tests in worker threads, under Stryker always, so the dry run failed. A probe script opens the default store in a process of its own under umask 022 and 000 and prints the modes it made; the narrowing and user-path cases need no umask and stay in process.
|
@codex security review |
1 similar comment
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Publishes one package, the unscoped
process-graph, and makes every other workspace package private and bundled into it. Supersedes #34: its CLI commits are carried here, rebased onto main, with the fallout from the projection changes on main fixed in the CLI's tests.process-graphis now built with tsdown (what cosmiconfig-extends, json-compose, trilean, config and most of the other ExaDev libraries use), which inlines the private packages' JavaScript and declarations and keeps every third-party library an import;deps.onlyBundlefails the build if anything else would be inlined. Following documents.js, each part is a subpath export:process-graphdag(unchanged)process-graph/layoutprocess-graph/source/github,/source/github/nodeprocess-graph/store,/store/nodenode:sqlitedriverprocess-graph/store/wasm,/store/wasm/workerprocess-graph/react,/ui,/react-flowprocess-graph/ui/style.css,/react-flow/style.cssprocess-graph/cliand the binprocess-graphbinzodandtrileanare dependencies because the root entry needs them; everything only another subpath needs is an optional peer dependency, so installing the package for its root entry stays as light as before. The command line's text output escapes every character in the Unicode categories Cc, Cf, Zl, Zp, Cn and Co (except newline, tab, ZWNJ and ZWJ), so a synced title cannot act on the terminal, and on Unix the default store's directory and files are created and kept owner-only. The bin checks that the peers the command line imports resolve before loading it; when any are missing it prints one message naming them and the install command for the package manager that ran it, and exits with status 6, a new documented exit status, with no stack trace. The internal packages aredevDependenciesat exact versions, which is also what makes a change in one of them releaseprocess-graph: the orchestrator followsdevDependenciesand forces a patch on the dependent (the dry run on this branch shows the cascade). Afeatin a private package therefore lands as aprocess-graphpatch; that is ExaDev/semantic-release-workspace#80.Private packages keep a version and a tag, which the orchestrator needs to find their last release, but now run only
@semantic-release/npm, so they get noCHANGELOG.mdupdates and no GitHub Release. The orchestrator has no way to drop the tag.Dependencies now come from a pnpm catalog: private manifests use
catalog:andworkspace:*, enforced by syncpack. The published manifest keeps literal exact versions, because@semantic-release/npmrunsnpm publish, which ships those specifiers verbatim;scripts/check-published-manifests.ts, added todeps:lint, fails on a protocol specifier or range there, on a version that differs from the catalog's or the sibling's, and on a catalog entry that is not exact.@exadev/process-graph-*andprocess-graphleaveminimumReleaseAgeExclude.The smoke test now packs the package, installs the tarball and its peers with pnpm into a throwaway project (npm 11.19.0, which the pinned Node ships, cannot resolve drizzle-orm 1.0.0-rc.4's optional
effectpeer at all), imports every subpath there, runs real work through each and the bin, and checks that the packed manifest has no protocol specifier, no shipped file names a private package, and both stylesheets resolve. A new browser integration test runs the store contract's conformance kit against the bundledstore/wasmworker in Chromium.attw --profile esm-onlyandpublintpass on the package.The subpath modules are pure re-exports.
@exadev/eslint-config3.1.0 adds anentriesoption toexadev/barrel-policy(ExaDev/eslint-config#135), whichpackageLintConfignow passes through, so the package declares them as entry points and the rule still holds them to re-exports; no rule is turned off anywhere.Every package was rebuilt uncached in CI, which pushed a work-growth case in projection's
bounded-worktest past Vitest's default per-test timeout under coverage; those cases now run without a clock bound, since they assert counted reads. Fixes #42.The already-published
@exadev/process-graph-*versions stay on the registry; deprecating them is left to a separate decision.