@mgiles/perk 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +1 -1
  2. package/extension/adapters/planAdapterPlannotator.ts +132 -91
  3. package/extension/adapters/planAdapterTombell.ts +5 -3
  4. package/extension/doors/address.ts +235 -37
  5. package/extension/doors/annotationPush.ts +924 -0
  6. package/extension/doors/auditWaveTools.ts +352 -0
  7. package/extension/doors/ciExecutor.ts +220 -55
  8. package/extension/doors/draftReviewWaveTools.ts +384 -0
  9. package/extension/doors/harvestWaveTools.ts +279 -0
  10. package/extension/doors/land.ts +1 -0
  11. package/extension/doors/learn.ts +238 -24
  12. package/extension/doors/learnFactory.ts +33 -7
  13. package/extension/doors/lifecycleGates.ts +1 -1
  14. package/extension/doors/objectiveReviewBrowser.ts +514 -0
  15. package/extension/doors/objectiveStack.ts +1143 -0
  16. package/extension/doors/planReviewBrowser.ts +453 -0
  17. package/extension/doors/plannotatorHandoff.ts +120 -49
  18. package/extension/doors/prReview.ts +203 -22
  19. package/extension/doors/prReviewBrowser.ts +31 -23
  20. package/extension/doors/prReviewDynamic.ts +256 -0
  21. package/extension/doors/prReviewTerminal.ts +6 -11
  22. package/extension/doors/reviewWaveTools.ts +374 -0
  23. package/extension/doors/selfcheck.ts +1 -1
  24. package/extension/doors/submit.ts +86 -10
  25. package/extension/factories/gistAuthor.ts +4 -4
  26. package/extension/factories/gistDraft.ts +1 -1
  27. package/extension/factories/gistSave.ts +2 -2
  28. package/extension/factories/objective.ts +7 -7
  29. package/extension/factories/objectiveAuthor.ts +5 -4
  30. package/extension/factories/objectiveDraft.ts +61 -6
  31. package/extension/factories/objectivePlan.ts +163 -8
  32. package/extension/factories/objectiveSave.ts +16 -1
  33. package/extension/factories/planMode.ts +5 -3
  34. package/extension/factories/planReview.ts +131 -36
  35. package/extension/factories/planTitle.ts +27 -9
  36. package/extension/hunkFeedback/inbox.ts +389 -0
  37. package/extension/hunkFeedback/perkFeedback.ts +364 -0
  38. package/extension/hunkFeedback/receiver.ts +296 -0
  39. package/extension/hunkFeedback/store.ts +533 -0
  40. package/extension/index.ts +116 -44
  41. package/extension/substrate/cache.ts +75 -22
  42. package/extension/substrate/coldDoor.ts +2 -3
  43. package/extension/substrate/config.ts +42 -14
  44. package/extension/substrate/git.ts +10 -0
  45. package/extension/substrate/providers.ts +4 -33
  46. package/extension/substrate/resources.ts +11 -0
  47. package/extension/substrate/result.ts +13 -5
  48. package/extension/substrate/sessionData.ts +3 -3
  49. package/extension/substrate/sessionPointers.ts +3 -3
  50. package/extension/substrate/structuredOutput.ts +78 -19
  51. package/extension/substrate/terminalLaunch.ts +1 -1
  52. package/extension/substrate/toolGating.ts +206 -26
  53. package/extension/substrate/workflowState.ts +6 -0
  54. package/extension/surfaces/footerProvider.ts +6 -6
  55. package/extension/surfaces/surfaces.ts +98 -282
  56. package/extension/vendor/btw/btw.ts +57 -12
  57. package/extension/waves/adversarialReviewWave.ts +164 -0
  58. package/extension/waves/auditWave.ts +312 -0
  59. package/extension/waves/draftReviewWave.ts +189 -0
  60. package/extension/waves/harvestWave.ts +399 -0
  61. package/extension/waves/learnWave.ts +155 -0
  62. package/extension/waves/memoryAdapter.ts +139 -0
  63. package/extension/waves/objectiveExplorerWave.ts +120 -0
  64. package/extension/waves/prReviewDynamicWave.ts +696 -0
  65. package/extension/waves/prReviewWave.ts +274 -0
  66. package/extension/waves/reportWave.ts +749 -0
  67. package/extension/waves/reviewClassifierWave.ts +109 -0
  68. package/extension/waves/rpcAdapter.ts +264 -0
  69. package/extension/worker/readOnlySession.ts +3 -3
  70. package/extension/worker/worker.ts +71 -93
  71. package/extension/workerMain.ts +4 -6
  72. package/package.json +20 -5
  73. package/prompts/README.md +19 -0
  74. package/prompts/_fixtures/live.yaml +71 -72
  75. package/prompts/common/resume-advisory.md +1 -0
  76. package/prompts/contexts/adapters/plannotator-gist.md +13 -0
  77. package/prompts/contexts/adapters/plannotator-objective.md +1 -2
  78. package/prompts/contexts/adapters/plannotator-plan.md +1 -2
  79. package/prompts/contexts/gist-authoring.md +6 -20
  80. package/prompts/contexts/objective-authoring.md +6 -18
  81. package/prompts/stages/address/action.md +4 -4
  82. package/prompts/stages/address/preview.md +3 -3
  83. package/prompts/stages/audit.md +18 -0
  84. package/prompts/stages/conflict-resolution.md +1 -1
  85. package/prompts/stages/gist-author/seed.md +4 -4
  86. package/prompts/stages/gist-save.md +1 -1
  87. package/prompts/stages/implement.md +3 -1
  88. package/prompts/stages/learn-code.md +1 -1
  89. package/prompts/stages/learn-docs.md +2 -2
  90. package/prompts/stages/learn-harvest.md +15 -0
  91. package/prompts/stages/learn-orchestrate.md +7 -5
  92. package/prompts/stages/objective-author/adopt.md +5 -3
  93. package/prompts/stages/objective-author/file.md +5 -4
  94. package/prompts/stages/objective-author/seed.md +5 -4
  95. package/prompts/stages/objective-land.md +7 -0
  96. package/prompts/stages/objective-plan/guidance.md +2 -2
  97. package/prompts/stages/objective-plan/seed.md +5 -1
  98. package/prompts/stages/objective-recover.md +8 -0
  99. package/prompts/stages/objective-replan.md +4 -2
  100. package/prompts/stages/objective-review-browser.md +9 -0
  101. package/prompts/stages/objective-sync.md +6 -0
  102. package/prompts/stages/plan-from/adopt.md +2 -2
  103. package/prompts/stages/plan-from/file.md +2 -2
  104. package/prompts/stages/plan-review-browser.md +9 -0
  105. package/prompts/stages/pr-review-browser/active.md +6 -6
  106. package/prompts/stages/pr-review-browser/foreign.md +6 -6
  107. package/prompts/stages/pr-review-dynamic.md +7 -0
  108. package/prompts/stages/pr-review-terminal/active.md +7 -7
  109. package/prompts/stages/pr-review-terminal/foreign.md +7 -7
  110. package/prompts/stages/pr-review.md +7 -6
  111. package/prompts/stages/replan.md +3 -3
  112. package/shared/README.md +2 -2
  113. package/shared/bindings.yaml +15 -0
  114. package/shared/contracts-history.md +11 -0
  115. package/shared/contracts.md +3713 -227
  116. package/shared/providers.yaml +27 -60
  117. package/shared/registry.yaml +32 -8
  118. package/shared/schemas/outputs/objective-doctor.schema.json +449 -0
  119. package/shared/schemas/outputs/objective-stack-land.schema.json +732 -0
  120. package/shared/schemas/outputs/objective-stack-recover.schema.json +397 -0
  121. package/shared/schemas/outputs/objective-stack-status.schema.json +577 -0
  122. package/shared/schemas/outputs/objective-stack-sync.schema.json +184 -0
  123. package/shared/schemas/outputs/plan-save.schema.json +12 -0
  124. package/shared/schemas/outputs/pr-submit.schema.json +177 -1
  125. package/extension/adapters/todoAdapterJuicesharp.ts +0 -102
  126. package/extension/checkpoints/checkpoints.ts +0 -550
  127. package/extension/checkpoints/planSteps.ts +0 -108
  128. package/extension/doors/askUser.ts +0 -198
  129. package/prompts/contexts/adapters/juicesharp-todo.md +0 -7
@@ -16,7 +16,7 @@
16
16
  # id — the stable provider id. NOT the cache.plan-ref `provider` string:
17
17
  # that field is the ISSUE BACKEND (the stamped `backend_id`, e.g.
18
18
  # "github"), not the seam id — see contracts.md §8.10 / §8.21.
19
- # seam — `plan` | `todo` | `askuser` | `footer` | `web` (the five seams; see
19
+ # seam — `plan` | `footer` | `web` (the three seams; see
20
20
  # pluggability-taxonomy.md for the scope fence).
21
21
  # package — the foreign Pi package spec added to .pi/settings.json `packages`
22
22
  # (e.g. "npm:@tombell/pi-plan"); `null` for perk's own bundled reference
@@ -25,7 +25,7 @@
25
25
  # a FOREIGN package because perk owns no native web implementation — its
26
26
  # `default: true` entry carries a non-null `package` (the documented exception).
27
27
  # adapter — the perk-owned shim module that bridges the foreign surface to the
28
- # artifact boundary (cache.plan-ref / perk:checkpoint); `null` for the
28
+ # artifact boundary (cache.plan-ref); `null` for the
29
29
  # reference provider.
30
30
  # default — exactly ONE `true` per seam: the behavior-preserving no-config pick.
31
31
  # package_filter — optional Pi object-form filter (extensions/skills/… arrays)
@@ -39,38 +39,23 @@
39
39
  # name a provider that exists / has the right seam? — are `doctor`'s job, NOT the
40
40
  # loaders. The Python plane is the authoritative validator.
41
41
  #
42
- # Status (Node 2.1 → 3.2): this file ships the substrate (the three reference entries +
43
- # foreign entries per seam), and ALL THREE seams now have a REAL foreign provider. The PLAN
44
- # adapter landed at Node 2.3: `tombell-plan` is a REAL, selectable plan provider —
45
- # `planAdapterTombell` bridges `@tombell/pi-plan`'s free-form prose surface to perk's
46
- # canonical `plan_save` → `cache.plan-ref` contract, and perk VACATES the plan surface at
42
+ # Status: this file ships the substrate (the reference entries + foreign entries per seam), and
43
+ # every seam has a REAL foreign provider. The PLAN adapter: `tombell-plan` is a REAL, selectable
44
+ # plan provider `planAdapterTombell` bridges `@tombell/pi-plan`'s free-form prose surface to
45
+ # perk's canonical `plan_save` `cache.plan-ref` contract, and perk VACATES the plan surface at
47
46
  # REGISTRATION time (not just handler-time) under a foreign plan selection so the foreign
48
47
  # `/plan`/`Ctrl+Alt+P`/`--plan` are the sole registrants (Pi suffixes duplicate command
49
- # names). The TODO adapter landed at Node 3.2: `juicesharp-todo` is a REAL, selectable todo
50
- # provider — `todoAdapterJuicesharp` carries perk's implement-progress discipline onto
51
- # `@juicesharp/rpiv-todo`'s checklist overlay (injection-only, active-workflow-gated), and
52
- # perk's own checkpoints simply DEFER at runtime (Node 3.1) — NO registration-time vacating,
53
- # because the todo seam has no command-name collision (`/checkpoints` vs the overlay's own
54
- # command). The DEFAULT path (the reference providers) is the hard guarantee.
48
+ # names). The DEFAULT path (the reference providers) is the hard guarantee.
55
49
  #
56
- # The ASKUSER seam is an INTERFACE seam (no durable artifact to bridge): its stable contract is
57
- # the tool NAME `ask_user_question` plus its non-terminating-answer semantics. `juicesharp-ask-user`
58
- # (`@juicesharp/rpiv-ask-user-question`) registers a tool with the IDENTICAL name, and tools
59
- # (unlike commands) do NOT get `:N` suffixes — a same-named tool replaces/warns by extension load
60
- # order. So the adapter is VACATE-ONLY (`adapter: null`, no shim, no injected context): under a
61
- # foreign askuser selection perk's `registerAskUser` registers NOTHING at REGISTRATION time,
62
- # leaving exactly one `ask_user_question` standing. Under the default (`perk-ask-user`) the foreign
63
- # package is never installed, so perk's tool is the sole registrant.
64
- #
65
- # The FOOTER seam is the SECOND INTERFACE seam (no durable artifact to bridge), mirroring askuser
66
- # but with INSTALL-SITE (runtime) vacating rather than registration-time vacating: perk installs
50
+ # The FOOTER seam is one of the TWO INTERFACE seams (with web; no durable artifact to bridge),
51
+ # vacated at the INSTALL SITE (runtime) rather than registration time: perk installs
67
52
  # its own footer (`installPerkFooter`) inside the `session_start` event handler, so under a foreign
68
53
  # `[providers] footer` selection perk simply does NOT call `installPerkFooter` (a runtime guard at
69
54
  # that single install site, keyed off `ctx.cwd`), leaving the foreign footer (`pi-powerline-footer`,
70
55
  # `pi-bar`, or `@tombell/pi-status`) as the sole footer surface. `adapter: null`, no shim: for
71
- # `pi-powerline-footer`/`pi-bar` perk's objective/checkpoints progress reaches the foreign footer
72
- # automatically via the already-publishing composed `perk` `setStatus` slot (both render extension
73
- # statuses), so the bridge is automatic; `@tombell/pi-status` is the exception (it does NOT render
56
+ # `pi-powerline-footer`/`pi-bar` perk's objective progress reaches the foreign footer
57
+ # automatically via the already-publishing single-value `perk` `setStatus` slot (both render
58
+ # extension statuses), so the bridge is automatic; `@tombell/pi-status` is the exception (it does NOT render
74
59
  # extension statuses — see the `pi-status-footer` note below).
75
60
  # Fail-safe: any config-read error resolves to the reference id → perk installs its footer (the
76
61
  # default path is the hard zero-change guarantee).
@@ -79,14 +64,14 @@
79
64
  # `[providers] footer` (no footer outcome ever needs a manual `packages` edit):
80
65
  # - `pi-status-footer` (`npm:@tombell/pi-status`) is vacate-only like the two above, BUT — unlike
81
66
  # `powerline-footer`/`pi-bar-footer` — pi-status does NOT render extension statuses, so perk's
82
- # objective/checkpoints progress is NOT shown in the footer when it is selected. This is an
67
+ # objective progress is NOT shown in the footer when it is selected. This is an
83
68
  # accepted limitation (it matches what pi-status already does today); perk does not build a
84
69
  # status-bridge adapter for it (it is a genuine interface seam).
85
70
  # - `pi-default` (`package: null`) is the "install nothing / leave pi's stock built-in footer"
86
71
  # option: perk vacates (gate false), convergence adds no package, so pi's own footer stands.
87
72
  #
88
- # The WEB seam is the THIRD INTERFACE seam (no durable artifact to bridge), but with a genuine
89
- # novelty: it is the FIRST seam whose `default: true` provider has a NON-NULL `package`. perk owns
73
+ # The WEB seam is the OTHER INTERFACE seam (no durable artifact to bridge), but with a genuine
74
+ # novelty: it is the ONLY seam whose `default: true` provider has a NON-NULL `package`. perk owns
90
75
  # no native web-research implementation, so the behavior-preserving reference (`pi-web-access`,
91
76
  # zero-config Exa search + content fetch + the bundled `librarian` skill) is itself a foreign npm
92
77
  # package. Selection simply SWAPS which web package the provider-convergence installs — `adapter:
@@ -102,6 +87,17 @@
102
87
  # IS the surface pick). The hunk CLI converges unconditionally (init/doctor's best-effort
103
88
  # `review-cli` install/verify); the plannotator package rides the plan seam's `plannotator-plan`
104
89
  # entry.
90
+ #
91
+ # There is NO askuser seam anymore: it is RETIRED to a REQUIRED BORROW. After perk's first-party
92
+ # `ask_user_question` tool was deleted the seam had exactly one selectable provider — nothing to
93
+ # select (the borrow-vs-seam criterion) — so `ask_user_question` is now the borrowed
94
+ # `@juicesharp/rpiv-ask-user-question` questionnaire, installed for every repo via
95
+ # `BORROWED_PACKAGES` (convergence/init/settings.py).
96
+ #
97
+ # There is NO todo seam anymore: it is RETIRED to a REQUIRED BORROW. After the seam had exactly
98
+ # one selectable provider — nothing to select (the borrow-vs-seam criterion) — the checklist
99
+ # overlay became the borrowed `@juicesharp/rpiv-todo`, installed for every repo via
100
+ # `BORROWED_PACKAGES` (convergence/init/settings.py).
105
101
 
106
102
  schema_version: 1
107
103
 
@@ -111,16 +107,6 @@ providers:
111
107
  package: null # null ⇒ perk's bundled reference provider (no foreign package)
112
108
  adapter: null # null ⇒ no shim needed; perk produces the contract natively
113
109
  default: true # the behavior-preserving no-config pick for the plan seam
114
- - id: perk-checkpoints # perk's own checkpoints
115
- seam: todo
116
- package: null
117
- adapter: null
118
- default: true # the behavior-preserving no-config pick for the todo seam
119
- - id: perk-ask-user # perk's own ask_user_question tool (extension/doors/askUser.ts)
120
- seam: askuser
121
- package: null
122
- adapter: null
123
- default: true # the behavior-preserving no-config pick for the askuser seam
124
110
 
125
111
  # --- foreign entries ---
126
112
  - id: tombell-plan # REAL plan provider (Node 2.3) — planAdapterTombell bridges it
@@ -145,25 +131,6 @@ providers:
145
131
  # event flow (its browser review UI). Saving stays the human-run `/plan-save`.
146
132
  # No `package_filter`: `@plannotator/pi-extension`'s `pi.extensions` is `["./"]` (the sole
147
133
  # extension is the package root), so omitting the filter loads exactly that one extension.
148
- - id: juicesharp-todo # REAL todo provider (Node 3.2) — todoAdapterJuicesharp bridges it
149
- seam: todo
150
- package: "npm:@juicesharp/rpiv-todo" # the foreign Pi package to add to `packages`
151
- adapter: "todoAdapterJuicesharp" # the perk-owned shim carrying progress discipline onto it
152
- default: false
153
- # No `package_filter`: `@juicesharp/rpiv-todo` is a single-concern checklist overlay, so omitting
154
- # the filter ("load all of that type") loads its bundled extension. The smoke's manual half is the
155
- # gate that no perk surface collides; a targeted `extensions` filter is a follow-up if one ever does.
156
- - id: juicesharp-ask-user # REAL askuser provider — VACATE-ONLY (interface seam, no adapter)
157
- seam: askuser
158
- package: "npm:@juicesharp/rpiv-ask-user-question" # the foreign Pi package to add to `packages`
159
- adapter: null # VACATE-ONLY: the foreign tool shares the exact name `ask_user_question`,
160
- # so perk's `registerAskUser` registers NOTHING under this selection —
161
- # there is no durable artifact to bridge (interface seam), and the
162
- # foreign tool self-documents via its own `promptGuidelines`.
163
- default: false
164
- # No `package_filter`: the verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
165
- # filter ("load all of that type") loads exactly that one extension — the same reasoning as the
166
- # tombell-plan / juicesharp-todo entries.
167
134
  - id: perk-footer # perk's own footer (extension/surfaces/surfaces.ts installPerkFooter)
168
135
  seam: footer
169
136
  package: null
@@ -189,7 +156,7 @@ providers:
189
156
  package: "npm:@tombell/pi-status" # the foreign Pi package to add to `packages`
190
157
  adapter: null # VACATE-ONLY: the footer produces no durable artifact (interface seam).
191
158
  # UNLIKE powerline/pi-bar, pi-status does NOT render extension statuses,
192
- # so perk's objective/checkpoints progress is NOT shown in the footer
159
+ # so perk's objective progress is NOT shown in the footer
193
160
  # under this selection (an accepted limitation — matches pi-status today;
194
161
  # no status-bridge adapter is built).
195
162
  default: false
@@ -28,6 +28,7 @@ state_keys:
28
28
  - review-threads # review threads (distinct API from comments)
29
29
  - learn # the perk:learn knowledge-capture issue (P2.T8b)
30
30
  - gist # the perk:gist statement-of-intent issue (contracts.md §8.41)
31
+ - stack # the native stacked-PR resource (contracts.md §8.47)
31
32
  # Tier 2 · .perk/workflow/ — the local cache (see contracts.md §8.1).
32
33
  cache:
33
34
  - plan # materialized plan body cache
@@ -52,6 +53,11 @@ state_keys:
52
53
  # `_check_doors_and_run_id` enforces `warm == keep` and `cold_local`/`cold_remote == mint`
53
54
  # for every stage (Q2). It is a shape-locked map, NOT free per-stage data — the field is kept
54
55
  # because the shape is the contract, not because stages vary.
56
+ # `worktree` vocabulary (positioned by the one selector/positioner, `launch.resolve_worktree`
57
+ # — contracts.md §8.38): `none` = the invoking checkout; `create` = create the `plan-<id>`
58
+ # branch/worktree when missing (idempotent validated reuse when present); `reuse` = reuse a
59
+ # VALIDATED local checkout, or (learn excepted) restore the EXISTING `origin/plan-<id>` branch
60
+ # non-destructively when the checkout is missing — `reuse` never creates a new plan branch.
55
61
  # `command` is the human/contract LABEL for the stage's command, not the routing table: the
56
62
  # actual dedicated cold-door routing lives in code via `perk/cli/stages.py` `DEDICATED_STAGES`
57
63
  # (the generic launcher generator skips those ids). The field documents intent; it does not route.
@@ -175,23 +181,26 @@ stages:
175
181
  run_id: { warm: keep, cold_local: mint, cold_remote: mint }
176
182
  command: pr submit
177
183
  requires: [cache.plan-ref] # T5a: reads the active ref to derive the branch
178
- reads: [cache.plan-ref, github.plan] # T5a: ref -> branch; plan issue title for the PR
179
- writes: [github.pr, github.plan] # T5a: open the draft PR; populate staged branch/pr header
184
+ # Stacked route (§8.47): the delivery publish operation reads the objective (train +
185
+ # journal fold) and the native stack, and writes the journal (objective comments), the
186
+ # checkpoint pair (plan header), and the stack registration. Incremental touches neither.
187
+ reads: [cache.plan-ref, github.plan, github.objective, github.stack]
188
+ writes: [github.pr, github.plan, github.objective, github.stack]
180
189
  predecessors: [implement]
181
190
  successors: [address]
182
191
 
183
192
  - id: address
184
- summary: Classify PR review feedback (isolated child) and resolve the threads.
193
+ summary: Classify PR review feedback, publish committed fixes, then resolve the threads.
185
194
  mode: read-write
186
195
  worktree: reuse
187
196
  doors: { warm: true, cold_local: true, cold_remote: true } # bounded agentic stage — remotely runnable
188
197
  run_id: { warm: keep, cold_local: mint, cold_remote: mint }
189
198
  command: pr address
190
- # P2.T7: a spawned read-only child (borrowed pi-subagents) fetches + classifies feedback;
191
- # the parent fixes only actionable items and batch-resolves the threads (`resolve_review_threads`).
199
+ # The isolated child classifies; the parent fixes, then §8.52's finalizer routes through
200
+ # submit before resolving. The stacked route owns the objective journal + native stack.
192
201
  requires: [github.pr] # the PR whose feedback we address
193
- reads: [cache.plan-ref, github.pr, github.review-threads, github.comments]
194
- writes: [github.review-threads, github.comments, github.pr, session.workflow-state]
202
+ reads: [cache.plan-ref, github.plan, github.pr, github.review-threads, github.comments, github.objective, github.stack]
203
+ writes: [github.review-threads, github.comments, github.pr, github.plan, github.objective, github.stack, session.workflow-state]
195
204
  predecessors: [submit]
196
205
  successors: [land]
197
206
 
@@ -211,7 +220,9 @@ stages:
211
220
  - id: learn
212
221
  summary: Capture learnings from the landed run; clears the pending-learn marker.
213
222
  mode: read-write
214
- worktree: reuse # pending-learn blocks worktree deletion until this runs (Q5)
223
+ worktree: reuse # pending-learn blocks worktree deletion until this runs (Q5);
224
+ # learn NEVER restores a missing checkout (post-merge the remote
225
+ # branch is commonly gone; its session evidence is machine-local)
215
226
  doors: { warm: true, cold_local: true, cold_remote: false }
216
227
  run_id: { warm: keep, cold_local: mint, cold_remote: mint }
217
228
  command: learn
@@ -226,3 +237,16 @@ stages:
226
237
  writes: [cache.markers, github.learn, github.comments, github.plan] # clear marker; create learn issue + back-link; §8.36 learn_state header stamp
227
238
  predecessors: [land]
228
239
  successors: []
240
+
241
+ - id: audit
242
+ summary: Judge session-audit evidence packets via the auditor wave (dev-only door in perk-dev).
243
+ mode: read-only
244
+ worktree: none # runs in the invoking checkout; the one write is gitignored scratch
245
+ doors: { warm: false, cold_local: true, cold_remote: false }
246
+ run_id: { warm: keep, cold_local: mint, cold_remote: mint }
247
+ command: audit judge # label only — the dedicated cold door lives in perk-dev, not perk
248
+ requires: []
249
+ reads: []
250
+ writes: [session.workflow-state, cache.scratch] # the claim append; run_audit_wave writes <bundle>/verdicts.json under scratch
251
+ predecessors: [] # a deliberately isolated node — the dev-only audit component
252
+ successors: []
@@ -0,0 +1,449 @@
1
+ {
2
+ "$defs": {
3
+ "_DriftConditionOut": {
4
+ "additionalProperties": false,
5
+ "properties": {
6
+ "code": {
7
+ "title": "Code",
8
+ "type": "string"
9
+ },
10
+ "severity": {
11
+ "title": "Severity",
12
+ "type": "string"
13
+ },
14
+ "node_id": {
15
+ "anyOf": [
16
+ {
17
+ "type": "string"
18
+ },
19
+ {
20
+ "type": "null"
21
+ }
22
+ ],
23
+ "title": "Node Id"
24
+ },
25
+ "target": {
26
+ "anyOf": [
27
+ {
28
+ "type": "string"
29
+ },
30
+ {
31
+ "type": "null"
32
+ }
33
+ ],
34
+ "title": "Target"
35
+ },
36
+ "message": {
37
+ "title": "Message",
38
+ "type": "string"
39
+ },
40
+ "repairable": {
41
+ "title": "Repairable",
42
+ "type": "boolean"
43
+ }
44
+ },
45
+ "required": [
46
+ "code",
47
+ "severity",
48
+ "node_id",
49
+ "target",
50
+ "message",
51
+ "repairable"
52
+ ],
53
+ "title": "_DriftConditionOut",
54
+ "type": "object"
55
+ },
56
+ "_RepairActionOut": {
57
+ "additionalProperties": false,
58
+ "description": "One manifest repair action. ``error`` carries the write-failure message on the\n**failed** action only \u2014 the key is omitted entirely when ``None`` (contracts.md\n\u00a78.54's documented conditionality; the emission is byte-identical to the historical\nhand-built payload).",
59
+ "properties": {
60
+ "code": {
61
+ "title": "Code",
62
+ "type": "string"
63
+ },
64
+ "node_id": {
65
+ "anyOf": [
66
+ {
67
+ "type": "string"
68
+ },
69
+ {
70
+ "type": "null"
71
+ }
72
+ ],
73
+ "title": "Node Id"
74
+ },
75
+ "error": {
76
+ "anyOf": [
77
+ {
78
+ "type": "string"
79
+ },
80
+ {
81
+ "type": "null"
82
+ }
83
+ ],
84
+ "default": null,
85
+ "title": "Error"
86
+ }
87
+ },
88
+ "required": [
89
+ "code",
90
+ "node_id"
91
+ ],
92
+ "title": "_RepairActionOut",
93
+ "type": "object"
94
+ },
95
+ "_RepairResultOut": {
96
+ "additionalProperties": false,
97
+ "properties": {
98
+ "applied": {
99
+ "items": {
100
+ "$ref": "#/$defs/_RepairActionOut"
101
+ },
102
+ "title": "Applied",
103
+ "type": "array"
104
+ },
105
+ "failed": {
106
+ "anyOf": [
107
+ {
108
+ "$ref": "#/$defs/_RepairActionOut"
109
+ },
110
+ {
111
+ "type": "null"
112
+ }
113
+ ]
114
+ },
115
+ "remaining": {
116
+ "items": {
117
+ "$ref": "#/$defs/_DriftConditionOut"
118
+ },
119
+ "title": "Remaining",
120
+ "type": "array"
121
+ },
122
+ "aborted": {
123
+ "title": "Aborted",
124
+ "type": "boolean"
125
+ },
126
+ "dry_run": {
127
+ "title": "Dry Run",
128
+ "type": "boolean"
129
+ }
130
+ },
131
+ "required": [
132
+ "applied",
133
+ "failed",
134
+ "remaining",
135
+ "aborted",
136
+ "dry_run"
137
+ ],
138
+ "title": "_RepairResultOut",
139
+ "type": "object"
140
+ },
141
+ "_TrainDiagnosisOut": {
142
+ "additionalProperties": false,
143
+ "properties": {
144
+ "state": {
145
+ "title": "State",
146
+ "type": "string"
147
+ },
148
+ "objective_id": {
149
+ "title": "Objective Id",
150
+ "type": "string"
151
+ },
152
+ "redirected_from": {
153
+ "anyOf": [
154
+ {
155
+ "type": "string"
156
+ },
157
+ {
158
+ "type": "null"
159
+ }
160
+ ],
161
+ "title": "Redirected From"
162
+ },
163
+ "error_type": {
164
+ "anyOf": [
165
+ {
166
+ "type": "string"
167
+ },
168
+ {
169
+ "type": "null"
170
+ }
171
+ ],
172
+ "title": "Error Type"
173
+ },
174
+ "message": {
175
+ "anyOf": [
176
+ {
177
+ "type": "string"
178
+ },
179
+ {
180
+ "type": "null"
181
+ }
182
+ ],
183
+ "title": "Message"
184
+ },
185
+ "blockers": {
186
+ "items": {
187
+ "$ref": "#/$defs/_TrainFindingOut"
188
+ },
189
+ "title": "Blockers",
190
+ "type": "array"
191
+ },
192
+ "information": {
193
+ "items": {
194
+ "$ref": "#/$defs/_TrainFindingOut"
195
+ },
196
+ "title": "Information",
197
+ "type": "array"
198
+ }
199
+ },
200
+ "required": [
201
+ "state",
202
+ "objective_id",
203
+ "redirected_from",
204
+ "error_type",
205
+ "message",
206
+ "blockers",
207
+ "information"
208
+ ],
209
+ "title": "_TrainDiagnosisOut",
210
+ "type": "object"
211
+ },
212
+ "_TrainFindingOut": {
213
+ "additionalProperties": false,
214
+ "properties": {
215
+ "code": {
216
+ "title": "Code",
217
+ "type": "string"
218
+ },
219
+ "severity": {
220
+ "title": "Severity",
221
+ "type": "string"
222
+ },
223
+ "node_id": {
224
+ "anyOf": [
225
+ {
226
+ "type": "string"
227
+ },
228
+ {
229
+ "type": "null"
230
+ }
231
+ ],
232
+ "title": "Node Id"
233
+ },
234
+ "plan_id": {
235
+ "anyOf": [
236
+ {
237
+ "type": "string"
238
+ },
239
+ {
240
+ "type": "null"
241
+ }
242
+ ],
243
+ "title": "Plan Id"
244
+ },
245
+ "message": {
246
+ "title": "Message",
247
+ "type": "string"
248
+ },
249
+ "repairable": {
250
+ "title": "Repairable",
251
+ "type": "boolean"
252
+ },
253
+ "remediation": {
254
+ "anyOf": [
255
+ {
256
+ "type": "string"
257
+ },
258
+ {
259
+ "type": "null"
260
+ }
261
+ ],
262
+ "title": "Remediation"
263
+ }
264
+ },
265
+ "required": [
266
+ "code",
267
+ "severity",
268
+ "node_id",
269
+ "plan_id",
270
+ "message",
271
+ "repairable",
272
+ "remediation"
273
+ ],
274
+ "title": "_TrainFindingOut",
275
+ "type": "object"
276
+ },
277
+ "_TrainFixOut": {
278
+ "additionalProperties": false,
279
+ "properties": {
280
+ "state": {
281
+ "title": "State",
282
+ "type": "string"
283
+ },
284
+ "applied": {
285
+ "items": {
286
+ "$ref": "#/$defs/_TrainRepairActionOut"
287
+ },
288
+ "title": "Applied",
289
+ "type": "array"
290
+ },
291
+ "skipped": {
292
+ "items": {
293
+ "$ref": "#/$defs/_TrainRepairActionOut"
294
+ },
295
+ "title": "Skipped",
296
+ "type": "array"
297
+ },
298
+ "failed": {
299
+ "anyOf": [
300
+ {
301
+ "$ref": "#/$defs/_TrainRepairActionOut"
302
+ },
303
+ {
304
+ "type": "null"
305
+ }
306
+ ]
307
+ },
308
+ "remaining": {
309
+ "items": {
310
+ "$ref": "#/$defs/_TrainFindingOut"
311
+ },
312
+ "title": "Remaining",
313
+ "type": "array"
314
+ },
315
+ "aborted": {
316
+ "title": "Aborted",
317
+ "type": "boolean"
318
+ },
319
+ "dry_run": {
320
+ "title": "Dry Run",
321
+ "type": "boolean"
322
+ }
323
+ },
324
+ "required": [
325
+ "state",
326
+ "applied",
327
+ "skipped",
328
+ "failed",
329
+ "remaining",
330
+ "aborted",
331
+ "dry_run"
332
+ ],
333
+ "title": "_TrainFixOut",
334
+ "type": "object"
335
+ },
336
+ "_TrainRepairActionOut": {
337
+ "additionalProperties": false,
338
+ "properties": {
339
+ "code": {
340
+ "title": "Code",
341
+ "type": "string"
342
+ },
343
+ "node_id": {
344
+ "title": "Node Id",
345
+ "type": "string"
346
+ },
347
+ "outcome": {
348
+ "title": "Outcome",
349
+ "type": "string"
350
+ },
351
+ "error": {
352
+ "anyOf": [
353
+ {
354
+ "type": "string"
355
+ },
356
+ {
357
+ "type": "null"
358
+ }
359
+ ],
360
+ "title": "Error"
361
+ }
362
+ },
363
+ "required": [
364
+ "code",
365
+ "node_id",
366
+ "outcome",
367
+ "error"
368
+ ],
369
+ "title": "_TrainRepairActionOut",
370
+ "type": "object"
371
+ }
372
+ },
373
+ "additionalProperties": false,
374
+ "description": "The ``perk objective doctor --json`` report envelope (contracts.md \u00a78.54). Field\ndeclaration order is load-bearing (the machine surface's exact key order) \u2014 do not\nreorder. The failure envelope stays the shared ``fail(...)`` path.",
375
+ "properties": {
376
+ "success": {
377
+ "title": "Success",
378
+ "type": "boolean"
379
+ },
380
+ "error_type": {
381
+ "anyOf": [
382
+ {
383
+ "type": "string"
384
+ },
385
+ {
386
+ "type": "null"
387
+ }
388
+ ],
389
+ "title": "Error Type"
390
+ },
391
+ "objective": {
392
+ "title": "Objective",
393
+ "type": "string"
394
+ },
395
+ "drift": {
396
+ "items": {
397
+ "$ref": "#/$defs/_DriftConditionOut"
398
+ },
399
+ "title": "Drift",
400
+ "type": "array"
401
+ },
402
+ "fix": {
403
+ "anyOf": [
404
+ {
405
+ "$ref": "#/$defs/_RepairResultOut"
406
+ },
407
+ {
408
+ "type": "null"
409
+ }
410
+ ]
411
+ },
412
+ "redirected_from": {
413
+ "anyOf": [
414
+ {
415
+ "type": "string"
416
+ },
417
+ {
418
+ "type": "null"
419
+ }
420
+ ],
421
+ "title": "Redirected From"
422
+ },
423
+ "train": {
424
+ "$ref": "#/$defs/_TrainDiagnosisOut"
425
+ },
426
+ "train_fix": {
427
+ "anyOf": [
428
+ {
429
+ "$ref": "#/$defs/_TrainFixOut"
430
+ },
431
+ {
432
+ "type": "null"
433
+ }
434
+ ]
435
+ }
436
+ },
437
+ "required": [
438
+ "success",
439
+ "error_type",
440
+ "objective",
441
+ "drift",
442
+ "fix",
443
+ "redirected_from",
444
+ "train",
445
+ "train_fix"
446
+ ],
447
+ "title": "ObjectiveDoctorOut",
448
+ "type": "object"
449
+ }