feat(workflows)!: render ctx.ui.* prompts as synthetic graph stage nodes - #1054
Conversation
Implement node-local workflow UI prompt stages with awaiting_input state, stage-local prompt cards, continuation replay safeguards, live-only answer replay, and hardened prompt callsite identity for packaged runtime paths. Add regression coverage for prompt-node lifecycle, continuation topology, prompt answer privacy, TUI routing, persistence restore, and packaged prompt callsite filtering. AI-Assisted-By: GPT-5.5
Implementation NotesTask: Implement #1046 Running Notes
Iteration 1 implementation (2026-05-25)
Iteration 2 implementation (2026-05-25)
Iteration 2 implementation (2026-05-25)
Iteration 3 implementation (2026-05-25)
Iteration 4 implementation (2026-05-25)
Iteration 5 implementation (2026-05-25)
Iteration 6 implementation (2026-05-25)
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Code Review — feat(workflows): render ui prompts as graph nodesThanks for this — the move from run-level overlays to node-local prompt stages is a substantive UX/state-model improvement and the test coverage (replay topology, ambiguity, parallel/concurrent prompts, privacy, callsite filtering) is impressively thorough. Below are the things worth a second look before merging; most are nits, a few are worth a comment in code, and one is a real correctness concern about the Correctness1.
|
Render stage-local text prompts through the host editor, support scrollable prompt bodies, and hide unstarted placeholder stages while prompt nodes await responses. Keep completed stage chat handles resumable until the host clears the registry, and let ctx.complete fall back to SDK sessions when no complete-adapter-specific options are used. Assistant-model: GPT-5.5
Review —
|
Assistant-model: GPT-5.5
|
Addressed the review feedback in bb09c1f:
Validation:
|
Code ReviewSolid PR that converts run-level HIL prompts into per-stage synthetic graph nodes. The state model, replay-key design, and live-only answer ledger are well thought out; tests are thorough. Notes below, with code quality first and a few concrete bugs after. Architecture / code quality
Potential bugs
Minor / nits
Security
Test coverageStrong: continuation replay ( Gaps worth considering:
Overall: looks ready to merge once the |
Assistant-model: GPT-5.5
|
Addressed this follow-up review in 144e273:
Validation:
|
Code Review — PR #1054
|
Assistant-model: GPT-5.5
|
Addressed this review in 0ecac9e:
Validation:
|
Code Review — feat(workflows): prompt nodes as synthetic graph stagesNice, thorough piece of work. The synthetic-stage model is well-factored, the private answer ledger keeps the secret/snapshot boundary clean, and the continuation replay logic (descriptor hash + filtered author callsite) handles the hard cases — parallel duplicates, parent topology drift, ambiguous re-asks. Test coverage is excellent: +610 lines in A handful of things to consider before merge — mostly correctness edge cases and a few code-quality nits. Correctness
Performance
Code organization
Security / privacy
TestsThe new tests are tight and cover the interesting paths well. Suggested additions:
Docs / migrationThe README/docs prose around Overall: solid PR. The stack-trace issue (1) is the only one I'd block on; the rest are polish/robustness improvements that could land in a follow-up. |
Assistant-model: GPT-5.5
|
Addressed this review in c81de74:
Validation:
|
Review — feat(workflows)!: render ctx.ui.* prompts as synthetic graph stage nodesThanks for the thorough write-up and tests. Overall this is a clean refactor with strong coverage. Below are findings grouped by severity. Strengths
Issues1. Unhandled rejection in for (const handle of handles) {
void handle.dispose?.();
}
void Promise.resolve(handle.dispose?.()).catch((err) => {
console.debug("pi-workflows: stage handle dispose failed", err);
});2. Silent empty-options coercion in async select<T extends string>(message: string, options: readonly T[]): Promise<T> {
if (options.length === 0) return "" as T;The cast lies to the type system — 3. Defensive-but-misleading fallback in activeStore.getStagePromptAnswer(opts.continuation?.source.id ?? "", replayDecision.source.id)The 4. Global Captures are synchronous within the
5. Prompt answer lifetime / memory residency
For a long-running workflow that prompts for a secret early and then runs for hours, the cleartext sits in heap. Consider:
Right now the JSDoc says "must never be logged, serialized, or copied into snapshots/persistence" — good — but doesn't mention residency. 6. Mutable The new mutability contract is "consumer code treats as immutable; executor may swap the frozen array reference." External code that does Minor / style
Architecture / API
Nice work overall — the synthetic stage approach is a real UX win over the run-level overlay. |
Assistant-model: GPT-5.5
|
Addressed this review in d0a680e:
Validation:
|
Review —
|
Assistant-model: GPT-5.5
|
Addressed the blocking items from this review in e335246:
Validation:
|
Code Review — synthetic prompt graph nodesOverall: ambitious, well-structured refactor with strong test coverage. The live-only Correctness / potential bugs
Style / nits
Test coverageStrong. The new tests cover: callsite filtering (multiple platforms + file URLs), deep-stack disambiguation, parallel prompt replay, ambiguous duplicate prompts, abort while pending (no leaked answer), topology-change rejection, prompt-parent-drift acceptance, persistence round-trip with
SecurityLive-only ledger design is sound: Suggested follow-ups (non-blocking)
Nice work on the parent-drift detection ( |
Assistant-model: GPT-5.5
|
Addressed this review in 18a146c:
Validation:
Also confirmed |
Code reviewI focused on the new prompt-as-graph-node path (executor.ts, store.ts, prompt-callsite.ts, stage-chat-view.ts, prompt-card.ts) and the supporting persistence/replay pieces. Overall this is a well-shaped change — the synthetic-node model is consistent with how A few things worth a look before merging: Correctness / behavior
Readability nits
Security / privacy
Tests
Nothing here is blocking — the architecture and privacy model both look solid, and the breaking-changes are clearly called out. |
…des (#1054) * feat(workflows): render ui prompts as graph nodes Implement node-local workflow UI prompt stages with awaiting_input state, stage-local prompt cards, continuation replay safeguards, live-only answer replay, and hardened prompt callsite identity for packaged runtime paths. Add regression coverage for prompt-node lifecycle, continuation topology, prompt answer privacy, TUI routing, persistence restore, and packaged prompt callsite filtering. AI-Assisted-By: GPT-5.5 * feat(workflows): enhance awaiting input stage prompts Render stage-local text prompts through the host editor, support scrollable prompt bodies, and hide unstarted placeholder stages while prompt nodes await responses. Keep completed stage chat handles resumable until the host clears the registry, and let ctx.complete fall back to SDK sessions when no complete-adapter-specific options are used. Assistant-model: GPT-5.5 * fix(workflows): address prompt node review feedback Assistant-model: GPT-5.5 * fix(workflows): harden prompt input edge cases Assistant-model: GPT-5.5 * fix(workflows): harden prompt replay internals Assistant-model: GPT-5.5 * fix(workflows): preserve deep prompt callsites Assistant-model: GPT-5.5 * fix(workflows): tighten prompt edge handling Assistant-model: GPT-5.5 * fix(workflows): strengthen prompt replay hashing Assistant-model: GPT-5.5 * fix(workflows): document prompt replay invariants Assistant-model: GPT-5.5
Summary
Converts node-local `ctx.ui.input/confirm/select/editor` prompts from run-level overlay banners into first-class synthetic DAG stages with `awaiting_input` status. Prompt answers are submitted from the owning stage's chat panel or via `/workflow send`, and failed-run continuation replay can reuse live prompt answers without ever persisting raw response data.
Closes #1046
Key Changes
Prompt graph nodes
Live-only answer ledger
Stable continuation replay
Stage chat & prompt card
Breaking Changes
Validation
```sh
AGENT=1 bun test test/unit/prompt-callsite.test.ts test/unit/executor.test.ts --test-name-pattern "continuation"
AGENT=1 bun test test/unit/builtin-workflows.test.ts
bun run typecheck
bun run lint
bun run test:unit
```