@tianhai/pi-workflow-kit 1.4.0 → 1.5.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/README.md +21 -8
- package/agents/pwk-hazard-reviewer.md +8 -2
- package/agents/pwk-recon-scout.md +11 -10
- package/agents/pwk-smell-reviewer.md +13 -3
- package/agents/pwk-spec-reviewer.md +6 -2
- package/agents/pwk-tracing-reviewer.md +6 -2
- package/docs/developer-usage-guide.md +14 -8
- package/docs/oversight-model.md +4 -4
- package/docs/provider-delegation-contract.md +112 -0
- package/docs/workflow-phases.md +2 -2
- package/extensions/workflow-guard.ts +244 -1
- package/package.json +2 -1
- package/skills/pwk-brainstorming/SKILL.md +1 -1
- package/skills/pwk-executing-tasks/SKILL.md +5 -20
- package/skills/pwk-writing-plans/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
AI coding agents tend to skip design and jump straight into implementation, producing over-engineered or misaligned code. **pi-workflow-kit** solves this by hard-blocking write operations during brainstorm and planning phases — the agent *literally cannot modify your source files* until you approve the design.
|
|
6
6
|
|
|
7
|
-
[pi](https://github.com/badlogic/pi-mono) package.
|
|
7
|
+
[pi](https://github.com/badlogic/pi-mono) package. Skills are portable; the workflow guard and `/pwk-setup` command are Pi integrations.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -12,7 +12,13 @@ AI coding agents tend to skip design and jump straight into implementation, prod
|
|
|
12
12
|
pi install npm:@tianhai/pi-workflow-kit
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
For Pi delegation providers that discover project agents, install the canonical PWK roles before starting a gated workflow:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
/pwk-setup
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This creates the five role definitions under `.agents/agents/`. It does not install or configure a provider. Existing customized files are preserved; use `/pwk-setup --force` only when you explicitly want to replace differing role files. Run setup before `/skill:pwk-brainstorming`; the command is refused during brainstorm and plan phases.
|
|
16
22
|
|
|
17
23
|
**Want to try before committing?**
|
|
18
24
|
|
|
@@ -20,13 +26,19 @@ No setup needed — skills and guards activate automatically after install.
|
|
|
20
26
|
pi -e npm:@tianhai/pi-workflow-kit
|
|
21
27
|
```
|
|
22
28
|
|
|
23
|
-
**Optional —
|
|
29
|
+
**Optional — delegated recon and review.** The skills request logical capabilities rather than a specific agent tool. If the host has no safe compatible provider, they perform recon and review inline. In Pi, [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents) is one compatible provider:
|
|
24
30
|
|
|
25
31
|
```bash
|
|
26
|
-
pi install npm
|
|
32
|
+
pi install npm:@tintinweb/pi-subagents
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
After `/pwk-setup`, Tintinweb can discover the five named roles from `.agents/agents/`; recon can also use its built-in read-only `Explore` agent. No running subagents need to be pre-created. Other Pi extensions require the documented capabilities or a separate adapter; arbitrary extensions are not automatically compatible.
|
|
36
|
+
|
|
37
|
+
### Using the roles on other hosts
|
|
38
|
+
|
|
39
|
+
The five role files define portable logical roles, not a required provider API. Claude Code can map them to its native read-only task/subagent mechanism, but must enforce its own permissions or hooks because the Pi workflow guard does not transfer outside Pi. A different Pi extension can use the same roles when it provides the documented capabilities or an adapter; otherwise PWK performs recon and review inline.
|
|
40
|
+
|
|
41
|
+
See [`docs/provider-delegation-contract.md`](docs/provider-delegation-contract.md) for the normalized capability and outcome contract. The core kit does not install a provider, require `@tintinweb/pi-subagents`, or provide automatic compatibility with every Pi subagent extension.
|
|
30
42
|
|
|
31
43
|
## What You Get
|
|
32
44
|
|
|
@@ -58,10 +70,10 @@ A **design doc is one PR**; a **requirement is one testable slice within it**. A
|
|
|
58
70
|
|
|
59
71
|
| Phase | Trigger | What Happens |
|
|
60
72
|
|-------|---------|--------------|
|
|
61
|
-
| **Brainstorm** | `/skill:pwk-brainstorming` | Explore approaches, produce a design doc with a `## Requirements` list. On non-trivial topics,
|
|
73
|
+
| **Brainstorm** | `/skill:pwk-brainstorming` | Explore approaches, produce a design doc with a `## Requirements` list. On non-trivial topics, requests the logical `codebase-recon` capability; if unavailable or unsafe, performs the `pwk-recon-scout` role inline. |
|
|
62
74
|
| **Plan** | `/skill:pwk-writing-plans` | Turn each requirement into **acceptance criteria + integration tests** — a behavioral spec (no implementation code) |
|
|
63
75
|
| **Execute** | `/skill:pwk-executing-tasks` | Write the feature E2E (red) → **checkpoint: feature-spec** → implement requirements → **checkpoint: feature-complete** → feature review |
|
|
64
|
-
| **Code review** | `/skill:pwk-code-review` | Feature-level (default) or per-requirement: code tracing, spec alignment, code smells (applies fixes), production hazard check |
|
|
76
|
+
| **Code review** | `/skill:pwk-code-review` | Feature-level (default) or per-requirement: code tracing, spec alignment, code smells (applies fixes), production hazard check. Delegated review uses four logical roles when a safe provider is available; otherwise it runs inline. |
|
|
65
77
|
| **Finalize** | `/skill:pwk-finalizing` | Delete consumed plan docs, update README/CHANGELOG, create PR |
|
|
66
78
|
| **Diagnose** | `/skill:pwk-diagnose` | Debugging loop: reproduce → hypothesise → instrument → fix → cleanup. **Exits the gated phase** (debugging writes tests/instrumentation) |
|
|
67
79
|
| **Status** | `/skill:pwk-status` | Read-only overview of all active design topics — phase + progress. Use when resuming or juggling several designs in parallel worktrees. Not a pipeline phase; **does not exit the gated phase**. |
|
|
@@ -177,11 +189,12 @@ pi-workflow-kit/
|
|
|
177
189
|
│ ├── pwk-finalizing/SKILL.md
|
|
178
190
|
│ ├── pwk-status/SKILL.md
|
|
179
191
|
│ └── pwk-diagnose/SKILL.md
|
|
180
|
-
├── agents/ #
|
|
192
|
+
├── agents/ # canonical role contracts; /pwk-setup copies them to .agents/agents/
|
|
181
193
|
├── docs/
|
|
182
194
|
│ ├── developer-usage-guide.md
|
|
183
195
|
│ ├── workflow-phases.md
|
|
184
196
|
│ ├── oversight-model.md
|
|
197
|
+
│ ├── provider-delegation-contract.md
|
|
185
198
|
│ ├── lessons.md
|
|
186
199
|
│ ├── adr/ # permanent architectural decisions (never archived)
|
|
187
200
|
│ └── plans/ # active design/plan/progress docs (deleted after finalization)
|
|
@@ -7,7 +7,11 @@ systemPromptMode: replace
|
|
|
7
7
|
|
|
8
8
|
# PWK Hazard Reviewer
|
|
9
9
|
|
|
10
|
-
You are a production-hazards reviewer. Execute the task instructions below faithfully using read-only tools
|
|
10
|
+
You are a production-hazards reviewer. Execute the task instructions below faithfully using the host’s read-only tools. **Report findings only — do not modify files.** Flag hazards and non-trivial issues for the main agent or human to decide.
|
|
11
|
+
|
|
12
|
+
## Authority boundary
|
|
13
|
+
|
|
14
|
+
The host must enforce read-only execution. Do not create, modify, delete, move, or copy files, and do not run commands that mutate system or repository state.
|
|
11
15
|
|
|
12
16
|
## Checklist — audit each changed file
|
|
13
17
|
|
|
@@ -21,4 +25,6 @@ For each item below, write `[SAFE]` (1-line justification) or `[TRIGGERED]` (con
|
|
|
21
25
|
6. **Unrestricted uploads / temp flooding** — uploads to local temp without limits or `finally` cleanup
|
|
22
26
|
7. **Silent swallowing loops** — background workers catching/suppressing exceptions without logging/back-off
|
|
23
27
|
|
|
24
|
-
Also check the design doc
|
|
28
|
+
Also check the design doc’s `## Production-risk areas`, if any.
|
|
29
|
+
|
|
30
|
+
Include file and line evidence for each finding. If there are no findings, report `No findings` explicitly.
|
|
@@ -7,21 +7,21 @@ systemPromptMode: replace
|
|
|
7
7
|
|
|
8
8
|
# PWK Recon Scout
|
|
9
9
|
|
|
10
|
-
You are a codebase recon scout
|
|
10
|
+
You are a codebase recon scout requested during brainstorming before design work. Your job is to map how a repository handles a topic today so the main agent can design against prior art instead of loading the relevant files into its own context.
|
|
11
11
|
|
|
12
12
|
**You are observations only.** No design recommendations, no preferred-approach opinion, no code beyond one-line excerpts. Every claim must cite a `file:line` so the main agent can drill in if it needs to.
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Authority boundary
|
|
15
15
|
|
|
16
|
-
You
|
|
16
|
+
You are a read-only reporter. The host must enforce the requested read-only boundary; do not create, modify, delete, move, or copy files, and do not run commands that mutate system or repository state.
|
|
17
17
|
|
|
18
18
|
## Inputs
|
|
19
19
|
|
|
20
|
-
The
|
|
20
|
+
The host provides three things:
|
|
21
21
|
|
|
22
22
|
- a `<topic>` (one short phrase, the new feature or change)
|
|
23
23
|
- a one-line `<intent>` (what the new thing does, in plain words)
|
|
24
|
-
- the
|
|
24
|
+
- the repository root
|
|
25
25
|
|
|
26
26
|
If any of these is missing, ask for it before proceeding.
|
|
27
27
|
|
|
@@ -47,7 +47,9 @@ Where similar tests live, what harness they use (vitest, jest, go test, etc.), a
|
|
|
47
47
|
|
|
48
48
|
### Gotchas
|
|
49
49
|
|
|
50
|
-
Anything that bit a previous change, in this layer of the code or in the topic area specifically. A migrations folder that must run in order, a feature flag that gates the new path, a known deadlock with another subsystem, an environment variable that has to be set, a CI hook that runs before tests. The point is to surface landmines before the
|
|
50
|
+
Anything that bit a previous change, in this layer of the code or in the topic area specifically. A migrations folder that must run in order, a feature flag that gates the new path, a known deadlock with another subsystem, an environment variable that has to be set, a CI hook that runs before tests. The point is to surface landmines before the planning phase.
|
|
51
|
+
|
|
52
|
+
End with `Scout: complete` when the five sections are present. If the host cannot complete the report, return `Scout: unavailable` with the reason instead of inventing observations.
|
|
51
53
|
|
|
52
54
|
## Hard rules
|
|
53
55
|
|
|
@@ -59,10 +61,9 @@ Anything that bit a previous change, in this layer of the code or in the topic a
|
|
|
59
61
|
|
|
60
62
|
## When you finish
|
|
61
63
|
|
|
62
|
-
Return the report as your final message. The main agent reads it into its context and uses it as the grounding for
|
|
64
|
+
Return the report as your final message. The main agent reads it into its context and uses it as the grounding context for approach exploration and design presentation.
|
|
63
65
|
|
|
64
66
|
## Failure modes
|
|
65
67
|
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- You return a wrong-shaped report: the main agent will downweight the findings but still proceed. Better to ship the 5-section shape than to improvise.
|
|
68
|
+
- If no compatible read-only delegation worker is available, the main agent performs this role inline.
|
|
69
|
+
- If the role cannot complete, return `Scout: unavailable` with the reason rather than returning an empty or invented report.
|
|
@@ -7,11 +7,21 @@ systemPromptMode: replace
|
|
|
7
7
|
|
|
8
8
|
# PWK Smell Reviewer
|
|
9
9
|
|
|
10
|
-
You are a code-smell reviewer. Execute the task instructions below faithfully using read-only tools
|
|
10
|
+
You are a code-smell reviewer. Execute the task instructions below faithfully using the host’s read-only tools. **Report findings only — do not modify files.** Flag only smells that require large refactors risky to the requirement; everything else is for the main agent to fix.
|
|
11
|
+
|
|
12
|
+
## Authority boundary
|
|
13
|
+
|
|
14
|
+
The host must enforce read-only execution. Do not create, modify, delete, move, or copy files, and do not run commands that mutate system or repository state.
|
|
15
|
+
|
|
16
|
+
## Review scope
|
|
17
|
+
|
|
18
|
+
Review the changed code and affected files against the assigned requirement and feature scope.
|
|
11
19
|
|
|
12
20
|
## Checklist — report what you find
|
|
13
21
|
|
|
14
22
|
- Shallow modules (interface nearly as complex as implementation)
|
|
15
23
|
- Duplication
|
|
16
|
-
- Missing seams
|
|
17
|
-
- Poor naming, magic values, dead code
|
|
24
|
+
- Missing seams or premature abstraction
|
|
25
|
+
- Poor naming, magic values, dead code
|
|
26
|
+
|
|
27
|
+
Include file and line evidence for each finding. If there are no findings, report `No findings` explicitly.
|
|
@@ -7,8 +7,12 @@ systemPromptMode: replace
|
|
|
7
7
|
|
|
8
8
|
# PWK Spec Reviewer
|
|
9
9
|
|
|
10
|
-
You are a spec-alignment reviewer. Execute the task instructions below faithfully using read-only tools
|
|
10
|
+
You are a spec-alignment reviewer. Execute the task instructions below faithfully using the host’s read-only tools. **Report findings only — do not modify files.**
|
|
11
|
+
|
|
12
|
+
## Authority boundary
|
|
13
|
+
|
|
14
|
+
The host must enforce read-only execution. Do not create, modify, delete, move, or copy files, and do not run commands that mutate system or repository state.
|
|
11
15
|
|
|
12
16
|
## Checklist
|
|
13
17
|
|
|
14
|
-
For each acceptance criterion, point to the code and the test that satisfy it. A criterion with no covering code or no test is a **gap**. Code that does more than the criteria specify is **scope creep** — flag it.
|
|
18
|
+
For each acceptance criterion, point to the code and the test that satisfy it. A criterion with no covering code or no test is a **gap**. Code that does more than the criteria specify is **scope creep** — flag it. Include the relevant file and line for each finding. If there are no findings, report `No findings` explicitly.
|
|
@@ -7,8 +7,12 @@ systemPromptMode: replace
|
|
|
7
7
|
|
|
8
8
|
# PWK Trace Reviewer
|
|
9
9
|
|
|
10
|
-
You are a code-tracing reviewer. Execute the task instructions below faithfully using read-only tools
|
|
10
|
+
You are a code-tracing reviewer. Execute the task instructions below faithfully using the host’s read-only tools. **Report findings only — do not modify files.**
|
|
11
|
+
|
|
12
|
+
## Authority boundary
|
|
13
|
+
|
|
14
|
+
The host must enforce read-only execution. Do not create, modify, delete, move, or copy files, and do not run commands that mutate system or repository state.
|
|
11
15
|
|
|
12
16
|
## Checklist
|
|
13
17
|
|
|
14
|
-
Trace the new
|
|
18
|
+
Trace the new or changed code paths end-to-end against the integration tests. For each path, determine whether data flows correctly from entry to the asserted outcome. Note any branch the tests do not exercise, any dead branch, or any path where the trace breaks. Include file and line evidence. If there are no findings, report `No findings` explicitly.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Developer Usage Guide
|
|
2
2
|
|
|
3
|
-
How to install and use `pi-workflow-kit` with
|
|
3
|
+
How to install and use `pi-workflow-kit` with Pi, and how its workflow roles map to other agent hosts.
|
|
4
4
|
|
|
5
5
|
## What you get
|
|
6
6
|
|
|
@@ -40,11 +40,19 @@ You control each phase by invoking the skill. A design doc is one PR; a requirem
|
|
|
40
40
|
|
|
41
41
|
### 1. Brainstorm
|
|
42
42
|
|
|
43
|
+
Before entering the gated phase in Pi, optionally install the canonical role definitions:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
/pwk-setup
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The command creates `.agents/agents/` and installs the five PWK roles. It preserves differing files unless `--force` is supplied and is refused during brainstorm and plan phases. It does not install a delegation provider.
|
|
50
|
+
|
|
43
51
|
```
|
|
44
52
|
/skill:pwk-brainstorming
|
|
45
53
|
```
|
|
46
54
|
|
|
47
|
-
Explore the idea through collaborative dialogue. The agent reads code, asks questions, proposes approaches, and presents the design for your review. On non-trivial topics with prior art, the
|
|
55
|
+
Explore the idea through collaborative dialogue. The agent reads code, asks questions, proposes approaches, and presents the design for your review. On non-trivial topics with prior art, the skill requests the logical `codebase-recon` capability using the `pwk-recon-scout` role. A compatible host may dispatch that role in a fresh, bounded, read-only worker; otherwise the skill reports `Scout: unavailable` and performs the same five-section recon inline.
|
|
48
56
|
|
|
49
57
|
Outcome: `docs/plans/YYYY-MM-DD-<topic>-design.md` — descriptive, opening with a `## Requirements` list. For a too-big requirement, may start an **umbrella** (writes a status-free overview + the first part's design doc). ADRs go to `docs/adr/` (permanent).
|
|
50
58
|
|
|
@@ -68,13 +76,11 @@ Implement via the **feature-gate flow** with full autonomy: write the feature-ac
|
|
|
68
76
|
|
|
69
77
|
### 4. Code review (feature level)
|
|
70
78
|
|
|
71
|
-
The `pwk-executing-tasks` skill
|
|
79
|
+
The `pwk-executing-tasks` skill requests the `parallel-review` capability for four logical roles over the whole feature diff: spec alignment, code tracing, code smells, and production hazards. The roles are independent, fresh-context, read-only reporters; the main agent collects their results, applies smell fixes itself, runs the tests, and flags other findings for the human.
|
|
72
80
|
|
|
73
|
-
|
|
81
|
+
In Pi, `/pwk-setup` installs the canonical role definitions into `.agents/agents/`, where compatible providers such as `@tintinweb/pi-subagents` can discover them. Tintinweb may run the roles through its native `Agent` mechanism or map recon to its built-in read-only `Explore` type. The core kit does not require Tintinweb or any other provider.
|
|
74
82
|
|
|
75
|
-
|
|
76
|
-
pi install npm:pi-subagents
|
|
77
|
-
```
|
|
83
|
+
*Fallback:* if no host/provider can guarantee the requested capabilities, the skill performs the missing recon or review work inline. Other Pi extensions are supported only when they expose the documented capabilities or have a separate adapter; arbitrary extensions are not automatically compatible. See `docs/provider-delegation-contract.md` for the integration contract.
|
|
78
84
|
|
|
79
85
|
### 5. Finalize
|
|
80
86
|
|
|
@@ -102,7 +108,7 @@ A read-only overview of all active design topics — which phase each is in and
|
|
|
102
108
|
|
|
103
109
|
## What the extension does
|
|
104
110
|
|
|
105
|
-
The `workflow-guard` extension watches `write`/`edit` and `bash` tool calls:
|
|
111
|
+
The `workflow-guard` extension registers `/pwk-setup` and watches `write`/`edit` and `bash` tool calls:
|
|
106
112
|
|
|
107
113
|
- **During brainstorm and writing-plans**: blocks writes outside `docs/plans/`, and blocks destructive bash via a simple common-blacklist (a command is allowed unless it matches a destructive pattern). A short phase reminder is shown once when the gated phase begins so the model self-restricts.
|
|
108
114
|
- **During executing-tasks, code-review, finalizing, diagnose**: no restrictions.
|
package/docs/oversight-model.md
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
Skills teach the agent the workflow. There are 5 pipeline skills:
|
|
8
8
|
|
|
9
|
-
- **pwk-brainstorming** — explore ideas, produce a descriptive design doc that opens with a `## Requirements` list. For a requirement too big for one design doc, may start an **umbrella** (multiple design docs under one status-free overview, shipping as one PR)
|
|
9
|
+
- **pwk-brainstorming** — explore ideas, produce a descriptive design doc that opens with a `## Requirements` list. For a requirement too big for one design doc, may start an **umbrella** (multiple design docs under one status-free overview, shipping as one PR). On non-trivial topics, requests the logical `codebase-recon` capability and falls back to the `pwk-recon-scout` role inline when unavailable or unsafe.
|
|
10
10
|
- **pwk-writing-plans** — turn each requirement into acceptance criteria + integration-test cases (a behavioral spec, no implementation code)
|
|
11
11
|
- **pwk-executing-tasks** — feature-gate flow: write the feature E2E first, implement the requirements, then one feature-level review; two mandatory checkpoints at the feature level, per-requirement ceremony opt-in
|
|
12
|
-
- **pwk-code-review** — the inline reviewer (code tracing, spec alignment, code smells, production hazards). During `pwk-executing-tasks`, the
|
|
12
|
+
- **pwk-code-review** — the inline reviewer (code tracing, spec alignment, code smells, production hazards). During `pwk-executing-tasks`, the feature-level review requests the `parallel-review` capability for four logical fresh-context, read-only roles; successful reports are retained and missing roles are retried or completed inline. It falls back to inline review when no safe compatible provider exists. The canonical provider contract is documented in `docs/provider-delegation-contract.md`.
|
|
13
13
|
- **pwk-finalizing** — dispose consumed plan docs (archive or delete; for an umbrella, the overview + every part), curate lessons, update docs, create PR or merge
|
|
14
14
|
|
|
15
15
|
Plus 2 on-demand skills:
|
|
@@ -21,7 +21,7 @@ They explain *what* to do and *when* to do it. Phase control is manual — you i
|
|
|
21
21
|
|
|
22
22
|
## Extension
|
|
23
23
|
|
|
24
|
-
The `workflow-guard` extension enforces one rule:
|
|
24
|
+
The `workflow-guard` extension registers the Pi-only `/pwk-setup` command and enforces one workflow rule:
|
|
25
25
|
|
|
26
26
|
> During brainstorm and plan phases, `write` and `edit` are **hard-blocked** outside `docs/plans/`.
|
|
27
27
|
|
|
@@ -29,7 +29,7 @@ The agent can still use `read` and `bash` for investigation. During those gated
|
|
|
29
29
|
|
|
30
30
|
During executing-tasks, code-review, finalizing, **and diagnose**, nothing is restricted (diagnosis needs to write failing tests and debug instrumentation, so it exits the gate). `pwk-status` stays inside the gate.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Canonical role contracts live in `agents/pwk-*.md` (single source of truth) and can be installed into `.agents/agents/` with `/pwk-setup`. `pwk-executing-tasks` requests logical review roles through the host’s delegation capabilities and passes each role just the requirement scope + diff.
|
|
33
33
|
|
|
34
34
|
Phases follow the skill you invoke — there is no message-keyword unlock. Invoking `/skill:pwk-executing-tasks`, `pwk-finalizing`, `pwk-code-review`, or `pwk-diagnose` exits the gated phase (those skills write source); `pwk-status` deliberately does **not** (read-only orientation). `/pwk-guard on|off|auto` manually overrides the guard.
|
|
35
35
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Provider Delegation Contract
|
|
2
|
+
|
|
3
|
+
This document defines the provider-neutral contract for running PWK roles outside the main agent. It is an integration contract for host adapters and extensions. The workflow skills describe the same behavior in portable language; they do not require this document’s TypeScript notation or any specific transport.
|
|
4
|
+
|
|
5
|
+
## Logical operations
|
|
6
|
+
|
|
7
|
+
A provider may support either operation independently:
|
|
8
|
+
|
|
9
|
+
- `codebase-recon` — run one `pwk-recon-scout` role and return its five-section observation map.
|
|
10
|
+
- `feature-review` — run the requested review roles over one feature scope and return one outcome per role.
|
|
11
|
+
|
|
12
|
+
The logical role name is not the provider’s concrete agent type. A provider may map `pwk-recon-scout` to a safe built-in explorer, a custom agent definition, or a host-native read-only task.
|
|
13
|
+
|
|
14
|
+
## Required capabilities
|
|
15
|
+
|
|
16
|
+
A provider advertises capabilities independently from its name:
|
|
17
|
+
|
|
18
|
+
| Capability | Meaning |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `codebase-recon` | Can run one fresh, read-only recon worker and collect its report. |
|
|
21
|
+
| `named-role-dispatch` | Can map each requested logical role to an appropriate worker. |
|
|
22
|
+
| `parallel-review` | Can run independent review roles concurrently when requested. |
|
|
23
|
+
| `result-collection` | Returns one distinguishable outcome for every requested role. |
|
|
24
|
+
| `read-only-enforcement` | Prevents delegated workers from writing files or running destructive commands. |
|
|
25
|
+
| `fresh-context` | Starts each requested worker without reusing an unrelated prior conversation. |
|
|
26
|
+
| `bounded-execution` | Applies a timeout, turn limit, or equivalent resource bound. |
|
|
27
|
+
|
|
28
|
+
A provider must not claim `read-only-enforcement` when it only adds a prompt instruction. Providers may support `codebase-recon` without supporting `parallel-review`.
|
|
29
|
+
|
|
30
|
+
## Request shape
|
|
31
|
+
|
|
32
|
+
The following TypeScript is illustrative. Implementations may use Pi events, tool calls, CLI processes, native task APIs, or another transport. A reference implementation of the outcome normalization lives in `extensions/workflow-guard.ts` (`assessDelegationCoverage`), exported as a pure helper so future adapters and tests share one definition of complete coverage.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
type DelegationOperation = 'codebase-recon' | 'feature-review';
|
|
36
|
+
type DelegationRole =
|
|
37
|
+
| 'pwk-recon-scout'
|
|
38
|
+
| 'pwk-spec-reviewer'
|
|
39
|
+
| 'pwk-tracing-reviewer'
|
|
40
|
+
| 'pwk-smell-reviewer'
|
|
41
|
+
| 'pwk-hazard-reviewer';
|
|
42
|
+
|
|
43
|
+
type DelegationRequest = {
|
|
44
|
+
operation: DelegationOperation;
|
|
45
|
+
roles: DelegationRole[];
|
|
46
|
+
prompt: string;
|
|
47
|
+
cwd: string;
|
|
48
|
+
constraints: {
|
|
49
|
+
readOnly: true;
|
|
50
|
+
freshContext: true;
|
|
51
|
+
parallel: boolean;
|
|
52
|
+
bounded: true;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The provider must preserve the logical roles and the repository root when translating a request. `parallel: true` requests concurrency; it does not permit unbounded concurrency. If the provider cannot satisfy a requested constraint, it must reject the delegated operation so the host can use inline fallback.
|
|
58
|
+
|
|
59
|
+
## Normalized outcome shape
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
type DelegationStatus = 'completed' | 'failed' | 'timed-out' | 'skipped';
|
|
63
|
+
|
|
64
|
+
type DelegationResult = {
|
|
65
|
+
role: DelegationRole;
|
|
66
|
+
status: DelegationStatus;
|
|
67
|
+
report?: string;
|
|
68
|
+
error?: string;
|
|
69
|
+
provider?: string;
|
|
70
|
+
runId?: string;
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Rules:
|
|
75
|
+
|
|
76
|
+
- `role` is required and must identify one requested logical role.
|
|
77
|
+
- `completed` requires a non-empty `report` that follows the role contract.
|
|
78
|
+
- `failed` and `timed-out` require an `error` or equivalent failure explanation.
|
|
79
|
+
- `skipped` is explicit and is not equivalent to completion.
|
|
80
|
+
- `provider` identifies the adapter or host that produced the outcome when known.
|
|
81
|
+
- `runId` is an opaque provider-local identifier when available; consumers must not interpret its format.
|
|
82
|
+
- A multi-role operation is complete only when every requested role has a completed result or an explicit fallback result approved by the workflow.
|
|
83
|
+
|
|
84
|
+
An empty report is not a successful result. A missing role is not silently discarded.
|
|
85
|
+
|
|
86
|
+
## Fallback protocol
|
|
87
|
+
|
|
88
|
+
If no provider satisfies the requested capabilities, the host performs the role inline using the same logical contract. For recon, it reports:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
Scout: unavailable — inline recon used.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For feature review, successful delegated reports remain usable. A failed or timed-out role is retried or performed inline. The host does not report a complete review while a required role has neither a delegated result nor an inline result.
|
|
95
|
+
|
|
96
|
+
## Provider discovery and selection
|
|
97
|
+
|
|
98
|
+
Provider discovery and transport are host-specific. A future Pi adapter may use a capability registry, an event-bus handshake, a shared extension RPC, or explicit configuration. The core PWK package does not assume that all Pi extensions are discoverable or that a package name identifies a compatible provider.
|
|
99
|
+
|
|
100
|
+
If multiple providers are available, selection must be deterministic. A host may use explicit configuration or a documented priority order. It must not select a provider based only on extension load order when that changes safety or result semantics.
|
|
101
|
+
|
|
102
|
+
## Role setup and provider loading
|
|
103
|
+
|
|
104
|
+
The Pi-only `/pwk-setup` command copies the canonical role definitions into `.agents/agents/`. This makes named roles available to providers that discover the shared directory, including `@tintinweb/pi-subagents`. Setup creates role definitions; it does not install or configure a provider.
|
|
105
|
+
|
|
106
|
+
Providers may cache role definitions. Hosts should tell the user when `/reload` or a new session is needed. Setup must not reload a session implicitly.
|
|
107
|
+
|
|
108
|
+
## Safety boundary
|
|
109
|
+
|
|
110
|
+
The provider is responsible for enforcing any capability it advertises. The role prompt is defense in depth, not a security boundary. The Pi workflow guard protects the main Pi session’s brainstorm and plan phases; it does not automatically protect Claude Code or another host, and it does not replace delegated-worker tool restrictions.
|
|
111
|
+
|
|
112
|
+
The `/pwk-setup` installer itself is hardened in depth: it opens the target with `O_NOFOLLOW` and does every subsequent check, read, and write through that one descriptor (`fstat` regular-file check, content comparison, and post-write verification), so nothing swapped in on the path afterward can affect what is read or written. On platforms where `O_NOFOLLOW` is unavailable, a symlink swapped in before the initial open remains a narrow advisory window; setup is a user-invoked development command, not a security boundary.
|
package/docs/workflow-phases.md
CHANGED
|
@@ -43,7 +43,7 @@ Write boundary: only `docs/plans/` is writable.
|
|
|
43
43
|
/skill:pwk-executing-tasks
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
- **Feature-gate flow:** write the feature-acceptance E2E test (red) → **⏸ checkpoint: feature-spec** (human confirms the E2E proves the feature) → implement the requirements back-to-back with full autonomy (the executor chooses structure/signatures/internals) → **⏸ checkpoint: feature-complete** (full suite + feature E2E green) → **feature review** (
|
|
46
|
+
- **Feature-gate flow:** write the feature-acceptance E2E test (red) → **⏸ checkpoint: feature-spec** (human confirms the E2E proves the feature) → implement the requirements back-to-back with full autonomy (the executor chooses structure/signatures/internals) → **⏸ checkpoint: feature-complete** (full suite + feature E2E green) → **feature review** (request the `parallel-review` capability for four logical read-only roles when the host supports it; otherwise run `/skill:pwk-code-review` inline — see [code-review](#code-review)).
|
|
47
47
|
- Per-requirement checkpoints/reviews are **opt-in** — they fire only for requirements the plan tags (default off); see [Proportionality](#proportionality).
|
|
48
48
|
- **Regression check after each commit** — run the full existing suite to catch cross-requirement regressions immediately. The feature E2E stays red until the last requirement and is gated only at `feature-complete` (the old integration gate folds into it).
|
|
49
49
|
- Progress tracked in `docs/plans/*-progress.md` (feature phase + requirement checklist).
|
|
@@ -68,7 +68,7 @@ Flag a requirement for a checkpoint when it has complex logic or is the main par
|
|
|
68
68
|
|
|
69
69
|
The **inline reviewer**: code tracing, spec alignment (vs acceptance criteria), code smells (applies fixes), production hazard check. Unlocked — may modify code to fix smells.
|
|
70
70
|
|
|
71
|
-
**Not a phase you drive manually.** During `pwk-executing-tasks`, the
|
|
71
|
+
**Not a phase you drive manually.** During `pwk-executing-tasks`, the feature-level review requests four logical roles (`pwk-spec-reviewer`, `pwk-tracing-reviewer`, `pwk-smell-reviewer`, `pwk-hazard-reviewer`) through the host’s `parallel-review` capability. Roles are fresh-context, read-only reporters; successful reports are retained and failed roles are retried or completed inline. If no compatible provider is available, the whole review runs inline. In Pi, `/pwk-setup` installs the canonical role definitions into `.agents/agents/`; [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents) is one compatible provider. See `docs/provider-delegation-contract.md` for the provider contract. You can also invoke `/skill:pwk-code-review` standalone for an ad-hoc review of any diff.
|
|
72
72
|
|
|
73
73
|
No write restrictions.
|
|
74
74
|
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
closeSync,
|
|
3
|
+
constants,
|
|
4
|
+
fstatSync,
|
|
5
|
+
ftruncateSync,
|
|
6
|
+
lstatSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
openSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
readSync,
|
|
11
|
+
writeSync,
|
|
12
|
+
} from "node:fs";
|
|
13
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
2
15
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
16
|
|
|
4
17
|
/**
|
|
@@ -12,6 +25,192 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
12
25
|
|
|
13
26
|
type Phase = "brainstorm" | "plan" | null;
|
|
14
27
|
|
|
28
|
+
type DelegationStatus = "completed" | "failed" | "timed-out" | "skipped";
|
|
29
|
+
|
|
30
|
+
export interface DelegationOutcome {
|
|
31
|
+
role: string;
|
|
32
|
+
status: DelegationStatus;
|
|
33
|
+
report?: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
provider?: string;
|
|
36
|
+
runId?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface DelegationCoverage {
|
|
40
|
+
complete: boolean;
|
|
41
|
+
missing: string[];
|
|
42
|
+
retainedReports: string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Summarize role outcomes without treating failed or empty outcomes as coverage. */
|
|
46
|
+
export function assessDelegationCoverage(
|
|
47
|
+
requiredRoles: readonly string[],
|
|
48
|
+
outcomes: readonly DelegationOutcome[],
|
|
49
|
+
): DelegationCoverage {
|
|
50
|
+
const completedReports = new Map<string, string>();
|
|
51
|
+
for (const outcome of outcomes) {
|
|
52
|
+
if (outcome.status === "completed" && outcome.report) {
|
|
53
|
+
completedReports.set(outcome.role, outcome.report);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const missing = requiredRoles.filter((role) => !completedReports.has(role));
|
|
58
|
+
return {
|
|
59
|
+
complete: missing.length === 0,
|
|
60
|
+
missing,
|
|
61
|
+
retainedReports: [...completedReports.values()],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const ROLE_NAMES = [
|
|
66
|
+
"pwk-recon-scout",
|
|
67
|
+
"pwk-spec-reviewer",
|
|
68
|
+
"pwk-tracing-reviewer",
|
|
69
|
+
"pwk-smell-reviewer",
|
|
70
|
+
"pwk-hazard-reviewer",
|
|
71
|
+
] as const;
|
|
72
|
+
|
|
73
|
+
const CANONICAL_AGENTS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..", "agents");
|
|
74
|
+
|
|
75
|
+
function setupUsageError(): Error {
|
|
76
|
+
return new Error("Usage: /pwk-setup [--force]");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseSetupArgs(args: string): { force: boolean } {
|
|
80
|
+
const normalized = args.trim();
|
|
81
|
+
if (!normalized) return { force: false };
|
|
82
|
+
if (normalized === "--force") return { force: true };
|
|
83
|
+
throw setupUsageError();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function ensureDirectory(path: string): void {
|
|
87
|
+
const stats = statNoFollow(path);
|
|
88
|
+
if (!stats) {
|
|
89
|
+
mkdirSync(path);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (stats.isSymbolicLink()) throw new Error(`Refusing symlink destination: ${path}`);
|
|
93
|
+
if (!stats.isDirectory()) throw new Error(`Destination is not a directory: ${path}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** lstat without following symlinks; null when the path does not exist. */
|
|
97
|
+
function statNoFollow(path: string): ReturnType<typeof lstatSync> | null {
|
|
98
|
+
try {
|
|
99
|
+
return lstatSync(path);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Read exactly `size` bytes from `fd` starting at position 0, regardless of the fd's cursor. */
|
|
107
|
+
function readAllFromFd(fd: number, size: number): string {
|
|
108
|
+
const buffer = Buffer.alloc(size);
|
|
109
|
+
let offset = 0;
|
|
110
|
+
while (offset < size) {
|
|
111
|
+
const bytesRead = readSync(fd, buffer, offset, size - offset, offset);
|
|
112
|
+
if (bytesRead === 0) break;
|
|
113
|
+
offset += bytesRead;
|
|
114
|
+
}
|
|
115
|
+
return buffer.toString("utf8");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Write `content` to `fd` at position 0 (truncating first) and verify by reading the same fd back. */
|
|
119
|
+
function overwriteFd(fd: number, content: string, path: string): void {
|
|
120
|
+
ftruncateSync(fd, 0);
|
|
121
|
+
const buffer = Buffer.from(content, "utf8");
|
|
122
|
+
writeSync(fd, buffer, 0, buffer.length, 0);
|
|
123
|
+
if (readAllFromFd(fd, buffer.length) !== content) throw new Error(`Verification failed after writing: ${path}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function writeNewFile(path: string, content: string): void {
|
|
127
|
+
const noFollow = constants.O_NOFOLLOW ?? 0;
|
|
128
|
+
const flags = constants.O_RDWR | noFollow | constants.O_CREAT | constants.O_EXCL;
|
|
129
|
+
const fd = openSync(path, flags, 0o644);
|
|
130
|
+
try {
|
|
131
|
+
overwriteFd(fd, content, path);
|
|
132
|
+
} finally {
|
|
133
|
+
closeSync(fd);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function installRoleFiles(cwd: string, force: boolean): { installed: string[]; skipped: string[] } {
|
|
138
|
+
const projectAgentsDir = join(cwd, ".agents");
|
|
139
|
+
const targetDir = join(projectAgentsDir, "agents");
|
|
140
|
+
ensureDirectory(projectAgentsDir);
|
|
141
|
+
ensureDirectory(targetDir);
|
|
142
|
+
|
|
143
|
+
const installed: string[] = [];
|
|
144
|
+
const skipped: string[] = [];
|
|
145
|
+
const failures: string[] = [];
|
|
146
|
+
const noFollow = constants.O_NOFOLLOW ?? 0;
|
|
147
|
+
|
|
148
|
+
for (const roleName of ROLE_NAMES) {
|
|
149
|
+
const sourcePath = join(CANONICAL_AGENTS_DIR, `${roleName}.md`);
|
|
150
|
+
const targetPath = join(targetDir, `${roleName}.md`);
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
// Read inside the try: one broken canonical source becomes a per-role failure
|
|
154
|
+
// instead of aborting the whole install and hiding other roles' results.
|
|
155
|
+
const content = readFileSync(sourcePath, "utf8");
|
|
156
|
+
|
|
157
|
+
// Open the existing target (if any) once and do every check/read/write through
|
|
158
|
+
// that single fd — the fd names one fixed inode, so nothing swapped in on the
|
|
159
|
+
// path between checks (TOCTOU) can affect what gets read or written.
|
|
160
|
+
let fd: number | null;
|
|
161
|
+
try {
|
|
162
|
+
fd = openSync(targetPath, constants.O_RDWR | noFollow);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
const err = error as NodeJS.ErrnoException;
|
|
165
|
+
if (err.code === "ENOENT") {
|
|
166
|
+
fd = null;
|
|
167
|
+
} else if (err.code === "ELOOP") {
|
|
168
|
+
throw new Error(`Refusing symlink destination: ${targetPath}`);
|
|
169
|
+
} else {
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (fd === null) {
|
|
175
|
+
writeNewFile(targetPath, content);
|
|
176
|
+
installed.push(roleName);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const stats = fstatSync(fd);
|
|
182
|
+
if (!stats.isFile()) throw new Error(`Refusing non-regular destination: ${targetPath}`);
|
|
183
|
+
|
|
184
|
+
const existing = readAllFromFd(fd, stats.size);
|
|
185
|
+
if (existing === content) {
|
|
186
|
+
skipped.push(roleName);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (!force) {
|
|
190
|
+
failures.push(`${targetPath}: conflict (use /pwk-setup --force to replace it)`);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
overwriteFd(fd, content, targetPath);
|
|
195
|
+
installed.push(roleName);
|
|
196
|
+
} finally {
|
|
197
|
+
closeSync(fd);
|
|
198
|
+
}
|
|
199
|
+
} catch (error) {
|
|
200
|
+
failures.push(`${targetPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (failures.length > 0) {
|
|
205
|
+
const partial =
|
|
206
|
+
installed.length + skipped.length > 0
|
|
207
|
+
? ` (${installed.length} installed, ${skipped.length} skipped before failure — installation is partial)`
|
|
208
|
+
: "";
|
|
209
|
+
throw new Error(`PWK setup incomplete${partial}:\n${failures.join("\n")}`);
|
|
210
|
+
}
|
|
211
|
+
return { installed, skipped };
|
|
212
|
+
}
|
|
213
|
+
|
|
15
214
|
// Destructive commands blocked in brainstorm/plan phases (simple common blacklist)
|
|
16
215
|
const DESTRUCTIVE_PATTERNS = [
|
|
17
216
|
/\brm\b/i,
|
|
@@ -181,6 +380,16 @@ function enforceLabel(): string {
|
|
|
181
380
|
return guardOverride === "on" ? "GUARD ON" : phase ? phase.toUpperCase() : "";
|
|
182
381
|
}
|
|
183
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Is `/pwk-setup` blocked right now? Deliberately NOT `enforceActive()`: setup must
|
|
385
|
+
* refuse during a gated phase even when the tool-call guard is manually disabled
|
|
386
|
+
* (`/pwk-guard off`), since its own banner promises writes stay confined to
|
|
387
|
+
* docs/plans/ for the whole gated phase, override or not.
|
|
388
|
+
*/
|
|
389
|
+
function setupBlocked(): boolean {
|
|
390
|
+
return phase !== null || guardOverride === "on";
|
|
391
|
+
}
|
|
392
|
+
|
|
184
393
|
export default function (pi: ExtensionAPI) {
|
|
185
394
|
pi.on("session_start", () => {
|
|
186
395
|
phase = null;
|
|
@@ -188,6 +397,40 @@ export default function (pi: ExtensionAPI) {
|
|
|
188
397
|
guardOverride = null;
|
|
189
398
|
});
|
|
190
399
|
|
|
400
|
+
// --- Project role setup -------------------------------------------------
|
|
401
|
+
// This command writes through Node rather than the write tool, so it enforces
|
|
402
|
+
// the gated-phase boundary itself instead of relying on tool_call interception.
|
|
403
|
+
pi.registerCommand("pwk-setup", {
|
|
404
|
+
description: "Install PWK role agents into .agents/agents/",
|
|
405
|
+
handler: async (args, ctx) => {
|
|
406
|
+
// Refuse whenever the session is read-only in fact: gated phase (even with the
|
|
407
|
+
// tool-call guard manually disabled — the design mandates that) or the manual
|
|
408
|
+
// read-only lock, whose banner promises "writes only under docs/plans/".
|
|
409
|
+
if (setupBlocked()) {
|
|
410
|
+
const scope =
|
|
411
|
+
guardOverride === "on"
|
|
412
|
+
? "the manual read-only lock (/pwk-guard on)"
|
|
413
|
+
: `${(phase as string).toUpperCase()} phase`;
|
|
414
|
+
const message = `Cannot run /pwk-setup during ${scope}. Run it before entering the gated workflow or after leaving it (guard auto/off).`;
|
|
415
|
+
ctx.ui.notify(message, "warning");
|
|
416
|
+
throw new Error(message);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const { force } = parseSetupArgs(args ?? "");
|
|
420
|
+
try {
|
|
421
|
+
const result = installRoleFiles(ctx.cwd, force);
|
|
422
|
+
const parts = [`PWK setup complete: ${result.installed.length} installed`];
|
|
423
|
+
if (result.skipped.length > 0) parts.push(`${result.skipped.length} skipped`);
|
|
424
|
+
if (force) parts.push("forced conflicts replaced");
|
|
425
|
+
ctx.ui.notify(`${parts.join(", ")}. Providers may require /reload to discover updated roles.`, "info");
|
|
426
|
+
} catch (error) {
|
|
427
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
428
|
+
ctx.ui.notify(message, "error");
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
|
|
191
434
|
// --- Manual override (escape hatch) -----------------------------------
|
|
192
435
|
// Phases are driven by `/skill:` commands; `/pwk-guard` lets the user pin the
|
|
193
436
|
// guard regardless of phase. `/pwk-guard auto` returns control to skill transitions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tianhai/pi-workflow-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Enforce structured brainstorm→plan→execute→finalize workflow with TDD discipline in AI coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"docs/developer-usage-guide.md",
|
|
33
33
|
"docs/workflow-phases.md",
|
|
34
34
|
"docs/oversight-model.md",
|
|
35
|
+
"docs/provider-delegation-contract.md",
|
|
35
36
|
"LICENSE",
|
|
36
37
|
"README.md"
|
|
37
38
|
],
|
|
@@ -54,7 +54,7 @@ The whole umbrella is one branch and one PR: `pwk-writing-plans` creates the bra
|
|
|
54
54
|
1. **Check git state** — `git status` + `git log --oneline -5`. Uncommitted work? Ask the user what to do first.
|
|
55
55
|
2. **Discovery** *(skip in a brand-new repo with no `docs/plans/`)* — glob `docs/plans/*-design.md` and `*-overview.md`; report in-flight topics and any active umbrella. If the new idea continues an existing topic, ask whether to extend it or start fresh. Part of an umbrella? An existing `*-overview.md` means the split is already decided — read it for the roster and design this part's `-design.md` against it (see [Umbrella](#umbrella)).
|
|
56
56
|
3. **Understand the idea** — read only enough code/docs/commits to ground the design. **Check `docs/lessons.md`** — known constraints may shape it. Ask questions one at a time, prefer multiple choice. Once you can articulate what/why/constraints, present a short summary and ask: "Should I proceed, or is there more?" The human decides when to move on.
|
|
57
|
-
4. **(skipped on trivial changes)** **Codebase recon** — for non-trivial topics with prior art,
|
|
57
|
+
4. **(skipped on trivial changes)** **Codebase recon** — for non-trivial topics with prior art, request the host’s `codebase-recon` capability using the logical `pwk-recon-scout` role. Require a fresh-context, read-only, bounded worker and pass the topic, one-line intent, and repo root. Use the returned 5-section codebase map (Relevant files, Existing patterns, Call sites, Test layout, Gotchas) as the grounding context for the next two steps instead of reading those files inline. The scout is observations only — no design recommendations. Skip this step on trivial changes (typo, version bump, single-function edit per the proportionality rule). If no compatible capability is available or the provider cannot enforce the requested constraints, report `Scout: unavailable` and do the same recon inline, preserving the five-section map and `file:line` citations; do not silently omit recon.
|
|
58
58
|
5. **Explore approaches** — propose 2–3, leading with your recommendation. Sketch the concrete interface (types, signatures, example caller) for each so the comparison is grounded in code, not abstractions.
|
|
59
59
|
6. **Present the design** in one pass, organized into sections (architecture, components, data flow, error handling, testing) — the human comments on any section; re-present only revised sections.
|
|
60
60
|
|
|
@@ -7,7 +7,7 @@ description: "Implement a plan via the feature-gate flow: write the feature-acce
|
|
|
7
7
|
|
|
8
8
|
Implement the plan from `docs/plans/*-implementation.md` via the **feature-gate flow**. The plan is a behavioral spec (acceptance criteria + integration tests) — you choose structure, signatures, internals; the criteria define *what*, you decide *how*.
|
|
9
9
|
|
|
10
|
-
The feature-acceptance E2E test is the primary enforced gate. The flow is always on: write the E2E first (red), implement the requirements back-to-back, then run one feature-level review over the whole diff. Per-requirement checkpoints and reviews are **opt-in** — they fire only for requirements the plan tags (default off); the feature gate covers everything else.
|
|
10
|
+
The feature-acceptance E2E test is the primary enforced gate and the primary enforced spec for the feature. The flow is always on: write the E2E first (red), implement the requirements back-to-back, then run one feature-level review over the whole diff. Per-requirement checkpoints and reviews are **opt-in** — they fire only for requirements the plan tags (default off); the feature gate covers everything else.
|
|
11
11
|
|
|
12
12
|
## Before you start
|
|
13
13
|
|
|
@@ -93,25 +93,10 @@ The old "integration gate" is gone — the feature E2E at `feature-complete` *is
|
|
|
93
93
|
|
|
94
94
|
After `feature-complete` is approved, run **one** review over the **whole feature diff**, driven by the plan's feature-level `### Feature review` tag. This is the single thorough review — per-requirement reviews, if any, only saw slices in isolation.
|
|
95
95
|
|
|
96
|
-
- **`parallel`** (default) — four fresh-context
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"tasks": [
|
|
101
|
-
{"agent": "pwk-spec-reviewer", "task": "<scope + whole diff here>"},
|
|
102
|
-
{"agent": "pwk-tracing-reviewer", "task": "<scope + whole diff here>"},
|
|
103
|
-
{"agent": "pwk-smell-reviewer", "task": "<scope + whole diff here>"},
|
|
104
|
-
{"agent": "pwk-hazard-reviewer", "task": "<scope + whole diff here>"}
|
|
105
|
-
],
|
|
106
|
-
"agentScope": "both",
|
|
107
|
-
"cwd": "<repo-root>"
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
The reviewer checklists live only in `agents/pwk-*-reviewer.md` — don't restate them in the task strings (duplication guarantees drift). Reviewers are read-only reporters; you apply smell fixes yourself (full suite + E2E must stay green, commit) and flag trace/spec/hazard findings as follow-ups for the human.
|
|
112
|
-
|
|
113
|
-
- **`inline`** — run `/skill:pwk-code-review` over the whole diff as a single pass.
|
|
114
|
-
- **Fallback** — subagent tool unavailable or errors → run `/skill:pwk-code-review` inline instead.
|
|
96
|
+
- **`parallel`** (default) — request the host’s `parallel-review` capability for four fresh-context, read-only logical roles: `pwk-spec-reviewer`, `pwk-tracing-reviewer`, `pwk-smell-reviewer`, and `pwk-hazard-reviewer`. Gather scope (the plan's acceptance criteria + Feature acceptance, `git log --oneline && git diff <merge-base>...HEAD`) and provide it to every role. Require independent execution and one collected outcome per role. The reviewer role contracts live in `agents/pwk-*-reviewer.md`; do not duplicate their checklists in the workflow instructions. Reviewers are read-only reporters; you apply smell fixes yourself (full suite + E2E must stay green, commit) and flag trace/spec/hazard findings as follow-ups for the human.
|
|
97
|
+
|
|
98
|
+
- **`inline`** — perform `/skill:pwk-code-review` over the whole diff as a single pass.
|
|
99
|
+
- **Fallback** — if the host has no compatible parallel-review capability, cannot prove the requested read-only/fresh-context/bounded constraints, or delegation fails, perform the missing review work inline. Retain successful delegated reports and do not mark the feature fully reviewed while a required role is missing.
|
|
115
100
|
|
|
116
101
|
On success, set `Feature phase: done`.
|
|
117
102
|
|
|
@@ -23,7 +23,7 @@ Your writes go into `docs/plans/` and nowhere else. Source code and configuratio
|
|
|
23
23
|
- **Integration tests** — test name + what each asserts. This is the spec the executor writes tests from.
|
|
24
24
|
- **Meaningful tests** — write acceptance criteria and tests as observable behavior: (1) **Test observable behavior** — assert on what the feature produces or changes (a return value, persisted/updated data, an emitted event, an HTTP response) through its public interface; these assertions keep passing as the implementation changes. (2) **Write a per-slice test when the slice has its own observable behavior** — when a slice is pure config or a trivial extraction, the feature E2E covers it and a per-slice test is unnecessary.
|
|
25
25
|
- **`### Checkpoints: none | full | spec`** — how many human stops. `none` = no per-requirement stop (default — the feature gate covers it); `full` = tests + complete stops; `spec` = tests stop only. Flag a requirement `full` or `spec` when it contains complex logic or is the main part of the feature — where a human look at the slice is worth the stop.
|
|
26
|
-
- **`### Review: skip | parallel | inline`** — `skip` = no per-requirement review (default — the feature-level review covers it); `parallel` = four reviewers via
|
|
26
|
+
- **`### Review: skip | parallel | inline`** — `skip` = no per-requirement review (default — the feature-level review covers it); `parallel` = four reviewers via delegated parallel roles; `inline` = one `pwk-code-review` pass. The auto-tag bullet below is the single source of truth for risky-requirement tagging.
|
|
27
27
|
- **`### Feature review: parallel | inline`** — one review over the **whole feature diff**, always present (the single thorough pass). `parallel` (default — thoroughness lives here, since it is the only review in the common case); `inline` for small features.
|
|
28
28
|
- Tag every requirement — missing tags default to `none` / `skip`. **`spec` requires at least `inline` review** — dropping the complete checkpoint is only safe when review covers implementation quality; never combine `spec` with `Review: skip` (use `Checkpoints: none` instead).
|
|
29
29
|
- **Production-risk notes** — carry forward the design's `## Production-risk areas`, if any.
|