pi-workflow-engine 0.13.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pi/extensions/pi-workflow-engine/index.ts +106 -391
- package/.pi/extensions/pi-workflow-engine/src/advisory-challenge.ts +1 -1
- package/.pi/extensions/pi-workflow-engine/src/advisory-evidence.ts +8 -8
- package/.pi/extensions/pi-workflow-engine/src/advisory-schema.ts +7 -1
- package/.pi/extensions/pi-workflow-engine/src/agent-attempt.ts +48 -62
- package/.pi/extensions/pi-workflow-engine/src/agent-replay.ts +46 -67
- package/.pi/extensions/pi-workflow-engine/src/agent-retry.ts +14 -37
- package/.pi/extensions/pi-workflow-engine/src/agent-runner-types.ts +5 -11
- package/.pi/extensions/pi-workflow-engine/src/agent-runner.ts +15 -21
- package/.pi/extensions/pi-workflow-engine/src/agent-session-identity.ts +13 -43
- package/.pi/extensions/pi-workflow-engine/src/agent-session-providers.ts +17 -5
- package/.pi/extensions/pi-workflow-engine/src/agent-session.ts +93 -100
- package/.pi/extensions/pi-workflow-engine/src/agent-skills.ts +11 -43
- package/.pi/extensions/pi-workflow-engine/src/agent-workspace.ts +4 -18
- package/.pi/extensions/pi-workflow-engine/src/background-workflows.ts +33 -86
- package/.pi/extensions/pi-workflow-engine/src/cancellation.ts +1 -5
- package/.pi/extensions/pi-workflow-engine/src/concurrency.ts +25 -80
- package/.pi/extensions/pi-workflow-engine/src/discovery.ts +16 -23
- package/.pi/extensions/pi-workflow-engine/src/dynamax-shortcuts.ts +1 -4
- package/.pi/extensions/pi-workflow-engine/src/dynamax.ts +39 -98
- package/.pi/extensions/pi-workflow-engine/src/engine.ts +37 -80
- package/.pi/extensions/pi-workflow-engine/src/finalizers.ts +2 -10
- package/.pi/extensions/pi-workflow-engine/src/git.ts +55 -0
- package/.pi/extensions/pi-workflow-engine/src/guards.ts +8 -0
- package/.pi/extensions/pi-workflow-engine/src/identity-canonicalization.ts +7 -19
- package/.pi/extensions/pi-workflow-engine/src/inline-workflow.ts +171 -106
- package/.pi/extensions/pi-workflow-engine/src/journal.ts +0 -12
- package/.pi/extensions/pi-workflow-engine/src/model-profile-command.ts +37 -8
- package/.pi/extensions/pi-workflow-engine/src/model-profiles.ts +15 -66
- package/.pi/extensions/pi-workflow-engine/src/options.ts +97 -16
- package/.pi/extensions/pi-workflow-engine/src/perf.ts +43 -72
- package/.pi/extensions/pi-workflow-engine/src/process-runner.ts +14 -4
- package/.pi/extensions/pi-workflow-engine/src/progress-types.ts +2 -0
- package/.pi/extensions/pi-workflow-engine/src/progress.ts +79 -80
- package/.pi/extensions/pi-workflow-engine/src/provider-usage-limit.ts +28 -20
- package/.pi/extensions/pi-workflow-engine/src/replay-path-identity.ts +2 -7
- package/.pi/extensions/pi-workflow-engine/src/research-contract.ts +0 -1
- package/.pi/extensions/pi-workflow-engine/src/research-evidence.ts +27 -31
- package/.pi/extensions/pi-workflow-engine/src/resume-context.ts +75 -139
- package/.pi/extensions/pi-workflow-engine/src/review/github-pr-comments.ts +14 -31
- package/.pi/extensions/pi-workflow-engine/src/review/patch-validation.ts +3 -4
- package/.pi/extensions/pi-workflow-engine/src/review/review-actions.ts +1 -1
- package/.pi/extensions/pi-workflow-engine/src/review/review-diff-lines.ts +54 -0
- package/.pi/extensions/pi-workflow-engine/src/review/review-fix-workflow.ts +7 -9
- package/.pi/extensions/pi-workflow-engine/src/review/review-format.ts +51 -117
- package/.pi/extensions/pi-workflow-engine/src/review/review-handoff.ts +1 -1
- package/.pi/extensions/pi-workflow-engine/src/review/review-issues.ts +8 -13
- package/.pi/extensions/pi-workflow-engine/src/review/review-report.ts +3 -7
- package/.pi/extensions/pi-workflow-engine/src/review/review-results-viewer.ts +158 -241
- package/.pi/extensions/pi-workflow-engine/src/review/review-session-coordinator.ts +28 -38
- package/.pi/extensions/pi-workflow-engine/src/review/review-snapshot.ts +35 -44
- package/.pi/extensions/pi-workflow-engine/src/review-diff-target.ts +13 -14
- package/.pi/extensions/pi-workflow-engine/src/text.ts +29 -0
- package/.pi/extensions/pi-workflow-engine/src/tool-capabilities.ts +2 -1
- package/.pi/extensions/pi-workflow-engine/src/tool-source-identity.ts +16 -28
- package/.pi/extensions/pi-workflow-engine/src/tree-fingerprint.ts +34 -14
- package/.pi/extensions/pi-workflow-engine/src/types.ts +6 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/kit.ts +193 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/research-result-renderer.ts +177 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/result-layout.ts +209 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-format.ts +17 -44
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-inspector.ts +703 -235
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-picker.ts +48 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-result-renderer.ts +239 -129
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-runs-browser.ts +461 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-tool-renderer.ts +91 -0
- package/.pi/extensions/pi-workflow-engine/src/ui/workflow-widget.ts +316 -98
- package/.pi/extensions/pi-workflow-engine/src/usage.ts +21 -32
- package/.pi/extensions/pi-workflow-engine/src/workflow-advisory-utils.ts +56 -19
- package/.pi/extensions/pi-workflow-engine/src/workflow-execution.ts +19 -24
- package/.pi/extensions/pi-workflow-engine/src/workflow-module.ts +17 -37
- package/.pi/extensions/pi-workflow-engine/src/workflow-result-context.ts +79 -0
- package/.pi/extensions/pi-workflow-engine/src/workflow-run-background.ts +4 -14
- package/.pi/extensions/pi-workflow-engine/src/workflow-run-controller.ts +77 -63
- package/.pi/extensions/pi-workflow-engine/src/workflow-run-history.ts +42 -29
- package/.pi/extensions/pi-workflow-engine/src/workflow-run-record.ts +15 -14
- package/.pi/extensions/pi-workflow-engine/src/workflow-run-store.ts +27 -31
- package/.pi/extensions/pi-workflow-engine/src/workflow-usage-limit-scheduler.ts +1 -5
- package/.pi/extensions/pi-workflow-engine/src/workflows.ts +3 -6
- package/.pi/extensions/pi-workflow-engine/src/worktree.ts +48 -110
- package/.pi/extensions/pi-workflow-engine/workflows/code-review.ts +64 -93
- package/.pi/extensions/pi-workflow-engine/workflows/diagnose.ts +25 -67
- package/.pi/extensions/pi-workflow-engine/workflows/perf-review.ts +19 -53
- package/.pi/extensions/pi-workflow-engine/workflows/refactor-scout.ts +21 -49
- package/.pi/extensions/pi-workflow-engine/workflows/research.ts +74 -66
- package/USAGE.md +31 -17
- package/package.json +1 -2
- package/skills/workflow-code-review-actions/SKILL.md +12 -23
- package/.pi/extensions/pi-workflow-engine/src/diff-capture.ts +0 -81
- package/.pi/extensions/pi-workflow-engine/src/review/code-review-orchestration.ts +0 -24
- package/.pi/extensions/pi-workflow-engine/src/review/review-results-flow.ts +0 -52
- package/.pi/settings.json +0 -3
package/USAGE.md
CHANGED
|
@@ -36,7 +36,7 @@ Useful flags:
|
|
|
36
36
|
/workflow code-review --concurrency=4 # cap concurrent subagents
|
|
37
37
|
/workflow code-review --max-agents=20 # cap total live agent calls in the run
|
|
38
38
|
/workflow code-review --agent-timeout-ms=600000 # abort one live agent after 10 minutes
|
|
39
|
-
/workflow code-review --agent-retries=2 #
|
|
39
|
+
/workflow code-review --agent-retries=2 # restart agents whose in-session retries are exhausted
|
|
40
40
|
/workflow code-review --budget=50000 # output-token ceiling for subagents
|
|
41
41
|
/workflow code-review --resume <run-id> # replay matching completed agent calls
|
|
42
42
|
/workflow code-review --resume <run-id> --resume-edited # reuse unchanged calls after a workflow edit
|
|
@@ -124,7 +124,7 @@ the journal's deterministic replay surface.
|
|
|
124
124
|
|
|
125
125
|
Use `dynamax` when the built-in workflows are not specific enough and you want the main pi agent to author a temporary workflow for the current question. It is the fastest path from "this needs multiple angles" to a live fan-out, verifier pass, and synthesized result.
|
|
126
126
|
|
|
127
|
-
Interactive shortcut: run `/workflow` with no arguments, choose
|
|
127
|
+
Interactive shortcut: run `/workflow` with no arguments, choose `+ author a one-off workflow` (the last row, below the registered workflows), and type a brief. Escape closes the picker without running anything. pi will send that brief back to the host agent as a `dynamax` request so it can author and run an inline workflow with the `workflow` tool's `script` argument.
|
|
128
128
|
|
|
129
129
|
That inline workflow should investigate, fan out, verify, and summarize. It is **not** where code edits happen. If you want changes made, use the workflow result as evidence and then ask pi to edit separately.
|
|
130
130
|
|
|
@@ -146,7 +146,7 @@ Sticky mode and inspector shortcut:
|
|
|
146
146
|
|
|
147
147
|
The workflow inspector and code-review results viewer are also registered as first-class shortcuts shown by `/hotkeys`. The defaults are `ctrl+shift+m` for the inspector and `ctrl+shift+r` for the latest review results. `ctrl+o` is intentionally not used because pi already uses it for tool-output expansion and tree filtering.
|
|
148
148
|
|
|
149
|
-
When only the literal `dynamax` token is used, the opt-in is one-shot: the next agent run receives the workflow permission reminder, stays visibly active for that run, then clears after the run ends. When `/workflow:dynamax on` is used, the opt-in is sticky for the current pi session until `/workflow:dynamax off`.
|
|
149
|
+
When only the literal `dynamax` token is used, the opt-in is one-shot: the next agent run receives the workflow permission reminder, stays visibly active for that run, then clears after the run ends. When `/workflow:dynamax on` is used, the opt-in is sticky for the current pi session until `/workflow:dynamax off`. The footer status states the mode compactly: `◆ dynamax` while sticky, `◆ dynamax · next prompt` while a one-shot waits for its prompt, and `◆ dynamax · this turn` while that run is active; off mode clears it. A running workflow names itself in its own status next to it.
|
|
150
150
|
|
|
151
151
|
### Prompt editor cue
|
|
152
152
|
|
|
@@ -172,7 +172,7 @@ is used so highlighting is never silently disabled. Pi editor registration is
|
|
|
172
172
|
still last-writer-wins; the previous editor is restored on shutdown only while
|
|
173
173
|
the Dynamax decorator still owns the registration.
|
|
174
174
|
|
|
175
|
-
When the host agent calls the `workflow` tool
|
|
175
|
+
When the host agent calls the `workflow` tool, the inspector stays closed so the agent's reply remains in view; the compact workflow widget shows the moving status above the editor. Press the inspector shortcut or run `/workflow:inspector` for the richer view of phases, agents, findings, and logs, live or after the run.
|
|
176
176
|
|
|
177
177
|
Configure either shortcut by creating `~/.pi/agent/extensions/pi-workflow-engine.json`:
|
|
178
178
|
|
|
@@ -241,9 +241,11 @@ Workflow results are rendered in pi with:
|
|
|
241
241
|
|
|
242
242
|
These workflow usage totals are separate from `--perf`, which is internal timing only. They are also separate from pi's built-in footer and `/session` totals, which may still show host-session usage only unless pi core adds a first-class extension usage API. If a model has no pricing configured, token totals can be non-zero while displayed cost remains `$0.000`.
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
Results, the inspector overview, the runs browser and the live widget header show usage in the compact form `↑34k ↓1.2k · $0.02` (input including cache, output, and cost when known); the footer status line carries no usage. The result text handed to the host agent keeps the full breakdown: providers with a complete breakdown show `fresh`, `cache read`, `cache write`, and `output` separately. Zero cache components are omitted. If a provider reports only some components, the summary labels mixed-run component totals with `≥` and preserves the provider's aggregate `total`; if it reports no components, the summary falls back to aggregate `tokens`. Costs are summed from provider session totals and are never inferred from local pricing.
|
|
245
245
|
|
|
246
|
-
During a run,
|
|
246
|
+
During a run, a widget above the editor shows the workflow's progress bar, finished/total agents, elapsed time and usage; phases in chronological order, with finished phases collapsed to one line and the active phase listing its running, failed and done agents; the declared phases not reached yet; the workflow's counters; and the inspector shortcut. The footer status line reads `◆ review · Find 6/10 · 12s`. Use `--inspect` if you want a larger live view while the workflow is active, then `/workflow:inspector` if you want to bring the last completed inspector back up afterward.
|
|
247
|
+
|
|
248
|
+
The inspector has Overview, Agents, Findings, and Logs sections, plus Result for a retained run opened from `/workflow:runs`. Switch sections with `tab`/`shift+tab`, `←`/`→`, or `1`–`5`; move with `↑`/`↓` or `j`/`k`, jump with `g`/`G`, expand an agent or finding with `enter`, and close with `q` or `esc`. Expanded agents show the full error, last tool, model, and token usage.
|
|
247
249
|
|
|
248
250
|
### Durable run records
|
|
249
251
|
|
|
@@ -257,7 +259,7 @@ Persistence is intentionally bounded and private by default. Raw workflow args,
|
|
|
257
259
|
|
|
258
260
|
The host-facing `workflow` tool accepts `background: true`. It returns as soon as the run ID and origin metadata are durably recorded, while the normal workflow engine continues in-process with the same concurrency, budget, worktree, progress, usage, and resume rules. Synchronous execution remains the default, and the `/workflow` slash command remains synchronous.
|
|
259
261
|
|
|
260
|
-
Background runs are detached from the initiating tool-call signal, so the host agent can finish that turn and continue the conversation. When the run completes or fails, the extension waits for the originating session to become idle and inserts one concise `workflow-result` message containing the run ID, terminal state, and summary. Delivery state is stored with the run record; on reload, the extension checks both that state and the session message history before retrying, which suppresses duplicates even if persistence failed immediately after message insertion.
|
|
262
|
+
Background runs are detached from the initiating tool-call signal, so the host agent can finish that turn and continue the conversation. While one runs, it shows a single line above the editor (`◆ background · code-review 56b57550 · Find 6/10 · 12s`) instead of the full live widget. When the run completes or fails, the extension waits for the originating session to become idle and inserts one concise `workflow-result` message containing the run ID, terminal state, and summary. Delivery state is stored with the run record; on reload, the extension checks both that state and the session message history before retrying, which suppresses duplicates even if persistence failed immediately after message insertion.
|
|
261
263
|
|
|
262
264
|
Provider usage-window continuation is a separate, explicit background option:
|
|
263
265
|
|
|
@@ -281,7 +283,7 @@ A graceful pi session shutdown aborts active background work and records it as `
|
|
|
281
283
|
|
|
282
284
|
### Recent runs and lifecycle actions
|
|
283
285
|
|
|
284
|
-
`/workflow:runs` opens
|
|
286
|
+
`/workflow:runs` opens a runs browser in the TUI: one aligned row per recent project run (state glyph and word, workflow, duration, age, cost when known, short run ID) above a details pane for the selected run with its wall-clock times, phases, agent and token counts, resume lineage, pause details, outcome, and why a relaunch is unavailable when it is. Keys act on the selected run: `enter` or `i` inspect, `r` resume, `s` stop (press twice), `R` restart; only the actions currently valid for that run are listed in the footer, and the others explain why they are unavailable. The browser refreshes while a run is active and reopens on the same run after an action. RPC sessions keep pi's native two-step selection (run, then action). The background activity line is present only while this session owns active background work.
|
|
285
287
|
|
|
286
288
|
The same operations are available without the selection UI:
|
|
287
289
|
|
|
@@ -293,9 +295,9 @@ The same operations are available without the selection UI:
|
|
|
293
295
|
/workflow:inspector <run-id>
|
|
294
296
|
```
|
|
295
297
|
|
|
296
|
-
Inspect is always safe. Stop is available for a background run active in the current session and for a retained paused run with a pending resume timer. Resume is limited to paused registered workflows whose source fingerprint is unchanged and whose invocation had no redacted arguments; it starts a new background run ID with `resumeFromRunId` journal replay. Restart is limited to completed, failed, or stopped registered workflows that had no arguments and also creates a new background run ID. Inline workflows and argument-bearing invocations are intentionally not relaunched because their executable input was not persisted. In `print` and `json` modes, list and inspect return formatted text without opening TUI components, while resume/restart report that background execution requires TUI or RPC mode.
|
|
298
|
+
Inspect is always safe. Stop is available for a background run active in the current session and for a retained paused run with a pending resume timer. Resume is limited to paused registered workflows whose source fingerprint is unchanged and whose invocation had no redacted arguments; it starts a new background run ID with `resumeFromRunId` journal replay. A paused run already resumed by a queued, running, paused, or completed run is listed as `resumed as <run-id>` and offers no second resume; once every resume of it has failed or been stopped, manual resume is offered again, while automatic provider-limit resume never fires twice for the same paused run. Restart is limited to completed, failed, or stopped registered workflows that had no arguments and also creates a new background run ID. Inline workflows and argument-bearing invocations are intentionally not relaunched because their executable input was not persisted. In `print` and `json` modes, list and inspect return formatted text without opening TUI components, while resume/restart report that background execution requires TUI or RPC mode.
|
|
297
299
|
|
|
298
|
-
Code-review findings are rendered as a formatted result message by default. pi no longer asks whether to open the findings viewer. Use `--result-viewer` or `--review-viewer` when you want to inspect findings interactively
|
|
300
|
+
Code-review findings are rendered as a formatted result message by default. pi no longer asks whether to open the findings viewer. Use `--result-viewer` or `--review-viewer` when you want to inspect findings interactively. The viewer lists findings most severe first with the selected finding's full detail beside the list (below it in narrow terminals); `space` or `enter` selects a finding, `a` toggles all, `f` generates patch previews and `c` posts PR comments for the selection, and `pgup`/`pgdn` scroll a long detail. The viewer is sized to its content and shows scroll hints only when something is clipped. `/workflow:results` or `ctrl+shift+r` reopens the most recent validated code-review report in the current pi session without rerunning the workflow; selections reset when it reopens.
|
|
299
301
|
|
|
300
302
|
The Fix action revalidates the exact reviewed PR/ref/index/working-tree snapshot, then runs each selected finding through its own worktree-isolated agent and returns the finding ID, validation summary, patch, and changed status. Failed attempts do not discard successful previews, no patch is applied to your active tree automatically, and a moved or unverifiable review target is rejected rather than patched against the wrong code. The original review and all Fix previews retained in that pi session share one output-token budget. Reopening the viewer does not reset it, finalized preview usage is always deducted, and only one preview can run at a time.
|
|
301
303
|
|
|
@@ -465,12 +467,12 @@ Guaranteed built-ins are statically registered:
|
|
|
465
467
|
|
|
466
468
|
1. Add `.pi/extensions/pi-workflow-engine/workflows/<name>.ts`.
|
|
467
469
|
2. Import it in `.pi/extensions/pi-workflow-engine/src/workflows.ts`.
|
|
468
|
-
3. Add
|
|
470
|
+
3. Add a `defineBuiltinWorkflow(mod, "<name>.ts")` entry to `BUILTIN_WORKFLOW_DEFINITIONS`.
|
|
469
471
|
|
|
470
472
|
Drop-in workflows are also discovered best-effort from:
|
|
471
473
|
|
|
472
|
-
-
|
|
473
|
-
-
|
|
474
|
+
- `~/.pi/agent/workflows/*.ts`: the user-level drop-in directory, which survives `pi update`.
|
|
475
|
+
- The extension's own `workflows/*.ts` directory: `.pi/extensions/pi-workflow-engine/workflows/` in a working copy or a project-vendored copy. Files added to an installed package are replaced by `pi update`.
|
|
474
476
|
|
|
475
477
|
Use `/workflow <name> --refresh` after adding a drop-in file.
|
|
476
478
|
|
|
@@ -517,7 +519,7 @@ Only tune these when a workflow is too slow, too expensive, or too noisy:
|
|
|
517
519
|
| `--parallel-limit=N` / `PI_WORKFLOW_PARALLEL_SUBMISSION_LIMIT=N` | Limit eager `parallel()` submission. |
|
|
518
520
|
| `--max-agents=N` / `PI_WORKFLOW_MAX_AGENTS=N` | Cap live model calls across the complete run, including sub-workflows. Default `64`; values are clamped to `1`–`10000`. Replay hits do not consume the cap. The `workflow` tool field is `maxAgents`. |
|
|
519
521
|
| `--agent-timeout-ms=N` / `PI_WORKFLOW_AGENT_TIMEOUT_MS=N` | Abort one live agent after this duration. Default `1800000` (30 minutes); values are clamped to `1000`–`86400000`. The session is aborted and its isolated worktree is cleaned up. The `workflow` tool field is `agentTimeoutMs`. |
|
|
520
|
-
| `--agent-retries=N` / `PI_WORKFLOW_AGENT_RETRIES=N` |
|
|
522
|
+
| `--agent-retries=N` / `PI_WORKFLOW_AGENT_RETRIES=N` | Restart the whole agent after a transient provider or transport failure that pi's in-session turn retry could not recover. Default `0`; values are clamped to `0`–`10`. Backoff starts at one second, doubles, and caps at 30 seconds. The `workflow` tool field is `agentRetries`. |
|
|
521
523
|
| `--budget=N` / `PI_WORKFLOW_BUDGET=N` | Set an output-token ceiling across recorded subagent attempts, including failed provider attempts. `agent()` throws `WorkflowBudgetExceededError` before starting another model request once the ceiling is reached; agents already running may overshoot because the engine does not reserve per-agent estimates. |
|
|
522
524
|
| `--perf` / `PI_WORKFLOW_PERF=1` | Include internal timing aggregates. Usage/cost totals are reported separately from perf. |
|
|
523
525
|
| `PI_WORKFLOW_LANE_ITEM_LIMIT=N` | Cap retained progress lane items. |
|
|
@@ -525,17 +527,29 @@ Only tune these when a workflow is too slow, too expensive, or too noisy:
|
|
|
525
527
|
These controls bound different dimensions: concurrency limits how many agents
|
|
526
528
|
are active together, `max-agents` limits how many live model calls the run may
|
|
527
529
|
start in total, `agent-timeout-ms` bounds one active call (including retry
|
|
528
|
-
backoff), and `budget` limits recorded output tokens. Every
|
|
530
|
+
backoff), and `budget` limits recorded output tokens. Every agent restart consumes
|
|
529
531
|
another live-agent admission and remains inside the original timeout, budget,
|
|
530
532
|
and abort scope. Usage from failed attempts is retained, so it can exhaust the
|
|
531
533
|
budget before the next retry begins. Host cancellation takes precedence over
|
|
532
534
|
limit and timeout failures.
|
|
533
535
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
+
Transient provider failures are retried in two layers. First, each subagent
|
|
537
|
+
inherits pi's session-level automatic retry from your pi `retry` settings
|
|
538
|
+
(enabled by default: 3 retries with 2s, 4s, 8s backoff). It retries the failed
|
|
539
|
+
turn in place, keeping the agent's earlier tool work; each attempt is logged in
|
|
540
|
+
the workflow progress log, and usage from failed attempts is still recorded.
|
|
541
|
+
Like the agent's other turns, these in-place retries are not budget-checked, and
|
|
542
|
+
a retryable rate-limit or usage-limit error is retried in-session before a
|
|
543
|
+
background run's usage-limit pause takes effect. Only when those retries are
|
|
544
|
+
exhausted does `--agent-retries` restart the agent from scratch. Invalid
|
|
536
545
|
models, schema-contract failures, exhausted budgets, agent limits, worktree
|
|
537
546
|
failures, timeouts, and host aborts are never provider-retried.
|
|
538
547
|
|
|
548
|
+
pi-workflow-engine 0.12.0 and 0.13.0 wrote `"retry": {"enabled": false}` into
|
|
549
|
+
`~/.pi/agent/settings.json` whenever a workflow ran, which disables automatic
|
|
550
|
+
retry for the host session and every subagent. Workflow runs log a warning while
|
|
551
|
+
that setting is in effect; remove it unless you disabled retry on purpose.
|
|
552
|
+
|
|
539
553
|
## Common fixes
|
|
540
554
|
|
|
541
555
|
- **Unknown workflow**: confirm the extension is loaded with `pi list`; use `--refresh` for new drop-ins.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-workflow-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Zero-dependency Dynamax workflows for pi: live parallel subagents, typed handoffs, synthesized results.",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
".pi/extensions/pi-workflow-engine",
|
|
25
|
-
".pi/settings.json",
|
|
26
25
|
"assets/preview.png",
|
|
27
26
|
"skills",
|
|
28
27
|
"README.md",
|
|
@@ -1,38 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: workflow-code-review-actions
|
|
3
|
-
description: "Act on selected code-review findings from pi-workflow-engine:
|
|
3
|
+
description: "Act on selected code-review findings from pi-workflow-engine: post GitHub PR inline comments using gh, GitHub MCP/tools, or project-specific tools."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Use this skill when the parent agent receives selected code-review finding JSON from `pi-workflow-engine`.
|
|
6
|
+
Use this skill when the parent agent receives selected code-review finding JSON from `pi-workflow-engine`. The engine hands comments to the parent agent only when its own `gh` posting could not resolve the PR or failed for some findings.
|
|
7
|
+
|
|
8
|
+
Fixes are never handed off: the results viewer generates isolated, independently validated patch previews for selected findings. Do not edit files in response to a code-review handoff.
|
|
7
9
|
|
|
8
10
|
## Inputs
|
|
9
11
|
|
|
10
|
-
The prompt will include compact JSON with:
|
|
12
|
+
The prompt will include the verified reviewed PR head SHA, the reason the engine could not post the comments itself, and compact JSON with:
|
|
11
13
|
|
|
12
|
-
- `context`: workflow name, target,
|
|
14
|
+
- `context`: workflow name, target, `diffTarget` (with the PR `number`), display `diffCommand`, changed files, optional summary, and optional snapshot identity.
|
|
13
15
|
- `issues`: selected findings with `id`, `summary`, `category`, `severity`, `confidence`, `location`, `impact`, `evidence`, and `recommendation`.
|
|
14
16
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
When mode is `fix selected code-review findings`:
|
|
18
|
-
|
|
19
|
-
1. Inspect the selected issue JSON before editing.
|
|
20
|
-
2. Make minimal edits that address only the selected findings.
|
|
21
|
-
3. Preserve unrelated user changes and avoid broad refactors.
|
|
22
|
-
4. Run focused validation if available for the touched files or behavior.
|
|
23
|
-
5. Summarize changed files and validation results.
|
|
24
|
-
6. Do not post GitHub PR comments in fix mode.
|
|
25
|
-
|
|
26
|
-
## Comment mode
|
|
27
|
-
|
|
28
|
-
When mode is `post inline GitHub PR comments`:
|
|
17
|
+
## Posting comments
|
|
29
18
|
|
|
30
|
-
1.
|
|
31
|
-
2.
|
|
19
|
+
1. Prefer installed GitHub MCP/tools if visible in the active tool list.
|
|
20
|
+
2. Before posting, resolve the current PR head and require it to equal the verified reviewed head from the prompt; stop if it differs.
|
|
32
21
|
3. If no GitHub MCP/tools are available, use `gh`:
|
|
33
|
-
- Resolve the PR with `gh pr view --json
|
|
34
|
-
-
|
|
35
|
-
- Post each inline comment with `gh api repos/{owner}/{repo}/pulls/{number}/comments` and include `commit_id
|
|
22
|
+
- Resolve the PR with `gh pr view <context.diffTarget.number> --json headRefOid,url`.
|
|
23
|
+
- Take owner/repo from the PR `url`, which names the base repository, so fork PRs are commented upstream. Do not use `headRepositoryOwner`/`headRepository`; on a fork PR they name the fork. Fall back to `gh repo view --json nameWithOwner` only if the URL is missing.
|
|
24
|
+
- Post each inline comment with `gh api repos/{owner}/{repo}/pulls/{number}/comments` and include `commit_id` (the verified head), `path`, `line`, and `side=RIGHT`.
|
|
36
25
|
4. Keep each comment concise: summary, severity/confidence/category, impact, evidence, and recommendation.
|
|
37
26
|
5. Report posted, skipped, and failed counts.
|
|
38
27
|
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { PerfSink } from "./perf.ts";
|
|
2
|
-
import { runBoundedProcess, type BoundedProcessFailure } from "./process-runner.ts";
|
|
3
|
-
import { parseAllowedDiffCommand, reviewDiffCommand, type ReviewDiffTarget } from "./review-diff-target.ts";
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
formatReviewDiffTarget,
|
|
7
|
-
GitReviewDiffTargetSchema,
|
|
8
|
-
isReviewDiffTarget,
|
|
9
|
-
parseAllowedDiffCommand,
|
|
10
|
-
PullRequestReviewDiffTargetSchema,
|
|
11
|
-
reviewDiffCommand,
|
|
12
|
-
ReviewDiffTargetSchema,
|
|
13
|
-
reviewGitDiffBaseline,
|
|
14
|
-
type GitDiffBaselineTarget,
|
|
15
|
-
type GitReviewDiffTarget,
|
|
16
|
-
type PullRequestReviewDiffTarget,
|
|
17
|
-
type ReviewDiffTarget,
|
|
18
|
-
} from "./review-diff-target.ts";
|
|
19
|
-
|
|
20
|
-
interface DiffCaptureResultBase {
|
|
21
|
-
readonly stdout: string;
|
|
22
|
-
readonly durationMs: number;
|
|
23
|
-
readonly bytes: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type DiffCaptureResult =
|
|
27
|
-
| (DiffCaptureResultBase & { readonly ok: true; readonly error?: undefined; readonly failure?: undefined })
|
|
28
|
-
| (DiffCaptureResultBase & { readonly ok: false; readonly error: string; readonly failure: DiffCaptureFailure });
|
|
29
|
-
|
|
30
|
-
export type DiffCaptureFailure = BoundedProcessFailure | { readonly kind: "invalid-target"; readonly message: string };
|
|
31
|
-
|
|
32
|
-
export interface DiffCaptureOptions {
|
|
33
|
-
readonly cwd: string;
|
|
34
|
-
readonly signal?: AbortSignal;
|
|
35
|
-
readonly timeoutMs: number;
|
|
36
|
-
readonly maxBufferBytes: number;
|
|
37
|
-
readonly perf?: PerfSink;
|
|
38
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
39
|
-
readonly killGraceMs?: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function captureDiff(command: string, options: DiffCaptureOptions): Promise<DiffCaptureResult> {
|
|
43
|
-
const parsed = parseAllowedDiffCommand(command);
|
|
44
|
-
if ("error" in parsed) {
|
|
45
|
-
return {
|
|
46
|
-
ok: false,
|
|
47
|
-
stdout: "",
|
|
48
|
-
durationMs: 0,
|
|
49
|
-
bytes: 0,
|
|
50
|
-
error: parsed.error,
|
|
51
|
-
failure: { kind: "invalid-target", message: parsed.error },
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return await captureDiffTarget(parsed, options);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function captureDiffTarget(target: ReviewDiffTarget, options: DiffCaptureOptions): Promise<DiffCaptureResult> {
|
|
59
|
-
const command = reviewDiffCommand(target);
|
|
60
|
-
const result = await runBoundedProcess({
|
|
61
|
-
file: command.file,
|
|
62
|
-
args: command.args,
|
|
63
|
-
cwd: options.cwd,
|
|
64
|
-
env: diffCaptureEnv(options.env),
|
|
65
|
-
signal: options.signal,
|
|
66
|
-
timeoutMs: options.timeoutMs,
|
|
67
|
-
maxBufferBytes: options.maxBufferBytes,
|
|
68
|
-
killGraceMs: options.killGraceMs,
|
|
69
|
-
abortError: "diff capture aborted",
|
|
70
|
-
timeoutError: `diff capture timed out after ${options.timeoutMs}ms`,
|
|
71
|
-
maxBufferError: `diff capture exceeded ${options.maxBufferBytes} bytes`,
|
|
72
|
-
exitError: (stderr, code, signal) => stderr.trim() || `diff command exited with code ${code ?? `signal ${signal ?? "unknown"}`}`,
|
|
73
|
-
});
|
|
74
|
-
options.perf?.observe("diff.capture_ms", result.durationMs);
|
|
75
|
-
options.perf?.observe("diff.bytes", result.bytes);
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function diffCaptureEnv(env: NodeJS.ProcessEnv | undefined): NodeJS.ProcessEnv {
|
|
80
|
-
return { ...(env ?? process.env), GIT_EXTERNAL_DIFF: "", GIT_DIFF_OPTS: "" };
|
|
81
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const DIFF_EMBED_CAP = 60_000;
|
|
2
|
-
|
|
3
|
-
export function buildCodeReviewScopeBlock(input: {
|
|
4
|
-
readonly diffCommand: string;
|
|
5
|
-
readonly files: readonly string[];
|
|
6
|
-
readonly summary: string;
|
|
7
|
-
readonly conventions?: string;
|
|
8
|
-
readonly diffText: string;
|
|
9
|
-
readonly target: string;
|
|
10
|
-
}): string {
|
|
11
|
-
const diffBlock = input.diffText
|
|
12
|
-
? `\n## Diff (review is bounded to these changed lines)\n\`\`\`diff\n${
|
|
13
|
-
input.diffText.length > DIFF_EMBED_CAP
|
|
14
|
-
? `${input.diffText.slice(0, DIFF_EMBED_CAP)}\n... (truncated — run \`${input.diffCommand}\` for the full diff)`
|
|
15
|
-
: input.diffText
|
|
16
|
-
}\n\`\`\`\n`
|
|
17
|
-
: "";
|
|
18
|
-
return (
|
|
19
|
-
`## Diff command\n${input.diffCommand}\n\n## Changed files\n${input.files.map((file) => `- ${file}`).join("\n")}\n\n` +
|
|
20
|
-
`## Summary\n${input.summary}\n\n## Conventions\n${input.conventions ?? "(none noted)"}\n` +
|
|
21
|
-
diffBlock +
|
|
22
|
-
(input.target ? `\n## User instructions (verbatim)\n${input.target}\n` : "")
|
|
23
|
-
);
|
|
24
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { WorkflowRunOptions } from "../types.ts";
|
|
3
|
-
import { toReviewIssues, type ReviewIssue, type ReviewIssueSelection } from "./review-issues.ts";
|
|
4
|
-
import { isReviewReport, type ReviewReport } from "./review-report.ts";
|
|
5
|
-
import { ReviewResultsViewer } from "./review-results-viewer.ts";
|
|
6
|
-
import { WORKFLOW_VIEWER_OVERLAY_OPTIONS } from "../ui/workflow-viewer-layout.ts";
|
|
7
|
-
|
|
8
|
-
export type ReviewResultsPresentationDecision =
|
|
9
|
-
| {
|
|
10
|
-
readonly kind: "send";
|
|
11
|
-
readonly reason: "not-code-review" | "not-advisory" | "no-findings" | "disabled" | "not-tui" | "not-requested";
|
|
12
|
-
}
|
|
13
|
-
| { readonly kind: "open"; readonly issues: readonly ReviewIssue[] };
|
|
14
|
-
|
|
15
|
-
export interface ReviewResultsDecisionInput {
|
|
16
|
-
readonly workflowName: string;
|
|
17
|
-
readonly result: unknown;
|
|
18
|
-
readonly mode?: string;
|
|
19
|
-
readonly hasUI: boolean;
|
|
20
|
-
readonly resultViewer?: WorkflowRunOptions["resultViewer"];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function codeReviewReport(workflowName: string, result: unknown): ReviewReport | undefined {
|
|
24
|
-
return workflowName === "code-review" && isReviewReport(result) ? result : undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ReviewResultsViewerContext {
|
|
28
|
-
readonly ui: Pick<ExtensionContext["ui"], "custom">;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function decideReviewResultsPresentation(input: ReviewResultsDecisionInput): ReviewResultsPresentationDecision {
|
|
32
|
-
if (input.workflowName !== "code-review") return { kind: "send", reason: "not-code-review" };
|
|
33
|
-
const report = codeReviewReport(input.workflowName, input.result);
|
|
34
|
-
if (!report) return { kind: "send", reason: "not-advisory" };
|
|
35
|
-
if (report.findings.length === 0) return { kind: "send", reason: "no-findings" };
|
|
36
|
-
if (input.resultViewer === "skip") return { kind: "send", reason: "disabled" };
|
|
37
|
-
if (input.mode !== "tui" || !input.hasUI) return { kind: "send", reason: "not-tui" };
|
|
38
|
-
|
|
39
|
-
if (input.resultViewer !== "open") return { kind: "send", reason: "not-requested" };
|
|
40
|
-
|
|
41
|
-
return { kind: "open", issues: toReviewIssues(input.workflowName, report) };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function showReviewResultsViewer(
|
|
45
|
-
ctx: ReviewResultsViewerContext,
|
|
46
|
-
issues: readonly ReviewIssue[],
|
|
47
|
-
): Promise<ReviewIssueSelection> {
|
|
48
|
-
return await ctx.ui.custom<ReviewIssueSelection>(
|
|
49
|
-
(tui, theme, _keybindings, done) => new ReviewResultsViewer(issues, "code-review", tui, theme, done),
|
|
50
|
-
WORKFLOW_VIEWER_OVERLAY_OPTIONS,
|
|
51
|
-
);
|
|
52
|
-
}
|
package/.pi/settings.json
DELETED