@mgiles/perk 1.0.1
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 +105 -0
- package/extension/adapters/planAdapterPlannotator.ts +269 -0
- package/extension/adapters/planAdapterTombell.ts +147 -0
- package/extension/adapters/todoAdapterJuicesharp.ts +105 -0
- package/extension/checkpoints/checkpoints.ts +542 -0
- package/extension/checkpoints/planSteps.ts +108 -0
- package/extension/doors/address.ts +360 -0
- package/extension/doors/askUser.ts +194 -0
- package/extension/doors/ciExecutor.ts +583 -0
- package/extension/doors/land.ts +222 -0
- package/extension/doors/learn.ts +235 -0
- package/extension/doors/learnDocs.ts +99 -0
- package/extension/doors/lifecycleGates.ts +171 -0
- package/extension/doors/prReview.ts +339 -0
- package/extension/doors/ready.ts +86 -0
- package/extension/doors/selfcheck.ts +155 -0
- package/extension/doors/submit.ts +253 -0
- package/extension/factories/objective.ts +240 -0
- package/extension/factories/objectiveAuthor.ts +114 -0
- package/extension/factories/objectiveDraft.ts +343 -0
- package/extension/factories/objectivePlan.ts +838 -0
- package/extension/factories/objectiveSave.ts +285 -0
- package/extension/factories/planDraft.ts +140 -0
- package/extension/factories/planMode.ts +214 -0
- package/extension/factories/planReview.ts +644 -0
- package/extension/factories/planSave.ts +589 -0
- package/extension/factories/planTitle.ts +123 -0
- package/extension/index.ts +459 -0
- package/extension/substrate/bindingDelivery.ts +199 -0
- package/extension/substrate/bindings.ts +180 -0
- package/extension/substrate/cache.ts +163 -0
- package/extension/substrate/coldDoor.ts +226 -0
- package/extension/substrate/config.ts +339 -0
- package/extension/substrate/miniYaml.ts +262 -0
- package/extension/substrate/prompts.ts +35 -0
- package/extension/substrate/providers.ts +177 -0
- package/extension/substrate/registry.ts +62 -0
- package/extension/substrate/resources.ts +41 -0
- package/extension/substrate/result.ts +72 -0
- package/extension/substrate/runId.ts +49 -0
- package/extension/substrate/sessionData.ts +229 -0
- package/extension/substrate/structuredOutput.ts +141 -0
- package/extension/substrate/toolGating.ts +400 -0
- package/extension/substrate/toolParams.ts +106 -0
- package/extension/substrate/workflowState.ts +233 -0
- package/extension/surfaces/footerProvider.ts +43 -0
- package/extension/surfaces/report.ts +34 -0
- package/extension/surfaces/surfaces.ts +460 -0
- package/extension/vendor/btw/btw.ts +964 -0
- package/extension/vendor/btw/core.ts +153 -0
- package/extension/vendor/whimsical/whimsical.ts +485 -0
- package/extension/worker/readOnlySession.ts +282 -0
- package/extension/worker/worker.ts +765 -0
- package/extension/workerMain.ts +150 -0
- package/package.json +55 -0
- package/prompts/README.md +15 -0
- package/prompts/_fixtures/cases.yaml +140 -0
- package/prompts/_fixtures/golden/address-action-model.txt +10 -0
- package/prompts/_fixtures/golden/address-action.txt +10 -0
- package/prompts/_fixtures/golden/address-preview-model.txt +6 -0
- package/prompts/_fixtures/golden/address-preview.txt +6 -0
- package/prompts/_fixtures/golden/hello.txt +1 -0
- package/prompts/_fixtures/golden/implement-github.txt +8 -0
- package/prompts/_fixtures/golden/learn-docs.txt +8 -0
- package/prompts/_fixtures/golden/learn-github.txt +11 -0
- package/prompts/_fixtures/golden/learn-linear.txt +11 -0
- package/prompts/_fixtures/golden/learn-no-ref.txt +8 -0
- package/prompts/_fixtures/golden/learn-other.txt +8 -0
- package/prompts/_fixtures/golden/objective-plan-guidance-linear.txt +8 -0
- package/prompts/_fixtures/golden/objective-plan-guidance.txt +8 -0
- package/prompts/_fixtures/golden/objective-plan-seed-linear.txt +20 -0
- package/prompts/_fixtures/golden/objective-plan-seed.txt +15 -0
- package/prompts/_fixtures/golden/objective-read-linear-nourl.txt +1 -0
- package/prompts/_fixtures/golden/objective-read-linear.txt +1 -0
- package/prompts/_fixtures/golden/plan-read-github.txt +1 -0
- package/prompts/_fixtures/golden/plan-read-linear.txt +1 -0
- package/prompts/_fixtures/golden/plan-read-other.txt +1 -0
- package/prompts/_fixtures/golden/with_include.txt +4 -0
- package/prompts/_fixtures/templates/_greeting.md +1 -0
- package/prompts/_fixtures/templates/hello.md +1 -0
- package/prompts/_fixtures/templates/with_include.md +4 -0
- package/prompts/common/objective-read/linear.md +1 -0
- package/prompts/common/plan-read/github.md +1 -0
- package/prompts/common/plan-read/linear.md +1 -0
- package/prompts/common/plan-read/other.md +1 -0
- package/prompts/stages/address/action.md +10 -0
- package/prompts/stages/address/preview.md +6 -0
- package/prompts/stages/implement.md +8 -0
- package/prompts/stages/learn-docs.md +8 -0
- package/prompts/stages/learn.md +21 -0
- package/prompts/stages/objective-plan/guidance.md +12 -0
- package/prompts/stages/objective-plan/seed.md +20 -0
- package/shared/README.md +29 -0
- package/shared/bindings.yaml +64 -0
- package/shared/contracts-history.md +403 -0
- package/shared/contracts.md +4172 -0
- package/shared/providers.yaml +221 -0
- package/shared/registry.yaml +199 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# perk provider-selection supported set — the THIRD parsed cross-plane contract
|
|
2
|
+
# (sibling of registry.yaml and bindings.yaml).
|
|
3
|
+
#
|
|
4
|
+
# Authored once here, bundled into each build artifact (wheel -> perk/_shared/,
|
|
5
|
+
# npm tarball -> shared/), and parsed directly by both planes at runtime: the
|
|
6
|
+
# Python reader is perk/substrate/providers.py, the TS reader is extension/substrate/providers.ts. No
|
|
7
|
+
# codegen step — both planes read this same file.
|
|
8
|
+
#
|
|
9
|
+
# This is the SUPPORTED SET (the full catalog of providers perk knows how to wire),
|
|
10
|
+
# distinct from the per-repo SELECTION (the flat `[providers]` table in .pi/perk.toml,
|
|
11
|
+
# which is just a pointer into this catalog). Because both planes read this with their
|
|
12
|
+
# full YAML readers, it can carry nested structure — notably the Pi `package_filter`
|
|
13
|
+
# object — that the narrow-TOML config reader cannot.
|
|
14
|
+
#
|
|
15
|
+
# Vocabulary — each provider entry:
|
|
16
|
+
# id — the stable provider id. NOT the cache.plan-ref `provider` string:
|
|
17
|
+
# that field is the ISSUE BACKEND (the stamped `backend_id`, e.g.
|
|
18
|
+
# "github"), not the seam id — see contracts.md §8.10 / §8.21.
|
|
19
|
+
# seam — `plan` | `todo` | `askuser` | `footer` | `web` (the five seams pluggability-taxonomy.md scope-fenced).
|
|
20
|
+
# package — the foreign Pi package spec added to .pi/settings.json `packages`
|
|
21
|
+
# (e.g. "npm:@tombell/pi-plan"); `null` for perk's own bundled reference
|
|
22
|
+
# provider (nothing to add — perk produces the contract natively). NOT
|
|
23
|
+
# universal: the `web` seam's reference provider (`pi-web-access`) is itself
|
|
24
|
+
# a FOREIGN package because perk owns no native web implementation — its
|
|
25
|
+
# `default: true` entry carries a non-null `package` (the documented exception).
|
|
26
|
+
# adapter — the perk-owned shim module that bridges the foreign surface to the
|
|
27
|
+
# artifact boundary (cache.plan-ref / perk:checkpoint); `null` for the
|
|
28
|
+
# reference provider.
|
|
29
|
+
# default — exactly ONE `true` per seam: the behavior-preserving no-config pick.
|
|
30
|
+
# package_filter — optional Pi object-form filter (extensions/skills/… arrays)
|
|
31
|
+
# merged into the foreign package's `packages` entry to enable only the
|
|
32
|
+
# conflicting surface. perk's own package is NEVER filtered (it defers at
|
|
33
|
+
# runtime instead — adapter-architecture.md Invariant 2).
|
|
34
|
+
#
|
|
35
|
+
# Validation split (mirrors bindings.yaml): the shape-only loaders (perk/substrate/providers.py,
|
|
36
|
+
# extension/substrate/providers.ts) check schema_version, id uniqueness, seam membership, and
|
|
37
|
+
# exactly-one-default-per-seam. Cross-checks — does the repo's `[providers]` selection
|
|
38
|
+
# name a provider that exists / has the right seam? — are `doctor`'s job, NOT the
|
|
39
|
+
# loaders. The Python plane is the authoritative validator.
|
|
40
|
+
#
|
|
41
|
+
# Status (Node 2.1 → 3.2): this file ships the substrate (the three reference entries +
|
|
42
|
+
# foreign entries per seam), and ALL THREE seams now have a REAL foreign provider. The PLAN
|
|
43
|
+
# adapter landed at Node 2.3: `tombell-plan` is a REAL, selectable plan provider —
|
|
44
|
+
# `planAdapterTombell` bridges `@tombell/pi-plan`'s free-form prose surface to perk's
|
|
45
|
+
# canonical `plan_save` → `cache.plan-ref` contract, and perk VACATES the plan surface at
|
|
46
|
+
# REGISTRATION time (not just handler-time) under a foreign plan selection so the foreign
|
|
47
|
+
# `/plan`/`Ctrl+Alt+P`/`--plan` are the sole registrants (Pi suffixes duplicate command
|
|
48
|
+
# names). The TODO adapter landed at Node 3.2: `juicesharp-todo` is a REAL, selectable todo
|
|
49
|
+
# provider — `todoAdapterJuicesharp` carries perk's implement-progress discipline onto
|
|
50
|
+
# `@juicesharp/rpiv-todo`'s checklist overlay (injection-only, active-workflow-gated), and
|
|
51
|
+
# perk's own checkpoints simply DEFER at runtime (Node 3.1) — NO registration-time vacating,
|
|
52
|
+
# because the todo seam has no command-name collision (`/checkpoints` vs the overlay's own
|
|
53
|
+
# command). The DEFAULT path (the reference providers) is the hard guarantee.
|
|
54
|
+
#
|
|
55
|
+
# The ASKUSER seam is an INTERFACE seam (no durable artifact to bridge): its stable contract is
|
|
56
|
+
# the tool NAME `ask_user_question` plus its non-terminating-answer semantics. `juicesharp-ask-user`
|
|
57
|
+
# (`@juicesharp/rpiv-ask-user-question`) registers a tool with the IDENTICAL name, and tools
|
|
58
|
+
# (unlike commands) do NOT get `:N` suffixes — a same-named tool replaces/warns by extension load
|
|
59
|
+
# order. So the adapter is VACATE-ONLY (`adapter: null`, no shim, no injected context): under a
|
|
60
|
+
# foreign askuser selection perk's `registerAskUser` registers NOTHING at REGISTRATION time,
|
|
61
|
+
# leaving exactly one `ask_user_question` standing. Under the default (`perk-ask-user`) the foreign
|
|
62
|
+
# package is never installed, so perk's tool is the sole registrant.
|
|
63
|
+
#
|
|
64
|
+
# The FOOTER seam is the SECOND INTERFACE seam (no durable artifact to bridge), mirroring askuser
|
|
65
|
+
# but with INSTALL-SITE (runtime) vacating rather than registration-time vacating: perk installs
|
|
66
|
+
# its own footer (`installPerkFooter`) inside the `session_start` event handler, so under a foreign
|
|
67
|
+
# `[providers] footer` selection perk simply does NOT call `installPerkFooter` (a runtime guard at
|
|
68
|
+
# that single install site, keyed off `ctx.cwd`), leaving the foreign footer (`pi-powerline-footer`,
|
|
69
|
+
# `pi-bar`, or `@tombell/pi-status`) as the sole footer surface. `adapter: null`, no shim: for
|
|
70
|
+
# `pi-powerline-footer`/`pi-bar` perk's objective/checkpoints progress reaches the foreign footer
|
|
71
|
+
# automatically via the already-publishing composed `perk` `setStatus` slot (both render extension
|
|
72
|
+
# statuses), so the bridge is automatic; `@tombell/pi-status` is the exception (it does NOT render
|
|
73
|
+
# extension statuses — see the `pi-status-footer` note below).
|
|
74
|
+
# Fail-safe: any config-read error resolves to the reference id → perk installs its footer (the
|
|
75
|
+
# default path is the hard zero-change guarantee).
|
|
76
|
+
#
|
|
77
|
+
# Two more footer outcomes round out the catalog so the footer is governed EXCLUSIVELY by
|
|
78
|
+
# `[providers] footer` (no footer outcome ever needs a manual `packages` edit):
|
|
79
|
+
# - `pi-status-footer` (`npm:@tombell/pi-status`) is vacate-only like the two above, BUT — unlike
|
|
80
|
+
# `powerline-footer`/`pi-bar-footer` — pi-status does NOT render extension statuses, so perk's
|
|
81
|
+
# objective/checkpoints progress is NOT shown in the footer when it is selected. This is an
|
|
82
|
+
# accepted limitation (it matches what pi-status already does today); perk does not build a
|
|
83
|
+
# status-bridge adapter for it (it is a genuine interface seam).
|
|
84
|
+
# - `pi-default` (`package: null`) is the "install nothing / leave pi's stock built-in footer"
|
|
85
|
+
# option: perk vacates (gate false), convergence adds no package, so pi's own footer stands.
|
|
86
|
+
#
|
|
87
|
+
# The WEB seam is the THIRD INTERFACE seam (no durable artifact to bridge), but with a genuine
|
|
88
|
+
# novelty: it is the FIRST seam whose `default: true` provider has a NON-NULL `package`. perk owns
|
|
89
|
+
# no native web-research implementation, so the behavior-preserving reference (`pi-web-access`,
|
|
90
|
+
# zero-config Exa search + content fetch + the bundled `librarian` skill) is itself a foreign npm
|
|
91
|
+
# package. Selection simply SWAPS which web package the provider-convergence installs — `adapter:
|
|
92
|
+
# null`, no shim, and there is NO perk surface to vacate at registration time because perk registers
|
|
93
|
+
# NO web tools of its own. The read-only allowlist statically carries the UNION of all known web
|
|
94
|
+
# tool names (inert when absent); perk does NOT normalize tool names across providers. `librarian`
|
|
95
|
+
# is pi-web-access-specific (it depends on `fetch_content`'s GitHub-clone path) and is accepted as
|
|
96
|
+
# lost under a foreign web selection. Fail-safe: any config-read error resolves to `pi-web-access`,
|
|
97
|
+
# keeping today's behavior exactly.
|
|
98
|
+
|
|
99
|
+
schema_version: 1
|
|
100
|
+
|
|
101
|
+
providers:
|
|
102
|
+
- id: perk-plan # perk's own planMode/planSave over toolGating
|
|
103
|
+
seam: plan
|
|
104
|
+
package: null # null ⇒ perk's bundled reference provider (no foreign package)
|
|
105
|
+
adapter: null # null ⇒ no shim needed; perk produces the contract natively
|
|
106
|
+
default: true # the behavior-preserving no-config pick for the plan seam
|
|
107
|
+
- id: perk-checkpoints # perk's own checkpoints
|
|
108
|
+
seam: todo
|
|
109
|
+
package: null
|
|
110
|
+
adapter: null
|
|
111
|
+
default: true # the behavior-preserving no-config pick for the todo seam
|
|
112
|
+
- id: perk-ask-user # perk's own ask_user_question tool (extension/doors/askUser.ts)
|
|
113
|
+
seam: askuser
|
|
114
|
+
package: null
|
|
115
|
+
adapter: null
|
|
116
|
+
default: true # the behavior-preserving no-config pick for the askuser seam
|
|
117
|
+
|
|
118
|
+
# --- foreign entries ---
|
|
119
|
+
- id: tombell-plan # REAL plan provider (Node 2.3) — planAdapterTombell bridges it
|
|
120
|
+
seam: plan
|
|
121
|
+
package: "npm:@tombell/pi-plan" # the foreign Pi package to add to `packages`
|
|
122
|
+
adapter: "planAdapterTombell" # the perk-owned shim bridging surface → cache.plan-ref
|
|
123
|
+
default: false
|
|
124
|
+
# No `package_filter`: `@tombell/pi-plan`'s sole extension is its root `index.ts` (not under
|
|
125
|
+
# `extensions/`), so omitting the filter ("load all of that type") loads exactly that one
|
|
126
|
+
# extension. The `package_filter` field stays in the vocabulary for future providers.
|
|
127
|
+
- id: plannotator-plan # REAL plan provider — planAdapterPlannotator bridges its browser review
|
|
128
|
+
seam: plan
|
|
129
|
+
package: "npm:@plannotator/pi-extension" # the foreign Pi package to add to `packages`
|
|
130
|
+
adapter: "planAdapterPlannotator" # the perk-owned shim bridging plan_review → its event API
|
|
131
|
+
default: false
|
|
132
|
+
# AUGMENT posture (contrast with tombell-plan's REPLACE posture): plannotator does not replace
|
|
133
|
+
# perk's plan surface — perk's `/plan` command, authoring injection, and read-only gate STAY
|
|
134
|
+
# registered; perk skips only the two real registration collisions (`--plan` flag and the
|
|
135
|
+
# `Ctrl+Alt+P` shortcut, both of which plannotator also registers — duplicate flag/shortcut
|
|
136
|
+
# registration is the known potentially-fatal Pi behavior). The bridge is the model-callable
|
|
137
|
+
# `plan_review` tool (planAdapterPlannotator) → plannotator's `plannotator:request` plan-review
|
|
138
|
+
# event flow (its browser review UI). Saving stays the human-run `/plan-save`.
|
|
139
|
+
# No `package_filter`: `@plannotator/pi-extension`'s `pi.extensions` is `["./"]` (the sole
|
|
140
|
+
# extension is the package root), so omitting the filter loads exactly that one extension.
|
|
141
|
+
- id: juicesharp-todo # REAL todo provider (Node 3.2) — todoAdapterJuicesharp bridges it
|
|
142
|
+
seam: todo
|
|
143
|
+
package: "npm:@juicesharp/rpiv-todo" # the foreign Pi package to add to `packages`
|
|
144
|
+
adapter: "todoAdapterJuicesharp" # the perk-owned shim carrying progress discipline onto it
|
|
145
|
+
default: false
|
|
146
|
+
# No `package_filter`: `@juicesharp/rpiv-todo` is a single-concern checklist overlay, so omitting
|
|
147
|
+
# the filter ("load all of that type") loads its bundled extension. The smoke's manual half is the
|
|
148
|
+
# gate that no perk surface collides; a targeted `extensions` filter is a follow-up if one ever does.
|
|
149
|
+
- id: juicesharp-ask-user # REAL askuser provider — VACATE-ONLY (interface seam, no adapter)
|
|
150
|
+
seam: askuser
|
|
151
|
+
package: "npm:@juicesharp/rpiv-ask-user-question" # the foreign Pi package to add to `packages`
|
|
152
|
+
adapter: null # VACATE-ONLY: the foreign tool shares the exact name `ask_user_question`,
|
|
153
|
+
# so perk's `registerAskUser` registers NOTHING under this selection —
|
|
154
|
+
# there is no durable artifact to bridge (interface seam), and the
|
|
155
|
+
# foreign tool self-documents via its own `promptGuidelines`.
|
|
156
|
+
default: false
|
|
157
|
+
# No `package_filter`: the verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
|
|
158
|
+
# filter ("load all of that type") loads exactly that one extension — the same reasoning as the
|
|
159
|
+
# tombell-plan / juicesharp-todo entries.
|
|
160
|
+
- id: perk-footer # perk's own footer (extension/surfaces/surfaces.ts installPerkFooter)
|
|
161
|
+
seam: footer
|
|
162
|
+
package: null
|
|
163
|
+
adapter: null
|
|
164
|
+
default: true # the behavior-preserving no-config pick for the footer seam
|
|
165
|
+
- id: powerline-footer # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
|
|
166
|
+
seam: footer
|
|
167
|
+
package: "npm:pi-powerline-footer" # the foreign Pi package to add to `packages`
|
|
168
|
+
adapter: null # VACATE-ONLY: the footer produces no durable artifact (interface seam),
|
|
169
|
+
# and pi-powerline-footer already renders perk's `perk` setStatus slot in
|
|
170
|
+
# its extension_statuses segment, so the bridge is automatic (no shim).
|
|
171
|
+
default: false
|
|
172
|
+
# No `package_filter`: load the package's sole footer extension ("load all of that type").
|
|
173
|
+
- id: pi-bar-footer # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
|
|
174
|
+
seam: footer
|
|
175
|
+
package: "npm:pi-bar" # the foreign Pi package to add to `packages`
|
|
176
|
+
adapter: null # VACATE-ONLY: pi-bar replaces pi's footer and "keeps extension statuses
|
|
177
|
+
# visible", so perk's `perk` setStatus slot appears automatically — no shim.
|
|
178
|
+
default: false
|
|
179
|
+
# No `package_filter`: load the package's sole footer extension ("load all of that type").
|
|
180
|
+
- id: pi-status-footer # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
|
|
181
|
+
seam: footer
|
|
182
|
+
package: "npm:@tombell/pi-status" # the foreign Pi package to add to `packages`
|
|
183
|
+
adapter: null # VACATE-ONLY: the footer produces no durable artifact (interface seam).
|
|
184
|
+
# UNLIKE powerline/pi-bar, pi-status does NOT render extension statuses,
|
|
185
|
+
# so perk's objective/checkpoints progress is NOT shown in the footer
|
|
186
|
+
# under this selection (an accepted limitation — matches pi-status today;
|
|
187
|
+
# no status-bridge adapter is built).
|
|
188
|
+
default: false
|
|
189
|
+
# No `package_filter`: load the package's sole footer extension ("load all of that type").
|
|
190
|
+
- id: pi-default # "install nothing" footer provider — leaves pi's stock built-in footer
|
|
191
|
+
seam: footer
|
|
192
|
+
package: null # null ⇒ perk adds NO package; pi's own built-in footer stands.
|
|
193
|
+
adapter: null # VACATE-ONLY: perk's footer-install gate is false (resolved id ≠
|
|
194
|
+
# perk-footer), so perk skips installPerkFooter; nothing else to add.
|
|
195
|
+
default: false
|
|
196
|
+
- id: pi-web-access # web seam DEFAULT — the FOREIGN reference provider (perk owns no native web impl)
|
|
197
|
+
seam: web
|
|
198
|
+
package: "npm:pi-web-access" # NON-NULL default package: the novelty — perk has no native web provider
|
|
199
|
+
adapter: null # VACATE-ONLY interface seam: no durable artifact, and perk registers NO web
|
|
200
|
+
# tools, so there is no perk surface to vacate. Selection just swaps the package.
|
|
201
|
+
default: true # the behavior-preserving no-config pick (zero-config Exa search + `librarian`)
|
|
202
|
+
# No `package_filter`: `pi-web-access`'s sole extension is its root `./index.ts` (verified via
|
|
203
|
+
# `npm view pi-web-access pi`), so omitting the filter loads exactly that one extension.
|
|
204
|
+
- id: ollama-web-search # REAL web provider — VACATE-ONLY (interface seam, no adapter)
|
|
205
|
+
seam: web
|
|
206
|
+
package: "npm:@ollama/pi-web-search" # the foreign Pi package to add to `packages`
|
|
207
|
+
adapter: null # VACATE-ONLY: web is an interface seam (no artifact); perk registers no web
|
|
208
|
+
# tools, so nothing to vacate. Tools: `ollama_web_search`/`ollama_web_fetch`
|
|
209
|
+
# (needs a local Ollama daemon). Divergent names — perk allowlists the union.
|
|
210
|
+
default: false
|
|
211
|
+
# No `package_filter`: verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
|
|
212
|
+
# filter loads exactly that one extension.
|
|
213
|
+
- id: juicesharp-web-tools # REAL web provider — VACATE-ONLY (interface seam, no adapter)
|
|
214
|
+
seam: web
|
|
215
|
+
package: "npm:@juicesharp/rpiv-web-tools" # the foreign Pi package to add to `packages`
|
|
216
|
+
adapter: null # VACATE-ONLY: interface seam, no artifact; perk registers no web tools.
|
|
217
|
+
# Tools: `web_search`/`web_fetch` (needs an API key; default provider Brave;
|
|
218
|
+
# registers a `/web-tools` command — no perk collision).
|
|
219
|
+
default: false
|
|
220
|
+
# No `package_filter`: verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
|
|
221
|
+
# filter loads exactly that one extension (the juicesharp single-extension convention).
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# perk stage registry — the language-neutral contract both planes read (Q4/Q6).
|
|
2
|
+
#
|
|
3
|
+
# Authored once here, bundled into each build artifact (wheel -> perk/_shared/,
|
|
4
|
+
# npm tarball -> shared/), and parsed directly by both planes at runtime: the
|
|
5
|
+
# Python CLI generates its subcommands from it (T4); the TS extension drives its
|
|
6
|
+
# in-session transitions from it (Phase 1+). No codegen step (Q6).
|
|
7
|
+
#
|
|
8
|
+
# T2 locks the descriptor *shape*, the stage *graph*, and the state-key
|
|
9
|
+
# *vocabulary*. The drift-prone per-stage state I/O (`requires`/`reads`/`writes`)
|
|
10
|
+
# is left empty and filled as each handler lands (Phase 1+) — locking the shape,
|
|
11
|
+
# not authoring fiction about unbuilt stages.
|
|
12
|
+
|
|
13
|
+
schema_version: 1
|
|
14
|
+
|
|
15
|
+
# ---------------------------------------------------------------------------
|
|
16
|
+
# State-key vocabulary (Q4). `requires`/`reads`/`writes` draw ONLY from these,
|
|
17
|
+
# written as dotted "<tier>.<key>" strings (e.g. "github.plan"). The self-check
|
|
18
|
+
# flattens this map to a set for membership validation.
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
state_keys:
|
|
21
|
+
# Tier 1 · GitHub — the canonical source of truth.
|
|
22
|
+
github:
|
|
23
|
+
- plan # the plan issue (header + body)
|
|
24
|
+
- objective # the objective issue (storage + mechanics live in P2.T9; its stage in T10)
|
|
25
|
+
- pr # the pull request
|
|
26
|
+
- labels # repo labels (e.g. perk:plan)
|
|
27
|
+
- comments # discussion comments
|
|
28
|
+
- review-threads # review threads (distinct API from comments)
|
|
29
|
+
- learn # the perk:learn knowledge-capture issue (P2.T8b)
|
|
30
|
+
# Tier 2 · .pi/workflow/ — the local cache (see contracts.md §8.1).
|
|
31
|
+
cache:
|
|
32
|
+
- plan # materialized plan body cache
|
|
33
|
+
- plan-ref # provider-agnostic plan->branch ref (see contracts.md §8.4)
|
|
34
|
+
- scratch # per-run inter-process workflow files
|
|
35
|
+
- handoff # pre-session CLI->extension cold-door state
|
|
36
|
+
- markers # existence-based friction semaphores (e.g. pending-learn)
|
|
37
|
+
- session-data # the run-scoped session data dir artifacts (scratch/runs/<run_id>/data/; #339 Node 2.1)
|
|
38
|
+
# Tier 3 · session entries — transient in-session state.
|
|
39
|
+
session:
|
|
40
|
+
- workflow-state # the single `perk:workflow-state` record (contracts.md §8.3)
|
|
41
|
+
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
# Stages — the loop (Q5): objective-author -> objective-save -> objective-plan -> plan ->
|
|
44
|
+
# save -> implement -> submit -> address -> land -> learn.
|
|
45
|
+
#
|
|
46
|
+
# Every field is locked EXCEPT `requires`/`reads`/`writes` (empty until handlers
|
|
47
|
+
# land). `run_id` is uniform AND shape-locked by the validator: `perk/substrate/registry.py`
|
|
48
|
+
# `_check_doors_and_run_id` enforces `warm == keep` and `cold_local`/`cold_remote == mint`
|
|
49
|
+
# for every stage (Q2). It is a shape-locked map, NOT free per-stage data — the field is kept
|
|
50
|
+
# because the shape is the contract, not because stages vary.
|
|
51
|
+
# `command` is the human/contract LABEL for the stage's command, not the routing table: the
|
|
52
|
+
# actual dedicated cold-door routing lives in code via `perk/cli/stages.py` `DEDICATED_STAGES`
|
|
53
|
+
# (the generic launcher generator skips those ids). The field documents intent; it does not route.
|
|
54
|
+
# `doors.cold_remote` records which stages a remote runner may run (cli-vs-pi §4.5) —
|
|
55
|
+
# a real registry-recorded constraint, not merely "not built yet". P2.T8c flips it
|
|
56
|
+
# `true` on `implement` + `address` (the agentic, headless-runnable stages a Phase-3 CI
|
|
57
|
+
# worker drives); `plan`/`save` need interactive local exploration and
|
|
58
|
+
# `submit`/`land`/`learn` are quick deterministic ops, so they stay `false`. Phase 2
|
|
59
|
+
# *builds + resolves* the target (the resolver + this door + the --json descriptor);
|
|
60
|
+
# Phase 3 *drives* it. Revisable in Phase 3.
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
stages:
|
|
63
|
+
- id: objective-author
|
|
64
|
+
summary: Draft a new objective + roadmap (read-only authoring).
|
|
65
|
+
mode: read-only
|
|
66
|
+
worktree: none # interactive authoring, like plan — no branch, no objective yet
|
|
67
|
+
doors: { warm: true, cold_local: true, cold_remote: false } # interactive local authoring
|
|
68
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
69
|
+
command: objective author # P3.T2: dedicated seeded cold door (perk objective author)
|
|
70
|
+
requires: [] # nothing exists yet — this stage CREATES the objective
|
|
71
|
+
reads: []
|
|
72
|
+
writes: [session.workflow-state, cache.session-data] # the read-only `mode` append (the gate toggle); #352 Node 2.1: objective_draft writes the objective-draft artifact + its session_artifacts pointer
|
|
73
|
+
predecessors: [] # the new single initial (authoring precedes everything)
|
|
74
|
+
successors: [objective-save]
|
|
75
|
+
|
|
76
|
+
- id: objective-save
|
|
77
|
+
summary: Persist the drafted objective to GitHub; the read-only -> read-write boundary.
|
|
78
|
+
mode: read-write
|
|
79
|
+
worktree: none # still no branch; save writes the objective issue
|
|
80
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
81
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
82
|
+
command: objective save # P3.T2: the objective_save terminating tool + /objective-save command
|
|
83
|
+
requires: []
|
|
84
|
+
reads: []
|
|
85
|
+
writes: [github.objective, session.workflow-state] # create the objective issue; link active_objective
|
|
86
|
+
predecessors: [objective-author]
|
|
87
|
+
successors: [objective-plan]
|
|
88
|
+
|
|
89
|
+
- id: objective-plan
|
|
90
|
+
summary: Select the next objective node and author a bounded plan (read-only).
|
|
91
|
+
mode: read-only
|
|
92
|
+
worktree: none # interactive planning, like plan — no branch yet
|
|
93
|
+
doors: { warm: true, cold_local: true, cold_remote: false } # interactive local exploration
|
|
94
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
95
|
+
command: objective plan # P2.T10: dedicated cold door (perk objective plan) + /objective-plan
|
|
96
|
+
requires: [github.objective] # an objective issue must exist
|
|
97
|
+
reads: [github.objective] # roadmap nodes + next-node selection
|
|
98
|
+
writes: [github.objective, session.workflow-state, cache.session-data] # mark node planning; set active_objective; #339 Node 2.1: plan_draft writes the working-plan artifact + its session_artifacts pointer
|
|
99
|
+
predecessors: [objective-save] # P3.T2: objective-save now precedes planning
|
|
100
|
+
successors: [plan]
|
|
101
|
+
|
|
102
|
+
- id: plan
|
|
103
|
+
summary: Explore the codebase and draft a plan (read-only).
|
|
104
|
+
mode: read-only
|
|
105
|
+
worktree: none # no implementation branch exists yet
|
|
106
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
107
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
108
|
+
command: plan # slash = /plan (perk-owned P2.T2a; toggles the read-only tool gate)
|
|
109
|
+
requires: []
|
|
110
|
+
reads: []
|
|
111
|
+
writes: [session.workflow-state, cache.session-data] # P2.T2a: /plan enter/exit appends `mode`; #339 Node 2.1: plan_draft writes the working-plan artifact + its session_artifacts pointer
|
|
112
|
+
predecessors: [objective-plan] # P2.T10: objective-plan is the new single initial
|
|
113
|
+
successors: [save]
|
|
114
|
+
|
|
115
|
+
- id: save
|
|
116
|
+
summary: Persist the plan to GitHub; the read-only -> read-write boundary.
|
|
117
|
+
mode: read-write
|
|
118
|
+
worktree: none # still no branch; save writes the plan issue + ref
|
|
119
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
120
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
121
|
+
command: plan save # cold: the merged `perk plan save` door (Node 3.2); warm twin: the plan_save tool + /plan-save command
|
|
122
|
+
requires: []
|
|
123
|
+
reads: []
|
|
124
|
+
writes: [github.plan, cache.plan-ref, session.workflow-state] # T2a: plan issue; T2b: plan-ref pointer; T3: warm door appends active_plan_ref
|
|
125
|
+
predecessors: [plan]
|
|
126
|
+
successors: [implement]
|
|
127
|
+
|
|
128
|
+
- id: implement
|
|
129
|
+
summary: Do the work on a branch (requires fresh context; cold-only).
|
|
130
|
+
mode: read-write
|
|
131
|
+
worktree: create # first stage that needs a branch/worktree (folds in erk's `prepare`)
|
|
132
|
+
doors: { warm: false, cold_local: true, cold_remote: true } # P2.T8c: a Phase-3 CI worker can run it
|
|
133
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
134
|
+
command: implement
|
|
135
|
+
requires: [cache.plan-ref] # T4: cold door derives plan-<pr_id> from the active ref
|
|
136
|
+
reads: [cache.plan-ref] # T4: positions the worktree from the ref (agent reads github.plan)
|
|
137
|
+
writes: [session.workflow-state] # T4: the worktree session links active_plan_ref on session_start
|
|
138
|
+
predecessors: [save]
|
|
139
|
+
successors: [submit]
|
|
140
|
+
|
|
141
|
+
- id: submit
|
|
142
|
+
summary: Push the branch and open a draft PR.
|
|
143
|
+
mode: read-write
|
|
144
|
+
worktree: reuse
|
|
145
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
146
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
147
|
+
command: pr submit
|
|
148
|
+
requires: [cache.plan-ref] # T5a: reads the active ref to derive the branch
|
|
149
|
+
reads: [cache.plan-ref, github.plan] # T5a: ref -> branch; plan issue title for the PR
|
|
150
|
+
writes: [github.pr, github.plan] # T5a: open the draft PR; populate staged branch/pr header
|
|
151
|
+
predecessors: [implement]
|
|
152
|
+
successors: [address]
|
|
153
|
+
|
|
154
|
+
- id: address
|
|
155
|
+
summary: Classify PR review feedback (isolated child) and resolve the threads.
|
|
156
|
+
mode: read-write
|
|
157
|
+
worktree: reuse
|
|
158
|
+
doors: { warm: true, cold_local: true, cold_remote: true } # P2.T8c: a Phase-3 CI worker can run it
|
|
159
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
160
|
+
command: pr address
|
|
161
|
+
# P2.T7: a spawned read-only child (borrowed pi-subagents) fetches + classifies feedback;
|
|
162
|
+
# the parent fixes only actionable items and batch-resolves the threads (`resolve_review_threads`).
|
|
163
|
+
requires: [github.pr] # the PR whose feedback we address
|
|
164
|
+
reads: [cache.plan-ref, github.pr, github.review-threads, github.comments]
|
|
165
|
+
writes: [github.review-threads, github.comments, github.pr, session.workflow-state]
|
|
166
|
+
predecessors: [submit]
|
|
167
|
+
successors: [land]
|
|
168
|
+
|
|
169
|
+
- id: land
|
|
170
|
+
summary: Merge the ready/approved PR and reconcile; sets the pending-learn marker.
|
|
171
|
+
mode: read-write
|
|
172
|
+
worktree: reuse
|
|
173
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
174
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
175
|
+
command: pr land
|
|
176
|
+
requires: [github.pr] # T5b: the PR to merge must exist
|
|
177
|
+
reads: [cache.plan-ref, github.pr, github.objective] # T5b ref->branch->PR; T11a node lookup
|
|
178
|
+
writes: [github.pr, cache.markers, github.objective] # T5b merge+marker; T11a mechanical node-done
|
|
179
|
+
predecessors: [address]
|
|
180
|
+
successors: [learn]
|
|
181
|
+
|
|
182
|
+
- id: learn
|
|
183
|
+
summary: Capture learnings from the landed run; clears the pending-learn marker.
|
|
184
|
+
mode: read-write
|
|
185
|
+
worktree: reuse # pending-learn blocks worktree deletion until this runs (Q5)
|
|
186
|
+
doors: { warm: true, cold_local: true, cold_remote: false }
|
|
187
|
+
run_id: { warm: keep, cold_local: mint, cold_remote: mint }
|
|
188
|
+
command: learn
|
|
189
|
+
# P2.T8b: deepened from a thin marker-clear into a real knowledge-capture pass — with a
|
|
190
|
+
# summary, create a perk:learn issue (idempotent via the perk:learn-scoped find_learn_issue) +
|
|
191
|
+
# back-link comment, then clear pending-learn; without one, the thin marker-clear (no issue).
|
|
192
|
+
# P2.T17: now launches PRIMED (launch.py _learn_prompt) — the cold session opens investigating
|
|
193
|
+
# the landed change; bare warm /learn injects perk-learn guidance (interactive). No new I/O
|
|
194
|
+
# keys (no new gateway op) — the existing learn tool / learn capture worker still persist.
|
|
195
|
+
requires: [cache.markers] # pending-learn gates the worktree
|
|
196
|
+
reads: [cache.markers, cache.plan-ref] # was it set? + the plan ref -> issue number/run_id
|
|
197
|
+
writes: [cache.markers, github.learn, github.comments] # clear marker; create learn issue + back-link
|
|
198
|
+
predecessors: [land]
|
|
199
|
+
successors: []
|