Skip to content

feat: add graph-cli package and the process-graph bin - #34

Closed
Mearman wants to merge 6 commits into
feat/domain-explainfrom
feat/graph-cli
Closed

Mearman wants to merge 6 commits into
feat/domain-explainfrom
feat/graph-cli

Conversation

@Mearman

@Mearman Mearman commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Adds @exadev/process-graph-cli (packages/targets/graph-cli), the command line and its library entry, and gives the unscoped process-graph package its process-graph bin, delegating to that library entry. Stacked on #32, which adds explainStatus to graph-domain for why.

Commands: sync <scope...> [--after], ready, blocked <id>, impact <id>, path, cycles, handoffs, why <id>, show --view flowchart|swimlane|state|sequence --format mermaid|dot|json [--subject] [--scenario], add participant|activity|decision|state|event|artefact|transition, set <id> <done|open|unknown> and validate [file]. Global options are --data (default PROCESS_GRAPH_DATA, else process-graph/graph.sqlite3 under the XDG data directory), --model (default default) and --json. Exit statuses are documented in the README and --help: 0 success, 1 failure, 2 usage, 3 not found, 4 invalid model (including validate issues and cycles found), 5 source refusal.

runCli(args, ports, identity) is the library entry Switchboard's sb graph forwards to: it takes injected ports (streams, store opener, sources by prefix, file reads, facts, abort signal) and resolves with the exit status, never touching the process. nodePorts wires the real ones, with the GitHub token from the adapter's githubTokenFromEnvironment. Each command's operation is also exported and returns plain data, for MCP tools.

Two deviations from the plan's row. set sets an element's run state rather than an artefact's value: the store contract has nowhere to keep facts such as which input artefacts are provided, so that is tracked in #35. add also covers activity and transition, since a decision or state cannot be connected to anything without them.

Tests run every command end to end against the source contract's in-memory fake (shaped like the GitHub adapter's output, across two repositories) and a SQLite file through sqlite-node, asserting the full text and JSON output; the emitters have their own content tests; the smoke tests run the built library and the built bin as a process.

blockedBy followed an element's unfinished needs whatever its own status, so an element the
overlay marked done ahead of its needs, or a skipped element consuming an artefact still to be
made, reported blockers. Its contract says a done or skipped element is blocked by nothing; it
now returns an empty list for both.
explainStatus names the rule of the status table that decided an element's status, the incoming
transitions and consumed artefacts it was decided from, and the blocked-by chain: every
unfinished need reached from the element with the needs each still waits on. The derivation
records this basis as it derives each status, so an explanation never re-derives it and always
agrees with deriveStatuses and blockedBy, which now share one waitingOn helper.
StatusBasis is the shape the derivation records for each element, and the fields of a status
explanation are drawn from it, so a consumer can name it.
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.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-10-10T21:53:54.551289Z 39acc99 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman

Mearman commented Oct 11, 2026

Copy link
Copy Markdown
Member Author

Superseded by the single-package restructure in PR 41, which has merged and contains this work.

@Mearman Mearman closed this Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant