pi-baton 0.8.0 → 0.8.5

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/CHANGELOG.md CHANGED
@@ -1,178 +1,202 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- This project follows semantic versioning.
6
-
7
- ## [Unreleased]
8
-
9
- ## [0.8.0] - 2026-09-14
10
-
11
- ### Added
12
-
13
- - `/baton:history` lists recent completed or failed Baton runs from persisted `.pi/baton/runs/` manifests, with bounded scan/output limits, skip diagnostics for unreadable manifests, and tests for empty, single, multi-run, exclusion, scan-cap ordering, and command registration cases.
14
- - `/baton:status` and `formatStatusSummary` now include the stored `failure` reason for terminal failed runs, with status tests covering iteration-cap exhaustion and other failure paths.
15
-
16
- ### Changed
17
-
18
- - README quick start and `docs/workflows.md` now document when to use `/baton:history` versus `/baton:status`, including the terminal-run fallback behavior for status.
19
- - README quick start and `docs/workflows.md` now document that `/baton:status` falls back to the most recent finished run when no active run exists.
20
- - Refreshed ROADMAP.md: marked S-109 done, updated release direction for 0.8.0/0.9.0, and added maintenance seed candidates S-110 through S-113 for the weekly seed planner.
21
- - Updated ROADMAP.md to mark S-108 done and refresh the security status table after the two-stage review gauntlet shipped in 0.7.5.
22
- - Aligned ROADMAP S-109 status with the shipped `docs/workflows.md` authoring guide.
23
-
24
- ## [0.7.5] - 2026-08-22
25
-
26
- ### Changed
27
-
28
- - Merge the 2026-08-22 managed OSS dependency and maintenance PR batch.
29
-
30
- ### Added
31
-
32
- - Added the builtin `Two-Stage Review Gauntlet` workflow to demonstrate a non-default two-stage review graph.
33
-
34
- ### Changed
35
-
36
- - Bump package version to `0.7.3` for the next patch release.
37
- - Bumped Pi dev toolchain packages to clear the transitive `protobufjs` audit advisory; the remaining `brace-expansion` finding is documented as upstream-blocked by `@earendil-works/pi-coding-agent`'s published shrinkwrap.
38
- - Removed unused `clearActiveRunPointer` export from `lib/run-store.ts` (dead code with no callers; `loadActiveRun` / `loadMostRecentTerminalRun` already treat a missing `runId` as no active pointer).
39
-
40
- ## [0.7.2] - 2026-07-04
41
-
42
- ### Added
43
-
44
- - `/baton:status` now shows the most recent finished run summary (state, last step, iteration, run directory) after a run reaches `completed` or `failed`, with clear finished-run framing instead of the no-active-run message.
45
-
46
- - Buy Me a Coffee sponsor button in README and native GitHub funding link via `.github/FUNDING.yml`.
47
-
48
- ### Changed
49
-
50
- - Merged Dependabot PR #14: bump `@earendil-works/pi-ai` devDependency from 0.78.1 to 0.80.2 (type-check clean, 57/57 tests passing).
51
- - Removed leftover template scaffolding (`prompts/`, `themes/`, `skills/`).
52
- - Deleted stale template bootstrap docs (`docs/examples.md`, `docs/github-template.md`, `docs/repository-settings.md`, `docs/typescript.md`, `docs/template-checklist.md`) that shipped to npm consumers describing non-existent commands.
53
- - Updated ROADMAP.md to reflect current version (0.7.2), test count (57), and seed completion status for S-101, S-102, S-103, S-105.
54
-
55
- ## [0.7.1] - 2026-06-27
56
-
57
- ### Changed
58
-
59
- - README aligned to the current Pi extension template: added `Features`, `Release`, `Security`, and `Links` sections; expanded install flows (`npm`, GitHub, project-local, and `pi -e`); and updated `Package contents` to match the published tarball.
60
-
61
- ## [0.7.0] - 2026-06-25
62
-
63
- ### Added
64
-
65
- - Command handler tests for `/baton:new`, `/baton:start`, `/baton:run`, and `/baton:status` covering scaffold creation, inline validation, active-run guard, and no-active-run messaging.
66
- - Handoff payload shape tests for implement, linear, and fix transitions.
67
- - Run-store tests for active-run visibility across idle, running, and terminal states.
68
-
69
- ### Changed
70
-
71
- - Finalizes the shipped builtin `default-review-loop` workflow (`worker` / `reviewer` / `worker`) with full v1 command-surface test coverage.
72
-
73
- ## [0.6.0] - 2026-06-25
74
-
75
- ### Added
76
-
77
- - Structured step envelopes for every run step (`summary`, `rawOutputPath`, and review fields when applicable).
78
- - Step handoff payload carries `taskBrief`, prior `stepOutputSummary`, `rawOutputPath`, and run metadata between isolated steps.
79
- - Review contract enforcement: `reject` requires non-empty `findings`; `accept` requires `acceptanceNote`.
80
- - Builtin `default-review-loop` routes `fix` back to `review`; iteration cap stops infinite reject loops.
81
- - Step-level `model` override with placeholder and session-model fallback via `resolveStepModel`.
82
-
83
- ### Changed
84
-
85
- - Expanded `run-engine` and `review-contract` tests for fix→review routing, model routing, envelope persistence, and contract violations.
86
-
87
- ## [0.5.0] - 2026-06-23
88
-
89
- ### Added
90
-
91
- - `/baton:run` continuous run engine executes the active idle run through isolated subagent steps to a terminal state.
92
- - Step records persist under `.pi/baton/runs/<run>/steps/` and raw outputs under `outputs/`.
93
- - Terminal run summaries report the failing step as `last step` when step execution fails.
94
-
95
- ### Changed
96
-
97
- - Expanded `run-engine` tests for step/output persistence, state transitions, and failure `last step` reporting.
98
-
99
- ## [0.4.0] - 2026-06-22
100
-
101
- ### Added
102
-
103
- - `/baton:start` creates an idle run from workflow selection and a task brief without starting execution.
104
- - `/baton:status` reports workflow name, task brief, last/current step, run state, iteration count, and run directory.
105
- - Single active run guard blocks a second `/baton:start` and points users to `/baton:status` or `/baton:run`.
106
- - Run manifests persist under `.pi/baton/runs/` with an active-run pointer.
107
- - Expanded workflow schema validation tests covering required fields, linear `next` transitions, review `on_accept` / `on_reject` branches, and invalid YAML handling at discovery time.
108
-
109
- ### Changed
110
-
111
- - Workflow selection display names continue to come from YAML `name`; invalid or incomplete workflow documents now fail with explicit validation errors during `/baton:start` and `/baton:run` discovery.
112
-
113
- ## [0.3.0] - 2026-06-18
114
-
115
- ### Added
116
-
117
- - `/baton:new` re-prompts for a workflow name when the derived filename collides with an existing scaffold.
118
- - Tests for lazy `.pi/baton/workflows/` creation and kebab-case filename derivation.
119
-
120
- ### Changed
121
-
122
- - Workflow discovery keeps user-defined `.pi/baton/workflows/*.yaml` entries ahead of builtin package workflows in selection order.
123
-
124
- ## [0.2.3] - 2026-06-13
125
-
126
- ### Added
127
-
128
- - README header icon and packaged `assets/pi-baton-icon-512.png` branding asset.
129
-
130
- ### Changed
131
-
132
- - `assets/` is now included in the published package.
133
-
134
- ## [0.2.2] - 2026-06-13
135
-
136
- ### Added
137
-
138
- - Live Baton run widget above the editor during `/baton:run`, showing workflow, brief, active step, agent, judgment, and step checklist.
139
- - Footer status line (`baton: implement`, `baton: review`, etc.) while a run is in progress.
140
-
141
- ## [0.2.1] - 2026-06-13
142
-
143
- ### Fixed
144
-
145
- - Ship builtin `worker` and `reviewer` subagent definitions so `default-review-loop` runs without pre-created `.pi/agents/` files.
146
- - Validate required workflow agents during `/baton:start` and `/baton:run` with clearer missing-agent errors.
147
-
148
- ## [0.2.0] - 2026-06-13
149
-
150
- ### Added
151
-
152
- - `/baton:new`, `/baton:start`, `/baton:run`, and `/baton:status` command surface.
153
- - Builtin `default-review-loop` workflow with `worker` / `reviewer` / `worker` agent mapping.
154
- - YAML workflow discovery, inline validation, scaffold generation, and run persistence under `.pi/baton/`.
155
- - Isolated subagent step execution with structured handoff, review contract enforcement, and per-step model routing.
156
-
157
- ## [0.1.2] - 2026-06-04
158
-
159
- ### Changed
160
-
161
- - README and `docs/template-checklist.md` now follow the Pi OSS minimal-docs policy: `docs/` is optional, with explicit post-generation cleanup for template bootstrap docs.
162
- - Template bootstrap docs (`github-template.md`, `repository-settings.md`, `typescript.md`) are labeled for delete-or-merge after setup.
163
-
164
- ## [0.1.1] - 2026-06-01
165
-
166
- ### Changed
167
-
168
- - Publish workflow now supports npm publishing on merged package version bumps in addition to tags, releases, and manual dispatch.
169
- - Publish workflow now installs a current npm CLI so npm Trusted Publishing OIDC is supported.
170
- - CI and publish workflow commands no longer include literal trailing `\\n` text.
171
-
172
- ## [0.1.0] - YYYY-MM-DD
173
-
174
- ### Added
175
-
176
- - Initial Pi package template.
177
- - Example extension, Agent Skill, prompt, and theme.
178
- - CI and npm Trusted Publishing workflow.
1
+ # Changelog
2
+
3
+ ## 0.8.5 - 2026-09-27
4
+
5
+ - chore: periodic patch bump after 7+ days without npm publish
6
+
7
+ ## 0.8.4 - 2026-09-27
8
+
9
+ - chore: periodic patch bump after 7+ days without npm publish
10
+
11
+ ## 0.8.3 - 2026-09-27
12
+
13
+ - chore: periodic patch bump after 7+ days without npm publish
14
+
15
+ ## 0.8.2 - 2026-09-27
16
+
17
+ - chore: periodic patch bump after 7+ days without npm publish
18
+
19
+ ## 0.8.1 - 2026-09-27
20
+
21
+ - chore: periodic patch bump after 7+ days without npm publish
22
+
23
+ All notable changes to this project will be documented in this file.
24
+
25
+ This project follows semantic versioning.
26
+
27
+ ## [Unreleased]
28
+
29
+ ### Added
30
+
31
+ - Regression tests for exhausted `iteration_cap` pre-check behavior in `runContinuous`, malformed unreadable active-run manifests in `loadActiveRun`/`loadMostRecentTerminalRun`, recovery via `createIdleRun`, and `/baton:status` terminal-fallback messaging for iteration-cap failures.
32
+
33
+ ## [0.8.0] - 2026-09-14
34
+
35
+ ### Added
36
+
37
+ - `/baton:history` lists recent completed or failed Baton runs from persisted `.pi/baton/runs/` manifests, with bounded scan/output limits, skip diagnostics for unreadable manifests, and tests for empty, single, multi-run, exclusion, scan-cap ordering, and command registration cases.
38
+ - `/baton:status` and `formatStatusSummary` now include the stored `failure` reason for terminal failed runs, with status tests covering iteration-cap exhaustion and other failure paths.
39
+
40
+ ### Changed
41
+
42
+ - README quick start and `docs/workflows.md` now document when to use `/baton:history` versus `/baton:status`, including the terminal-run fallback behavior for status.
43
+ - README quick start and `docs/workflows.md` now document that `/baton:status` falls back to the most recent finished run when no active run exists.
44
+ - Refreshed ROADMAP.md: marked S-109 done, updated release direction for 0.8.0/0.9.0, and added maintenance seed candidates S-110 through S-113 for the weekly seed planner.
45
+ - Updated ROADMAP.md to mark S-108 done and refresh the security status table after the two-stage review gauntlet shipped in 0.7.5.
46
+ - Aligned ROADMAP S-109 status with the shipped `docs/workflows.md` authoring guide.
47
+
48
+ ## [0.7.5] - 2026-08-22
49
+
50
+ ### Changed
51
+
52
+ - Merge the 2026-08-22 managed OSS dependency and maintenance PR batch.
53
+
54
+ ### Added
55
+
56
+ - Added the builtin `Two-Stage Review Gauntlet` workflow to demonstrate a non-default two-stage review graph.
57
+
58
+ ### Changed
59
+
60
+ - Bump package version to `0.7.3` for the next patch release.
61
+ - Bumped Pi dev toolchain packages to clear the transitive `protobufjs` audit advisory; the remaining `brace-expansion` finding is documented as upstream-blocked by `@earendil-works/pi-coding-agent`'s published shrinkwrap.
62
+ - Removed unused `clearActiveRunPointer` export from `lib/run-store.ts` (dead code with no callers; `loadActiveRun` / `loadMostRecentTerminalRun` already treat a missing `runId` as no active pointer).
63
+
64
+ ## [0.7.2] - 2026-07-04
65
+
66
+ ### Added
67
+
68
+ - `/baton:status` now shows the most recent finished run summary (state, last step, iteration, run directory) after a run reaches `completed` or `failed`, with clear finished-run framing instead of the no-active-run message.
69
+
70
+ - Buy Me a Coffee sponsor button in README and native GitHub funding link via `.github/FUNDING.yml`.
71
+
72
+ ### Changed
73
+
74
+ - Merged Dependabot PR #14: bump `@earendil-works/pi-ai` devDependency from 0.78.1 to 0.80.2 (type-check clean, 57/57 tests passing).
75
+ - Removed leftover template scaffolding (`prompts/`, `themes/`, `skills/`).
76
+ - Deleted stale template bootstrap docs (`docs/examples.md`, `docs/github-template.md`, `docs/repository-settings.md`, `docs/typescript.md`, `docs/template-checklist.md`) that shipped to npm consumers describing non-existent commands.
77
+ - Updated ROADMAP.md to reflect current version (0.7.2), test count (57), and seed completion status for S-101, S-102, S-103, S-105.
78
+
79
+ ## [0.7.1] - 2026-06-27
80
+
81
+ ### Changed
82
+
83
+ - README aligned to the current Pi extension template: added `Features`, `Release`, `Security`, and `Links` sections; expanded install flows (`npm`, GitHub, project-local, and `pi -e`); and updated `Package contents` to match the published tarball.
84
+
85
+ ## [0.7.0] - 2026-06-25
86
+
87
+ ### Added
88
+
89
+ - Command handler tests for `/baton:new`, `/baton:start`, `/baton:run`, and `/baton:status` covering scaffold creation, inline validation, active-run guard, and no-active-run messaging.
90
+ - Handoff payload shape tests for implement, linear, and fix transitions.
91
+ - Run-store tests for active-run visibility across idle, running, and terminal states.
92
+
93
+ ### Changed
94
+
95
+ - Finalizes the shipped builtin `default-review-loop` workflow (`worker` / `reviewer` / `worker`) with full v1 command-surface test coverage.
96
+
97
+ ## [0.6.0] - 2026-06-25
98
+
99
+ ### Added
100
+
101
+ - Structured step envelopes for every run step (`summary`, `rawOutputPath`, and review fields when applicable).
102
+ - Step handoff payload carries `taskBrief`, prior `stepOutputSummary`, `rawOutputPath`, and run metadata between isolated steps.
103
+ - Review contract enforcement: `reject` requires non-empty `findings`; `accept` requires `acceptanceNote`.
104
+ - Builtin `default-review-loop` routes `fix` back to `review`; iteration cap stops infinite reject loops.
105
+ - Step-level `model` override with placeholder and session-model fallback via `resolveStepModel`.
106
+
107
+ ### Changed
108
+
109
+ - Expanded `run-engine` and `review-contract` tests for fix→review routing, model routing, envelope persistence, and contract violations.
110
+
111
+ ## [0.5.0] - 2026-06-23
112
+
113
+ ### Added
114
+
115
+ - `/baton:run` continuous run engine executes the active idle run through isolated subagent steps to a terminal state.
116
+ - Step records persist under `.pi/baton/runs/<run>/steps/` and raw outputs under `outputs/`.
117
+ - Terminal run summaries report the failing step as `last step` when step execution fails.
118
+
119
+ ### Changed
120
+
121
+ - Expanded `run-engine` tests for step/output persistence, state transitions, and failure `last step` reporting.
122
+
123
+ ## [0.4.0] - 2026-06-22
124
+
125
+ ### Added
126
+
127
+ - `/baton:start` creates an idle run from workflow selection and a task brief without starting execution.
128
+ - `/baton:status` reports workflow name, task brief, last/current step, run state, iteration count, and run directory.
129
+ - Single active run guard blocks a second `/baton:start` and points users to `/baton:status` or `/baton:run`.
130
+ - Run manifests persist under `.pi/baton/runs/` with an active-run pointer.
131
+ - Expanded workflow schema validation tests covering required fields, linear `next` transitions, review `on_accept` / `on_reject` branches, and invalid YAML handling at discovery time.
132
+
133
+ ### Changed
134
+
135
+ - Workflow selection display names continue to come from YAML `name`; invalid or incomplete workflow documents now fail with explicit validation errors during `/baton:start` and `/baton:run` discovery.
136
+
137
+ ## [0.3.0] - 2026-06-18
138
+
139
+ ### Added
140
+
141
+ - `/baton:new` re-prompts for a workflow name when the derived filename collides with an existing scaffold.
142
+ - Tests for lazy `.pi/baton/workflows/` creation and kebab-case filename derivation.
143
+
144
+ ### Changed
145
+
146
+ - Workflow discovery keeps user-defined `.pi/baton/workflows/*.yaml` entries ahead of builtin package workflows in selection order.
147
+
148
+ ## [0.2.3] - 2026-06-13
149
+
150
+ ### Added
151
+
152
+ - README header icon and packaged `assets/pi-baton-icon-512.png` branding asset.
153
+
154
+ ### Changed
155
+
156
+ - `assets/` is now included in the published package.
157
+
158
+ ## [0.2.2] - 2026-06-13
159
+
160
+ ### Added
161
+
162
+ - Live Baton run widget above the editor during `/baton:run`, showing workflow, brief, active step, agent, judgment, and step checklist.
163
+ - Footer status line (`baton: implement`, `baton: review`, etc.) while a run is in progress.
164
+
165
+ ## [0.2.1] - 2026-06-13
166
+
167
+ ### Fixed
168
+
169
+ - Ship builtin `worker` and `reviewer` subagent definitions so `default-review-loop` runs without pre-created `.pi/agents/` files.
170
+ - Validate required workflow agents during `/baton:start` and `/baton:run` with clearer missing-agent errors.
171
+
172
+ ## [0.2.0] - 2026-06-13
173
+
174
+ ### Added
175
+
176
+ - `/baton:new`, `/baton:start`, `/baton:run`, and `/baton:status` command surface.
177
+ - Builtin `default-review-loop` workflow with `worker` / `reviewer` / `worker` agent mapping.
178
+ - YAML workflow discovery, inline validation, scaffold generation, and run persistence under `.pi/baton/`.
179
+ - Isolated subagent step execution with structured handoff, review contract enforcement, and per-step model routing.
180
+
181
+ ## [0.1.2] - 2026-06-04
182
+
183
+ ### Changed
184
+
185
+ - README and `docs/template-checklist.md` now follow the Pi OSS minimal-docs policy: `docs/` is optional, with explicit post-generation cleanup for template bootstrap docs.
186
+ - Template bootstrap docs (`github-template.md`, `repository-settings.md`, `typescript.md`) are labeled for delete-or-merge after setup.
187
+
188
+ ## [0.1.1] - 2026-06-01
189
+
190
+ ### Changed
191
+
192
+ - Publish workflow now supports npm publishing on merged package version bumps in addition to tags, releases, and manual dispatch.
193
+ - Publish workflow now installs a current npm CLI so npm Trusted Publishing OIDC is supported.
194
+ - CI and publish workflow commands no longer include literal trailing `\\n` text.
195
+
196
+ ## [0.1.0] - YYYY-MM-DD
197
+
198
+ ### Added
199
+
200
+ - Initial Pi package template.
201
+ - Example extension, Agent Skill, prompt, and theme.
202
+ - CI and npm Trusted Publishing workflow.
package/README.md CHANGED
@@ -1,184 +1,184 @@
1
- # Pi Baton
2
-
3
- [![Join dotfield.xyz on Discord](https://img.shields.io/badge/Join%20dotfield.xyz%20on%20Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/4945dXZVW5)
4
-
5
- <p align="center">
6
- <img src="./assets/pi-baton-icon-512.png" alt="Pi Baton icon" width="192" height="192" />
7
- </p>
8
-
9
- [![CI](https://github.com/eiei114/pi-baton/actions/workflows/ci.yml/badge.svg)](https://github.com/eiei114/pi-baton/actions/workflows/ci.yml)
10
- [![Publish](https://github.com/eiei114/pi-baton/actions/workflows/publish.yml/badge.svg)](https://github.com/eiei114/pi-baton/actions/workflows/publish.yml)
11
- [![npm version](https://img.shields.io/npm/v/pi-baton.svg)](https://www.npmjs.com/package/pi-baton)
12
- [![npm downloads](https://img.shields.io/npm/dm/pi-baton.svg)](https://www.npmjs.com/package/pi-baton)
13
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
- [![Pi package](https://img.shields.io/badge/pi-package-purple.svg)](https://pi.dev/packages)
15
- [![Trusted Publishing](https://img.shields.io/badge/npm-Trusted%20Publishing-blue.svg)](docs/release.md)
16
- <a href="https://buymeacoffee.com/ekawano114m"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" height="60"></a>
17
-
18
- > Run YAML-defined review loops in Pi with per-step model switching and isolated step context.
19
-
20
- ## What this is
21
-
22
- Pi Baton is a Pi-native workflow baton runner. Define `implement → review → fix` loops in YAML, and let Pi Baton execute them with automatic baton handoff between isolated subagent steps.
23
-
24
- ## Features
25
-
26
- - **Per-step model switching** — fast model for implement, strong model for review
27
- - **Isolated step context** — no shared conversation pollution between steps
28
- - **Structured review contract** — `accept`/`reject` with mandatory findings or acceptance notes
29
- - **Live progress widget** — see which step is running, its agent, and judgment in real time
30
-
31
- ## Install
32
-
33
- Install the published npm package with Pi:
34
-
35
- ```bash
36
- pi install npm:pi-baton
37
- ```
38
-
39
- Pin a specific version when you want reproducible installs:
40
-
41
- ```bash
42
- pi install npm:pi-baton@0.8.0
43
- ```
44
-
45
- Install into the current project instead of your user Pi settings:
46
-
47
- ```bash
48
- pi install npm:pi-baton -l
49
- ```
50
-
51
- Or install from GitHub:
52
-
53
- ```bash
54
- pi install git:github.com/eiei114/pi-baton
55
- ```
56
-
57
- Try it without permanently installing:
58
-
59
- ```bash
60
- pi -e npm:pi-baton
61
- ```
62
-
63
- ## Quick start
64
-
65
- Try this package locally from a clone of this repository:
66
-
67
- ```bash
68
- pi -e .
69
- ```
70
-
71
- Then run:
72
-
73
- ```txt
74
- /baton:new create a workflow scaffold
75
- /baton:start choose workflow + task brief → idle run
76
- /baton:run execute run to terminal state (with live widget)
77
- /baton:status show the active run summary, or the most recent finished run
78
- /baton:history list recent completed or failed runs from persisted history
79
- ```
80
-
81
- Use `/baton:status` for the active run or the single most recent finished run. Use `/baton:history` when you need a short list of recent completed or failed runs and their `.pi/baton/runs/<id>` directories.
82
-
83
- Builtin workflows work out of the box — no agent setup required:
84
-
85
- - `Default Review Loop` (`implement → review → fix`)
86
- - `Two-Stage Review Gauntlet` (`draft → technical_review → editorial_review`, with rejects routed through `fix`)
87
-
88
- ## Prerequisites
89
-
90
- Pi Baton ships builtin `worker` and `reviewer` subagents under `agents/`. They work with your current Pi model.
91
-
92
- To override with custom agents, place `.md` files under:
93
-
94
- ```
95
- .pi/agents/worker.md
96
- .pi/agents/reviewer.md
97
- ```
98
-
99
- Discovery order: project `.pi/agents/` → user `~/.pi/agent/agents/` → pi-baton builtin.
100
-
101
- ## Workflow authoring
102
-
103
- See [`docs/workflows.md`](docs/workflows.md) for an end-to-end walkthrough: step kinds, transitions, the review contract, `iteration_cap`, model overrides, and agent discovery order.
104
-
105
- ```txt
106
- /baton:new
107
- ```
108
-
109
- Pick a name and a scaffold from `default-review-loop` is written to `.pi/baton/workflows/` and opened in editor. The scaffold includes `<your-fast-model>` / `<your-strong-model>` placeholders for step-level model overrides.
110
-
111
- The shipped `workflows/` directory also includes `two-stage-review-gauntlet.yaml`, a second builtin graph that demonstrates chaining two review gates before completion.
112
-
113
- ### Workflow YAML reference
114
-
115
- ```yaml
116
- name: My Review Loop
117
- iteration_cap: 5
118
- steps:
119
- implement:
120
- agent: worker
121
- model: openai/gpt-5.4 # optional: fast model
122
- prompt: work prompt
123
- next: review
124
- review:
125
- agent: reviewer
126
- model: anthropic/claude-opus-4-5 # optional: strong model
127
- prompt: review prompt
128
- on_accept: _complete # or a step name
129
- on_reject: fix
130
- fix:
131
- agent: worker
132
- model: openai/gpt-5.4
133
- prompt: fix prompt
134
- next: review
135
- ```
136
-
137
- - `on_accept: _complete` ends the run.
138
- - `iteration_cap` prevents infinite review loops — the run fails at the cap.
139
- - Review agents must return `accept`/`reject` with findings or acceptance notes.
140
-
141
- ## Package contents
142
-
143
- | Path | Purpose |
144
- |---|---|
145
- | `extensions/` | Slash-command entrypoints (`/baton:new`, `/baton:start`, `/baton:run`, `/baton:status`, `/baton:history`) |
146
- | `lib/` | Workflow parser, run engine, subagent runner, review contract, UI widget |
147
- | `agents/` | Builtin `worker` and `reviewer` subagent definitions |
148
- | `workflows/` | Builtin workflows (`default-review-loop.yaml`, `two-stage-review-gauntlet.yaml`) |
149
- | `assets/` | README / package branding assets |
150
- | `docs/` | Workflow authoring guide, release and maintainer documentation |
151
-
152
- ## Development
153
-
154
- ```bash
155
- npm install
156
- npm run ci
157
- ```
158
-
159
- ## Release
160
-
161
- This package uses npm Trusted Publishing with GitHub Actions OIDC — no `NPM_TOKEN` is required.
162
-
163
- ```bash
164
- npm version patch
165
- git push
166
- ```
167
-
168
- On `main`, version bumps trigger auto-release and publish workflows. See [`docs/release.md`](docs/release.md) for setup details.
169
-
170
- ## Security
171
-
172
- Pi packages can execute code with your local permissions. Review extensions before installing third-party packages.
173
-
174
- For vulnerability reporting, see [`SECURITY.md`](SECURITY.md).
175
-
176
- ## Links
177
-
178
- - npm: https://www.npmjs.com/package/pi-baton
179
- - GitHub: https://github.com/eiei114/pi-baton
180
- - Issues: https://github.com/eiei114/pi-baton/issues
181
-
182
- ## License
183
-
184
- MIT
1
+ # Pi Baton
2
+
3
+ [![Join dotfield.xyz on Discord](https://img.shields.io/badge/Join%20dotfield.xyz%20on%20Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/4945dXZVW5)
4
+
5
+ <p align="center">
6
+ <img src="./assets/pi-baton-icon-512.png" alt="Pi Baton icon" width="192" height="192" />
7
+ </p>
8
+
9
+ [![CI](https://github.com/eiei114/pi-baton/actions/workflows/ci.yml/badge.svg)](https://github.com/eiei114/pi-baton/actions/workflows/ci.yml)
10
+ [![Publish](https://github.com/eiei114/pi-baton/actions/workflows/publish.yml/badge.svg)](https://github.com/eiei114/pi-baton/actions/workflows/publish.yml)
11
+ [![npm version](https://img.shields.io/npm/v/pi-baton.svg)](https://www.npmjs.com/package/pi-baton)
12
+ [![npm downloads](https://img.shields.io/npm/dm/pi-baton.svg)](https://www.npmjs.com/package/pi-baton)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
+ [![Pi package](https://img.shields.io/badge/pi-package-purple.svg)](https://pi.dev/packages)
15
+ [![Trusted Publishing](https://img.shields.io/badge/npm-Trusted%20Publishing-blue.svg)](docs/release.md)
16
+ <a href="https://buymeacoffee.com/ekawano114m"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" height="60"></a>
17
+
18
+ > Run YAML-defined review loops in Pi with per-step model switching and isolated step context.
19
+
20
+ ## What this is
21
+
22
+ Pi Baton is a Pi-native workflow baton runner. Define `implement → review → fix` loops in YAML, and let Pi Baton execute them with automatic baton handoff between isolated subagent steps.
23
+
24
+ ## Features
25
+
26
+ - **Per-step model switching** — fast model for implement, strong model for review
27
+ - **Isolated step context** — no shared conversation pollution between steps
28
+ - **Structured review contract** — `accept`/`reject` with mandatory findings or acceptance notes
29
+ - **Live progress widget** — see which step is running, its agent, and judgment in real time
30
+
31
+ ## Install
32
+
33
+ Install the published npm package with Pi:
34
+
35
+ ```bash
36
+ pi install npm:pi-baton
37
+ ```
38
+
39
+ Pin a specific version when you want reproducible installs:
40
+
41
+ ```bash
42
+ pi install npm:pi-baton@0.8.5
43
+ ```
44
+
45
+ Install into the current project instead of your user Pi settings:
46
+
47
+ ```bash
48
+ pi install npm:pi-baton -l
49
+ ```
50
+
51
+ Or install from GitHub:
52
+
53
+ ```bash
54
+ pi install git:github.com/eiei114/pi-baton
55
+ ```
56
+
57
+ Try it without permanently installing:
58
+
59
+ ```bash
60
+ pi -e npm:pi-baton
61
+ ```
62
+
63
+ ## Quick start
64
+
65
+ Try this package locally from a clone of this repository:
66
+
67
+ ```bash
68
+ pi -e .
69
+ ```
70
+
71
+ Then run:
72
+
73
+ ```txt
74
+ /baton:new create a workflow scaffold
75
+ /baton:start choose workflow + task brief → idle run
76
+ /baton:run execute run to terminal state (with live widget)
77
+ /baton:status show the active run summary, or the most recent finished run
78
+ /baton:history list recent completed or failed runs from persisted history
79
+ ```
80
+
81
+ Use `/baton:status` for the active run or the single most recent finished run. Use `/baton:history` when you need a short list of recent completed or failed runs and their `.pi/baton/runs/<id>` directories.
82
+
83
+ Builtin workflows work out of the box — no agent setup required:
84
+
85
+ - `Default Review Loop` (`implement → review → fix`)
86
+ - `Two-Stage Review Gauntlet` (`draft → technical_review → editorial_review`, with rejects routed through `fix`)
87
+
88
+ ## Prerequisites
89
+
90
+ Pi Baton ships builtin `worker` and `reviewer` subagents under `agents/`. They work with your current Pi model.
91
+
92
+ To override with custom agents, place `.md` files under:
93
+
94
+ ```
95
+ .pi/agents/worker.md
96
+ .pi/agents/reviewer.md
97
+ ```
98
+
99
+ Discovery order: project `.pi/agents/` → user `~/.pi/agent/agents/` → pi-baton builtin.
100
+
101
+ ## Workflow authoring
102
+
103
+ See [`docs/workflows.md`](docs/workflows.md) for an end-to-end walkthrough: step kinds, transitions, the review contract, `iteration_cap`, model overrides, and agent discovery order.
104
+
105
+ ```txt
106
+ /baton:new
107
+ ```
108
+
109
+ Pick a name and a scaffold from `default-review-loop` is written to `.pi/baton/workflows/` and opened in editor. The scaffold includes `<your-fast-model>` / `<your-strong-model>` placeholders for step-level model overrides.
110
+
111
+ The shipped `workflows/` directory also includes `two-stage-review-gauntlet.yaml`, a second builtin graph that demonstrates chaining two review gates before completion.
112
+
113
+ ### Workflow YAML reference
114
+
115
+ ```yaml
116
+ name: My Review Loop
117
+ iteration_cap: 5
118
+ steps:
119
+ implement:
120
+ agent: worker
121
+ model: openai/gpt-5.4 # optional: fast model
122
+ prompt: work prompt
123
+ next: review
124
+ review:
125
+ agent: reviewer
126
+ model: anthropic/claude-opus-4-5 # optional: strong model
127
+ prompt: review prompt
128
+ on_accept: _complete # or a step name
129
+ on_reject: fix
130
+ fix:
131
+ agent: worker
132
+ model: openai/gpt-5.4
133
+ prompt: fix prompt
134
+ next: review
135
+ ```
136
+
137
+ - `on_accept: _complete` ends the run.
138
+ - `iteration_cap` prevents infinite review loops — the run fails at the cap.
139
+ - Review agents must return `accept`/`reject` with findings or acceptance notes.
140
+
141
+ ## Package contents
142
+
143
+ | Path | Purpose |
144
+ |---|---|
145
+ | `extensions/` | Slash-command entrypoints (`/baton:new`, `/baton:start`, `/baton:run`, `/baton:status`, `/baton:history`) |
146
+ | `lib/` | Workflow parser, run engine, subagent runner, review contract, UI widget |
147
+ | `agents/` | Builtin `worker` and `reviewer` subagent definitions |
148
+ | `workflows/` | Builtin workflows (`default-review-loop.yaml`, `two-stage-review-gauntlet.yaml`) |
149
+ | `assets/` | README / package branding assets |
150
+ | `docs/` | Workflow authoring guide, release and maintainer documentation |
151
+
152
+ ## Development
153
+
154
+ ```bash
155
+ npm install
156
+ npm run ci
157
+ ```
158
+
159
+ ## Release
160
+
161
+ This package uses npm Trusted Publishing with GitHub Actions OIDC — no `NPM_TOKEN` is required.
162
+
163
+ ```bash
164
+ npm version patch
165
+ git push
166
+ ```
167
+
168
+ On `main`, version bumps trigger auto-release and publish workflows. See [`docs/release.md`](docs/release.md) for setup details.
169
+
170
+ ## Security
171
+
172
+ Pi packages can execute code with your local permissions. Review extensions before installing third-party packages.
173
+
174
+ For vulnerability reporting, see [`SECURITY.md`](SECURITY.md).
175
+
176
+ ## Links
177
+
178
+ - npm: https://www.npmjs.com/package/pi-baton
179
+ - GitHub: https://github.com/eiei114/pi-baton
180
+ - Issues: https://github.com/eiei114/pi-baton/issues
181
+
182
+ ## License
183
+
184
+ MIT
package/lib/run-store.ts CHANGED
@@ -134,22 +134,33 @@ export async function loadTerminalRunHistory(
134
134
  .sort(compareRunIdsNewestFirst)
135
135
  .slice(0, TERMINAL_HISTORY_MAX_SCAN);
136
136
 
137
+ const scanResults = await Promise.all(
138
+ runIds.map(async (runId) => {
139
+ try {
140
+ const manifest = await readJson<unknown>(getRunManifestPath(cwd, runId));
141
+ if (!isCompleteManifest(manifest)) {
142
+ return { kind: "skipped" as const };
143
+ }
144
+ if (!isTerminalRunState(manifest.state)) {
145
+ return { kind: "non-terminal" as const };
146
+ }
147
+ return { kind: "terminal" as const, manifest };
148
+ } catch {
149
+ return { kind: "skipped" as const };
150
+ }
151
+ }),
152
+ );
153
+
137
154
  const terminalRuns: RunManifest[] = [];
138
155
  let skippedCount = 0;
139
156
 
140
- for (const runId of runIds) {
141
- try {
142
- const manifest = await readJson<unknown>(getRunManifestPath(cwd, runId));
143
- if (!isCompleteManifest(manifest)) {
144
- skippedCount++;
145
- continue;
146
- }
147
- if (!isTerminalRunState(manifest.state)) {
148
- continue;
149
- }
150
- terminalRuns.push(manifest);
151
- } catch {
157
+ for (const result of scanResults) {
158
+ if (result.kind === "skipped") {
152
159
  skippedCount++;
160
+ continue;
161
+ }
162
+ if (result.kind === "terminal") {
163
+ terminalRuns.push(result.manifest);
153
164
  }
154
165
  }
155
166
 
@@ -15,42 +15,82 @@ async function listYamlFiles(dir: string): Promise<string[]> {
15
15
  }
16
16
  }
17
17
 
18
+ async function loadWorkflowItems(
19
+ filePaths: string[],
20
+ source: "user" | "builtin",
21
+ ): Promise<WorkflowListItem[]> {
22
+ return Promise.all(
23
+ filePaths.map(async (filePath) => {
24
+ const yamlText = await readFile(filePath, "utf8");
25
+ const id = basename(filePath, ".yaml");
26
+ const workflow = parseWorkflowDocument(yamlText, { id, source, path: filePath });
27
+ return { id, name: workflow.name, source, path: filePath };
28
+ }),
29
+ );
30
+ }
31
+
18
32
  export async function discoverWorkflowItems(cwd: string): Promise<WorkflowListItem[]> {
19
- const userFiles = await listYamlFiles(getWorkflowsDir(cwd));
20
- const builtinFiles = await listYamlFiles(getPackageWorkflowsDir());
21
-
22
- const userItems: WorkflowListItem[] = [];
23
- for (const filePath of userFiles) {
24
- const yamlText = await readFile(filePath, "utf8");
25
- const id = basename(filePath, ".yaml");
26
- const workflow = parseWorkflowDocument(yamlText, { id, source: "user", path: filePath });
27
- userItems.push({ id, name: workflow.name, source: "user", path: filePath });
28
- }
33
+ const [userFiles, builtinFiles] = await Promise.all([
34
+ listYamlFiles(getWorkflowsDir(cwd)),
35
+ listYamlFiles(getPackageWorkflowsDir()),
36
+ ]);
29
37
 
30
- const builtinItems: WorkflowListItem[] = [];
31
- for (const filePath of builtinFiles) {
32
- const yamlText = await readFile(filePath, "utf8");
33
- const id = basename(filePath, ".yaml");
34
- const workflow = parseWorkflowDocument(yamlText, { id, source: "builtin", path: filePath });
35
- builtinItems.push({ id, name: workflow.name, source: "builtin", path: filePath });
36
- }
38
+ const [userItems, builtinItems] = await Promise.all([
39
+ loadWorkflowItems(userFiles, "user"),
40
+ loadWorkflowItems(builtinFiles, "builtin"),
41
+ ]);
37
42
 
38
43
  return [...userItems, ...builtinItems];
39
44
  }
40
45
 
46
+ function isMissingFileError(error: unknown): boolean {
47
+ return (
48
+ typeof error === "object" &&
49
+ error !== null &&
50
+ "code" in error &&
51
+ (error as NodeJS.ErrnoException).code === "ENOENT"
52
+ );
53
+ }
54
+
55
+ const UNSAFE_WORKFLOW_ID_PATTERN = /[\\/\0]/;
56
+
57
+ function isSafeWorkflowId(workflowId: string): boolean {
58
+ return (
59
+ workflowId.length > 0 &&
60
+ workflowId !== "." &&
61
+ workflowId !== ".." &&
62
+ !UNSAFE_WORKFLOW_ID_PATTERN.test(workflowId)
63
+ );
64
+ }
65
+
41
66
  export async function loadWorkflowById(cwd: string, workflowId: string): Promise<WorkflowDefinition> {
42
- const items = await discoverWorkflowItems(cwd);
43
- const match = items.find((item) => item.id === workflowId);
44
- if (!match) {
67
+ // The direct lookup builds a path from the id, so ids that could escape the
68
+ // workflow directories are rejected before any read is attempted.
69
+ if (!isSafeWorkflowId(workflowId)) {
45
70
  throw new Error(`Unknown workflow: ${workflowId}`);
46
71
  }
47
72
 
48
- const yamlText = await readFile(match.path, "utf8");
49
- return parseWorkflowDocument(yamlText, {
50
- id: match.id,
51
- source: match.source,
52
- path: match.path,
53
- });
73
+ const userPath = join(getWorkflowsDir(cwd), `${workflowId}.yaml`);
74
+ try {
75
+ const yamlText = await readFile(userPath, "utf8");
76
+ return parseWorkflowDocument(yamlText, { id: workflowId, source: "user", path: userPath });
77
+ } catch (error) {
78
+ if (!isMissingFileError(error)) {
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ const builtinPath = join(getPackageWorkflowsDir(), `${workflowId}.yaml`);
84
+ try {
85
+ const yamlText = await readFile(builtinPath, "utf8");
86
+ return parseWorkflowDocument(yamlText, { id: workflowId, source: "builtin", path: builtinPath });
87
+ } catch (error) {
88
+ if (!isMissingFileError(error)) {
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ throw new Error(`Unknown workflow: ${workflowId}`);
54
94
  }
55
95
 
56
96
  export async function loadWorkflowFromPath(
package/package.json CHANGED
@@ -1,67 +1,67 @@
1
- {
2
- "name": "pi-baton",
3
- "version": "0.8.0",
4
- "description": "Pi-native workflow baton runner with per-step model switching and isolated step context.",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=22.6.0"
8
- },
9
- "license": "MIT",
10
- "author": "eiei114",
11
- "keywords": [
12
- "pi-package",
13
- "pi",
14
- "pi-extension",
15
- "workflow",
16
- "review-loop",
17
- "typescript"
18
- ],
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/eiei114/pi-baton.git"
22
- },
23
- "bugs": {
24
- "url": "https://github.com/eiei114/pi-baton/issues"
25
- },
26
- "homepage": "https://github.com/eiei114/pi-baton#readme",
27
- "files": [
28
- "assets/",
29
- "extensions/",
30
- "lib/",
31
- "agents/",
32
- "workflows/",
33
- "docs/",
34
- "README.md",
35
- "LICENSE",
36
- "CHANGELOG.md"
37
- ],
38
- "scripts": {
39
- "typecheck": "tsc --noEmit",
40
- "test": "node --test tests/*.test.mjs",
41
- "ci": "npm run typecheck && npm test && npm run pack:check",
42
- "pack:check": "npm pack --dry-run"
43
- },
44
- "pi": {
45
- "extensions": [
46
- "./extensions"
47
- ]
48
- },
49
- "publishConfig": {
50
- "access": "public"
51
- },
52
- "dependencies": {
53
- "yaml": "^2.9.0"
54
- },
55
- "peerDependencies": {
56
- "@earendil-works/pi-ai": "*",
57
- "@earendil-works/pi-coding-agent": "*",
58
- "typebox": "*"
59
- },
60
- "devDependencies": {
61
- "@earendil-works/pi-ai": "^0.84.1",
62
- "@earendil-works/pi-coding-agent": "^0.84.1",
63
- "typebox": "latest",
64
- "@types/node": "^26.0.1",
65
- "typescript": "^7.0.2"
66
- }
67
- }
1
+ {
2
+ "name": "pi-baton",
3
+ "version": "0.8.5",
4
+ "description": "Pi-native workflow baton runner with per-step model switching and isolated step context.",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=22.6.0"
8
+ },
9
+ "license": "MIT",
10
+ "author": "eiei114",
11
+ "keywords": [
12
+ "pi-package",
13
+ "pi",
14
+ "pi-extension",
15
+ "workflow",
16
+ "review-loop",
17
+ "typescript"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/eiei114/pi-baton.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/eiei114/pi-baton/issues"
25
+ },
26
+ "homepage": "https://github.com/eiei114/pi-baton#readme",
27
+ "files": [
28
+ "assets/",
29
+ "extensions/",
30
+ "lib/",
31
+ "agents/",
32
+ "workflows/",
33
+ "docs/",
34
+ "README.md",
35
+ "LICENSE",
36
+ "CHANGELOG.md"
37
+ ],
38
+ "scripts": {
39
+ "typecheck": "tsc --noEmit",
40
+ "test": "node --test tests/*.test.mjs",
41
+ "ci": "npm run typecheck && npm test && npm run pack:check",
42
+ "pack:check": "npm pack --dry-run"
43
+ },
44
+ "pi": {
45
+ "extensions": [
46
+ "./extensions"
47
+ ]
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "dependencies": {
53
+ "yaml": "^2.9.0"
54
+ },
55
+ "peerDependencies": {
56
+ "@earendil-works/pi-ai": "*",
57
+ "@earendil-works/pi-coding-agent": "*",
58
+ "typebox": "*"
59
+ },
60
+ "devDependencies": {
61
+ "@earendil-works/pi-ai": "^0.84.1",
62
+ "@earendil-works/pi-coding-agent": "^0.84.1",
63
+ "typebox": "latest",
64
+ "@types/node": "^26.0.1",
65
+ "typescript": "^7.0.2"
66
+ }
67
+ }