@mgiles/perk 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -57
- package/extension/adapters/planAdapterPlannotator.ts +27 -41
- package/extension/adapters/planAdapterTombell.ts +15 -28
- package/extension/adapters/todoAdapterJuicesharp.ts +10 -13
- package/extension/checkpoints/checkpoints.ts +21 -13
- package/extension/doors/address.ts +6 -5
- package/extension/doors/askUser.ts +12 -8
- package/extension/doors/ciExecutor.ts +23 -15
- package/extension/doors/hunkHandoff.ts +202 -0
- package/extension/doors/land.ts +33 -10
- package/extension/doors/learn.ts +240 -34
- package/extension/doors/learnFactory.ts +144 -0
- package/extension/doors/lifecycleGates.ts +2 -1
- package/extension/doors/plannotatorHandoff.ts +509 -0
- package/extension/doors/prReview.ts +22 -37
- package/extension/doors/prReviewBrowser.ts +341 -0
- package/extension/doors/prReviewTerminal.ts +267 -0
- package/extension/doors/ready.ts +2 -1
- package/extension/doors/selfcheck.ts +240 -6
- package/extension/doors/submit.ts +37 -19
- package/extension/doors/submitPrReview.ts +408 -0
- package/extension/factories/implementHere.ts +116 -0
- package/extension/factories/objective.ts +17 -6
- package/extension/factories/objectiveAuthor.ts +15 -32
- package/extension/factories/objectiveDraft.ts +1 -1
- package/extension/factories/objectivePlan.ts +16 -34
- package/extension/factories/objectiveSave.ts +7 -17
- package/extension/factories/planMode.ts +24 -38
- package/extension/factories/planReview.ts +291 -177
- package/extension/factories/planSave.ts +23 -8
- package/extension/index.ts +117 -20
- package/extension/substrate/bindingDelivery.ts +32 -10
- package/extension/substrate/bindings.ts +4 -2
- package/extension/substrate/cache.ts +36 -9
- package/extension/substrate/clipboard.ts +81 -0
- package/extension/substrate/command.ts +25 -0
- package/extension/substrate/config.ts +98 -76
- package/extension/substrate/consoleCapture.ts +90 -0
- package/extension/substrate/git.ts +77 -0
- package/extension/substrate/miniJinja.ts +480 -0
- package/extension/substrate/paths.ts +38 -0
- package/extension/substrate/prompts.ts +15 -24
- package/extension/substrate/providers.ts +62 -8
- package/extension/substrate/sessionData.ts +1 -1
- package/extension/substrate/sessionPointers.ts +184 -0
- package/extension/substrate/structuredOutput.ts +3 -1
- package/extension/substrate/terminalLaunch.ts +178 -0
- package/extension/substrate/toolGating.ts +332 -73
- package/extension/substrate/toolParams.ts +7 -0
- package/extension/substrate/workflowState.ts +54 -2
- package/extension/surfaces/footerProvider.ts +8 -4
- package/extension/surfaces/surfaces.ts +338 -13
- package/extension/vendor/btw/btw.ts +10 -0
- package/extension/worker/readOnlySession.ts +19 -6
- package/extension/worker/worker.ts +187 -31
- package/extension/workerMain.ts +14 -13
- package/package.json +3 -7
- package/prompts/README.md +56 -5
- package/prompts/_fixtures/cases.yaml +52 -131
- package/prompts/_fixtures/golden/cond_elif-a.txt +3 -0
- package/prompts/_fixtures/golden/cond_elif-b.txt +3 -0
- package/prompts/_fixtures/golden/cond_elif-c.txt +3 -0
- package/prompts/_fixtures/golden/cond_if-false.txt +3 -0
- package/prompts/_fixtures/golden/cond_if-true.txt +3 -0
- package/prompts/_fixtures/golden/cond_ops-1.txt +3 -0
- package/prompts/_fixtures/golden/cond_ops-2.txt +3 -0
- package/prompts/_fixtures/golden/no_trailing_nl.txt +2 -0
- package/prompts/_fixtures/golden/trailing_nl.txt +2 -0
- package/prompts/_fixtures/golden/trim_block.txt +3 -0
- package/prompts/_fixtures/golden/trim_inline.txt +1 -0
- package/prompts/_fixtures/live.yaml +396 -0
- package/prompts/_fixtures/templates/cond_elif.md +9 -0
- package/prompts/_fixtures/templates/cond_if.md +7 -0
- package/prompts/_fixtures/templates/cond_ops.md +3 -0
- package/prompts/_fixtures/templates/no_trailing_nl.md +2 -0
- package/prompts/_fixtures/templates/trailing_nl.md +2 -0
- package/prompts/_fixtures/templates/trim_block.md +5 -0
- package/prompts/_fixtures/templates/trim_inline.md +1 -0
- package/prompts/contexts/adapters/juicesharp-todo.md +7 -0
- package/prompts/contexts/adapters/plannotator-objective.md +7 -0
- package/prompts/contexts/adapters/plannotator-plan.md +6 -0
- package/prompts/contexts/adapters/tombell-plan.md +17 -0
- package/prompts/contexts/objective-authoring.md +20 -0
- package/prompts/contexts/plan-authoring.md +24 -0
- package/prompts/contexts/read-only.md +10 -0
- package/prompts/stages/conflict-resolution.md +4 -0
- package/prompts/stages/learn-code.md +8 -0
- package/prompts/stages/learn-docs.md +7 -6
- package/prompts/stages/learn-orchestrate.md +6 -0
- package/prompts/stages/learn.md +1 -1
- package/prompts/stages/objective-author/adopt.md +12 -0
- package/prompts/stages/objective-author/file.md +9 -0
- package/prompts/stages/objective-author/seed.md +9 -0
- package/prompts/stages/objective-plan/guidance.md +1 -1
- package/prompts/stages/objective-plan/seed.md +3 -2
- package/prompts/stages/objective-reconcile.md +7 -0
- package/prompts/stages/objective-replan.md +14 -0
- package/prompts/stages/objective-save.md +9 -0
- package/prompts/stages/plan-from/adopt.md +10 -0
- package/prompts/stages/plan-from/file.md +9 -0
- package/prompts/stages/pr-review-browser/active.md +11 -0
- package/prompts/stages/pr-review-browser/foreign.md +11 -0
- package/prompts/stages/pr-review-terminal/active.md +12 -0
- package/prompts/stages/pr-review-terminal/foreign.md +13 -0
- package/prompts/stages/pr-review-terminal/local.md +4 -0
- package/prompts/stages/pr-review.md +6 -0
- package/prompts/stages/replan.md +13 -0
- package/prompts/stages/skills/create-from.md +15 -0
- package/prompts/stages/skills/create.md +9 -0
- package/prompts/stages/skills/refine.md +9 -0
- package/shared/README.md +23 -13
- package/shared/bindings.yaml +22 -2
- package/shared/contracts-history.md +191 -0
- package/shared/contracts.md +2258 -1638
- package/shared/providers.yaml +8 -1
- package/shared/registry.yaml +10 -11
- package/shared/schemas/contracts/bindings.schema.json +38 -0
- package/shared/schemas/contracts/providers.schema.json +89 -0
- package/shared/schemas/contracts/registry.schema.json +98 -0
- package/shared/schemas/inputs/handoff-arg.schema.json +6 -0
- package/shared/schemas/inputs/resolve-threads-batch.schema.json +37 -0
- package/shared/schemas/inputs/review-post-batch.schema.json +84 -0
- package/shared/schemas/inputs/review-submit-batch.schema.json +66 -0
- package/shared/schemas/inputs/structured-roadmap-node.schema.json +102 -0
- package/shared/schemas/outputs/doctor-report.schema.json +236 -0
- package/shared/schemas/outputs/init-report.schema.json +419 -0
- package/shared/schemas/outputs/learn-capture.schema.json +90 -0
- package/shared/schemas/outputs/learn-skip.schema.json +59 -0
- package/shared/schemas/outputs/plan-save.schema.json +209 -0
- package/shared/schemas/outputs/pr-feedback.schema.json +334 -0
- package/shared/schemas/outputs/pr-land.schema.json +187 -0
- package/shared/schemas/outputs/pr-ready.schema.json +75 -0
- package/shared/schemas/outputs/pr-review-checkout.schema.json +69 -0
- package/shared/schemas/outputs/pr-review-cleanup.schema.json +54 -0
- package/shared/schemas/outputs/pr-review-context.schema.json +86 -0
- package/shared/schemas/outputs/pr-review-submit.schema.json +64 -0
- package/shared/schemas/outputs/pr-submit.schema.json +147 -0
- package/extension/doors/learnDocs.ts +0 -99
- package/prompts/_fixtures/golden/address-action-model.txt +0 -10
- package/prompts/_fixtures/golden/address-action.txt +0 -10
- package/prompts/_fixtures/golden/address-preview-model.txt +0 -6
- package/prompts/_fixtures/golden/address-preview.txt +0 -6
- package/prompts/_fixtures/golden/implement-github.txt +0 -8
- package/prompts/_fixtures/golden/learn-docs.txt +0 -8
- package/prompts/_fixtures/golden/learn-github.txt +0 -11
- package/prompts/_fixtures/golden/learn-linear.txt +0 -11
- package/prompts/_fixtures/golden/learn-no-ref.txt +0 -8
- package/prompts/_fixtures/golden/learn-other.txt +0 -8
- package/prompts/_fixtures/golden/objective-plan-guidance-linear.txt +0 -8
- package/prompts/_fixtures/golden/objective-plan-guidance.txt +0 -8
- package/prompts/_fixtures/golden/objective-plan-seed-linear.txt +0 -20
- package/prompts/_fixtures/golden/objective-plan-seed.txt +0 -15
- package/prompts/_fixtures/golden/objective-read-linear-nourl.txt +0 -1
- package/prompts/_fixtures/golden/objective-read-linear.txt +0 -1
- package/prompts/_fixtures/golden/plan-read-github.txt +0 -1
- package/prompts/_fixtures/golden/plan-read-linear.txt +0 -1
- package/prompts/_fixtures/golden/plan-read-other.txt +0 -1
package/shared/bindings.yaml
CHANGED
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
# trigger — the "<kind>:<id>" string above.
|
|
21
21
|
# skill — the skill name (a skills/*/ dir name today).
|
|
22
22
|
# mode — per-binding delivery mode:
|
|
23
|
-
# nudge — deliver a short pointer to follow the named skill
|
|
24
|
-
#
|
|
23
|
+
# nudge — deliver a short pointer to follow the named skill. The pointer
|
|
24
|
+
# carries the skill's read path (.agents/skills/<skill>/SKILL.md):
|
|
25
|
+
# perk's own stage skills are hidden from the ambient system prompt
|
|
26
|
+
# (disable-model-invocation: true) and are reached only through it.
|
|
25
27
|
# transclude — inline the skill body into the prompt/context.
|
|
26
28
|
# mode is per-binding (not global): one skill may be a nudge at one trigger
|
|
27
29
|
# and a transclude at another.
|
|
@@ -56,9 +58,27 @@ bindings:
|
|
|
56
58
|
- trigger: "command:objective-reconcile"
|
|
57
59
|
skill: perk-objective-reconcile
|
|
58
60
|
mode: nudge
|
|
61
|
+
- trigger: "command:objective-replan"
|
|
62
|
+
skill: perk-objective-replan
|
|
63
|
+
mode: nudge
|
|
59
64
|
- trigger: "command:learn-docs"
|
|
60
65
|
skill: perk-learn-docs
|
|
61
66
|
mode: nudge
|
|
67
|
+
- trigger: "command:learn-code"
|
|
68
|
+
skill: perk-learn-code
|
|
69
|
+
mode: nudge
|
|
62
70
|
- trigger: "command:pr-review"
|
|
63
71
|
skill: perk-pr-review
|
|
64
72
|
mode: nudge
|
|
73
|
+
- trigger: "command:pr-review-terminal"
|
|
74
|
+
skill: perk-pr-review-terminal
|
|
75
|
+
mode: nudge
|
|
76
|
+
- trigger: "command:pr-review-browser"
|
|
77
|
+
skill: perk-pr-review-browser
|
|
78
|
+
mode: nudge
|
|
79
|
+
- trigger: "command:skills-create"
|
|
80
|
+
skill: perk-skill-author
|
|
81
|
+
mode: nudge
|
|
82
|
+
- trigger: "command:skills-refine"
|
|
83
|
+
skill: perk-skill-author
|
|
84
|
+
mode: nudge
|
|
@@ -401,3 +401,194 @@ bundled — the Python wheel as package data `perk/_shared/`, the npm package un
|
|
|
401
401
|
> selection** — it is pi-web-access-specific (it depends on `fetch_content`'s GitHub-clone path),
|
|
402
402
|
> documented and not re-homed. Catalog entries carry no `package_filter` (each package's sole
|
|
403
403
|
> extension is its root `./index.ts`, verified via `npm view <pkg> pi`).
|
|
404
|
+
>
|
|
405
|
+
> **Status (review — the sixth seam, the first DISPATCH seam; RETIRED 2026-07, Objective #1261
|
|
406
|
+
> Node 4.1):** a sixth seam, **`review`**, existed from the toolbox objective's nodes 1.x through
|
|
407
|
+
> 4.1 and is now **retired**. Its shape while live: the first **DISPATCH posture** — no adapter
|
|
408
|
+
> (the seam produces no durable artifact) and nothing to vacate (perk owned no prior guest-review
|
|
409
|
+
> surface); the selection drove **protocol dispatch** inside a dispatching `/review` door — which
|
|
410
|
+
> review surface the door drove (`hunk`, the default: the hunk session CLI handshake, with perk's
|
|
411
|
+
> `submit_pr_review` tool as the only posting path; or `plannotator-review`: the `code-review`
|
|
412
|
+
> `pi.events` bridge behind an `open_plannotator_review` tool plus the agent-driven
|
|
413
|
+
> external-annotations HTTP stream, with the UI's native platform-posting as the GitHub path) and
|
|
414
|
+
> which posting path was primary. The default `hunk` was the first `default: true` entry whose
|
|
415
|
+
> substrate is an **external CLI** (npm `hunkdiff`) rather than a Pi package;
|
|
416
|
+
> `plannotator-review` shared `npm:@plannotator/pi-extension` with `plannotator-plan`, the
|
|
417
|
+
> cross-seam instance of the desired-**union** package convergence. **The retirement (Node 4.1):**
|
|
418
|
+
> once the surface-named doors (`/pr-review-terminal`, `/pr-review-browser`) absorbed both arms
|
|
419
|
+
> (nodes 2.1–3.1), the dispatch had no job left — the command IS the selection. `/review`, its
|
|
420
|
+
> dispatch, `open_plannotator_review`, and the seam rows were deleted; `SEAMS`/`PROVIDER_SEAMS`
|
|
421
|
+
> shrank back to five; the retired `[providers] review` key got the legacy-tripwire treatment
|
|
422
|
+
> (hard-fail on the Python plane, silent-ignore on the TS plane); the hunk-CLI init/doctor
|
|
423
|
+
> handling was already unconditional (a review *surface*, not a selection consequence) and is
|
|
424
|
+
> unchanged; the plannotator package is desired via `plannotator-plan` alone (the union mechanism
|
|
425
|
+
> stays generic, its only cross-seam instance retired). `submit_pr_review` re-homed to
|
|
426
|
+
> `extension/doors/submitPrReview.ts` with an unchanged contract; the `perk-review` skill split
|
|
427
|
+
> into `perk-pr-review-terminal` + `perk-pr-review-browser`.
|
|
428
|
+
|
|
429
|
+
## §8.31 · The prompt render seam + golden parity (Objective #791, Node 1.2)
|
|
430
|
+
|
|
431
|
+
**First prompt moved onto the seam — the plan-read instruction (Node 2.1).** The cross-plane
|
|
432
|
+
plan-read instruction (the "how do I read the saved plan" SSOT) is the first real (non-fixture)
|
|
433
|
+
consumer of the render seam. Its three arm templates live at
|
|
434
|
+
`prompts/common/plan-read/{github,linear,other}.md` — one file per provider arm, no
|
|
435
|
+
conditionals/loops in the frozen subset. **Branching stays in code**: `perk/run/launch/prompts.py::
|
|
436
|
+
_plan_read_instruction` and `extension/doors/lifecycleGates.ts::planReadInstruction` keep their
|
|
437
|
+
`(provider, pr_id/prId, url)` signature and the same if/elif/else, each arm now a `render(...)` call
|
|
438
|
+
selecting its arm template (passing `{pr_id, url}`; jinja2/nunjucks ignore unused vars). The helpers
|
|
439
|
+
still branch on `cache.plan-ref.provider` — only the **wording source** moved.
|
|
440
|
+
|
|
441
|
+
The arm templates (and their golden files) carry **no trailing newline** — the helper returns
|
|
442
|
+
single-line strings embedded mid-prompt, so the render output must equal the prior literal exactly
|
|
443
|
+
(a deliberate departure from the fixture convention of trailing newlines). The three `plan-read-*`
|
|
444
|
+
golden cases in `cases.yaml` prove cross-plane byte-identity for each arm; a thin per-arm selection
|
|
445
|
+
test in each plane (`tests/test_worker_prompt_parity.py`, `extension/doors/lifecycleGates.test.ts`)
|
|
446
|
+
proves the code picks the right arm and `render()` is wired. This golden-fixture parity (plus the
|
|
447
|
+
selection tests) **replaces the prior dedicated substring parity** for plan-read; the
|
|
448
|
+
implement/learn prompt parity suites are untouched (they embed the byte-identical helper output, so
|
|
449
|
+
they keep passing — the downstream prompts move in nodes 2.2/2.4).
|
|
450
|
+
|
|
451
|
+
**Second prompt moved — the implement primer (Node 2.2).** The implement-stage primer wording lives
|
|
452
|
+
at `prompts/stages/implement.md`, the second real consumer of the render seam. All three sites that
|
|
453
|
+
used to hand-duplicate it — cold `perk/run/launch/prompts.py::_implement_prompt`, worker
|
|
454
|
+
`extension/worker/worker.ts::initialPromptFor` (implement arm), and warm
|
|
455
|
+
`extension/doors/lifecycleGates.ts::implementHandoffPrompt` — are now thin `render("stages/
|
|
456
|
+
implement.md", {provider, pr_id, url, read_cmd})` calls. The prior warm/cold variance (the warm
|
|
457
|
+
handoff omitting the "Progress markers:" tail) is reconciled by **unifying**: all three render the
|
|
458
|
+
one template with the same vars, so they are **byte-identical** and the warm handoff now carries the
|
|
459
|
+
progress markers too. `read_cmd` is the provider-selected plan-read instruction computed in code via
|
|
460
|
+
the Node-2.1 helper — branching stays in code, no `{% if %}`/second template. The template and its
|
|
461
|
+
golden (`implement-github`) carry **no trailing newline** (matching the prior cold/worker literal).
|
|
462
|
+
One golden case proves the template renders identically in both planes; thin per-plane composition
|
|
463
|
+
tests (start-with / contains read_cmd / ends-with the progress tail) prove each helper wires the
|
|
464
|
+
right template + vars — together these **replace `IMPLEMENT_SUBSTRINGS`**. The pre-objective audit
|
|
465
|
+
`docs/design/prompt-language-audit.md` (still describing warm as a shorter near-copy) is left as a
|
|
466
|
+
frozen snapshot; this paragraph is the authoritative current-state note.
|
|
467
|
+
|
|
468
|
+
**The address prompt moved onto the seam — converging three consumers (Node 2.3).** The
|
|
469
|
+
address-stage wording lives in two canonical templates `prompts/stages/address/{action,preview}.md`
|
|
470
|
+
(each a complete body, no template logic; vars `{{ provider }}`, `{{ pr_id }}`, `{{ url }}`,
|
|
471
|
+
`{{ model_clause }}`), rendered identically by **all three** address consumers via the shared
|
|
472
|
+
render seam: the cold `perk/run/launch/prompts.py::_address_prompt`, the worker
|
|
473
|
+
`extension/worker/worker.ts::initialPromptFor("address")`, and the warm
|
|
474
|
+
`extension/doors/address.ts::addressGuidance`. Before this node the warm `/address` loop used a
|
|
475
|
+
*different* wording; the three were **converged** onto one canonical body — the cold/worker
|
|
476
|
+
structure (the PR-identity header a fresh headless worker needs) **plus** warm's Plan File Mode
|
|
477
|
+
step, which now upgrades the cold/worker path too; warm loses its divergent framing. This is a
|
|
478
|
+
deliberate wording change to all three surfaces; the *command/flag/config* surface of `/address`
|
|
479
|
+
and `perk pr address` is unchanged.
|
|
480
|
+
|
|
481
|
+
**Branching stays in code** (the frozen subset has no conditionals): preview vs action is a
|
|
482
|
+
template *selection* (`preview.md` for `--preview`, which omits the action steps including Plan
|
|
483
|
+
File Mode; `action.md` otherwise), and the classifier present/absent split builds the
|
|
484
|
+
`model_clause` render var in code (empty string when no `[subagents] review-classifier` model) —
|
|
485
|
+
the clause's own wording is deferred to node 3.3. The worker has **no preview path** (preview is a
|
|
486
|
+
warm/cold flag), so it always renders `action.md`.
|
|
487
|
+
|
|
488
|
+
**The warm door is now ref-aware and null-guarded.** The converged body carries the PR identity, so
|
|
489
|
+
`addressGuidance` takes the active `PlanRef`; the `/address` handler resolves it via the same
|
|
490
|
+
helper `doors/learn.ts` uses (`readPlanRef(ctx.cwd)` → fallback
|
|
491
|
+
`rebuildWorkflowState(branchOf(ctx)).active_plan_ref`). A null ref reports a `warning` (mirroring
|
|
492
|
+
the `/implement` guard) and sends no guidance — a strict improvement, since `/address` cannot
|
|
493
|
+
function without a plan-ref regardless (the classifier child's `perk pr feedback` hard-errors
|
|
494
|
+
`no_plan_ref`).
|
|
495
|
+
|
|
496
|
+
The two address templates (and their golden files) carry **no trailing newline** (the builders
|
|
497
|
+
return mid-prompt strings). Four `address-*` golden cases in `cases.yaml` (action/preview × model
|
|
498
|
+
present/absent) prove cross-plane byte-identity; thin per-plane selection tests prove each caller
|
|
499
|
+
picks the right template and injects/omits the model clause, and the warm null-ref guard is
|
|
500
|
+
covered. This golden-fixture parity **replaces the prior `ADDRESS_SUBSTRINGS` substring parity**.
|
|
501
|
+
|
|
502
|
+
**The learn primer moved onto the seam (Node 2.4).** The learn-stage primer wording moved off its
|
|
503
|
+
two hand-concatenated twins onto the render seam — one canonical `prompts/stages/learn.md` rendered
|
|
504
|
+
byte-identical by cold `perk/run/launch/prompts.py::_learn_prompt` and warm
|
|
505
|
+
`extension/doors/learn.ts::learnGuidance` (learn has **no worker twin** — only cold + warm). Cold
|
|
506
|
+
and warm are **unified onto the cold body**: warm `/learn` wording changed from its prior numbered
|
|
507
|
+
"perk /learn —" style to the cold bullet "You are in the learn step…" body, the `other` arm
|
|
508
|
+
collapsed to a single "Open the plan and its merged change" line (warm **lost** its prior `other`
|
|
509
|
+
merged-PR derivation — an accepted change for the effectively-unreachable provider arm), and warm's
|
|
510
|
+
no-plan-ref fallback folded into the same template. This node is the **first template to use
|
|
511
|
+
conditionals**: the `{% if pr_id %}` header split and the no-ref / github+linear / other structure
|
|
512
|
+
selection are the template's conditional on `provider` (+ `pr_id` presence); the provider read-line
|
|
513
|
+
text is supplied as the `read_cmd` var from the node-2.1 plan-read helper (`_plan_read_instruction`
|
|
514
|
+
/ `planReadInstruction`), `read_cmd` passed always (empty string when absent) so it is defined. The
|
|
515
|
+
template keeps each `{% if %}`/`{% elif %}`/`{% else %}`/`{% endif %}` tag on its **own line** (off
|
|
516
|
+
the content lines) — enabled by the `trim_blocks` env flip above, which swallows the single newline
|
|
517
|
+
after each block tag so the indented bullet content renders intact (whitespace-control `{%- -%}`
|
|
518
|
+
markers alone could not — they also strip the bullets' leading indentation). The
|
|
519
|
+
template and all four golden files carry **no trailing newline** (matching the cold literal). Four
|
|
520
|
+
`learn-*` golden cases in `cases.yaml` (`learn-github`, `learn-linear`, `learn-other`,
|
|
521
|
+
`learn-no-ref`) prove cross-plane byte-identity and **replace the dedicated learn substring parity**;
|
|
522
|
+
thin per-plane selection/composition tests remain. nunjucks stays the TS engine — the golden suite
|
|
523
|
+
is the byte-parity proof that jinja2 and nunjucks render the conditional template identically (the
|
|
524
|
+
tag-hugging whitespace discipline keeps them equal with `trim_blocks`/`lstrip_blocks` off).
|
|
525
|
+
|
|
526
|
+
**The objective-read instruction moved onto the seam (Node 2.5).** The cross-plane objective-read
|
|
527
|
+
clause (the supplemental wording telling the model how to inspect a Linear-Project-backed
|
|
528
|
+
objective's node-issues) moved off its two hand-duplicated twins onto the render seam, mirroring the
|
|
529
|
+
plan-read move. The wording lives in a subdirectory at `prompts/common/objective-read/linear.md` —
|
|
530
|
+
one arm file for the **linear** arm only (github and any non-linear backend return `""` directly in
|
|
531
|
+
code without rendering, since `perk objective show` already covers them). **Branching stays in
|
|
532
|
+
code**: `perk/cli/commands/objective/shared.py::objective_read_instruction` and
|
|
533
|
+
`extension/factories/objectivePlan.ts::objectiveReadInstruction` keep their `(backend,
|
|
534
|
+
objective_id/objectiveId, url)` signature and the `backend != "linear" → ""` early return; the
|
|
535
|
+
linear arm computes the two **url-presence** render vars `where`/`fallback` in code (the frozen
|
|
536
|
+
subset has no conditionals — mirroring the `model_clause` precedent) and renders the one template.
|
|
537
|
+
|
|
538
|
+
The template (and its golden files) carry **no trailing newline** — the helper returns a single-line
|
|
539
|
+
string embedded mid-prompt, so the render output must equal the prior literal exactly (the
|
|
540
|
+
`_seed_prompt`/`factoryGuidance`/`reconcileGuidance` composition tests embed it and keep passing).
|
|
541
|
+
Two `objective-read-*` golden cases in `cases.yaml` (the linear arm, both url sub-variants) prove
|
|
542
|
+
cross-plane byte-identity; the empty github/other arm stays code-only (no render → no golden) and is
|
|
543
|
+
covered by the per-plane selection tests. Per-plane selection tests in each plane
|
|
544
|
+
(`tests/test_objective_prompt_parity.py`, `extension/factories/objectivePlan.test.ts`) prove the
|
|
545
|
+
code picks the right arm + computes where/fallback. This golden-fixture parity **replaces the prior
|
|
546
|
+
`OBJECTIVE_LINEAR_SUBSTRINGS` substring lockstep** (which remains only as a local constant for the
|
|
547
|
+
per-plane + seed-composition tests, no longer a cross-plane invariant). The `_seed_prompt` /
|
|
548
|
+
`factoryGuidance` / `reconcileGuidance` body moves are deferred to Node 2.6.
|
|
549
|
+
|
|
550
|
+
**The objective-plan factory seed + warm guidance moved onto the seam (Node 2.6).** The two
|
|
551
|
+
hand-built objective-plan-factory prompt bodies — the **cold** seed
|
|
552
|
+
(`perk/cli/commands/objective/plan_cmd.py::_seed_prompt`) and the **warm** guidance
|
|
553
|
+
(`extension/factories/objectivePlan.ts::factoryGuidance`) — moved onto the render seam as the sixth
|
|
554
|
+
real consumer. Unlike the implement (2.2) / learn (2.4) moves, they are **NOT unified**: the cold
|
|
555
|
+
seed launches a *fresh* read-only session, so it **injects** the objective title + node description
|
|
556
|
+
(the `<untrusted_objective>` block) and the pre-planning node-engagement block as DATA, and its node
|
|
557
|
+
is already marked `planning` by the cold door; the warm guidance runs *in-session*, so it
|
|
558
|
+
**instructs** the model to fetch the objective + node engagement and to mark the node `planning`
|
|
559
|
+
itself. This **cold-injects / warm-instructs** asymmetry makes them genuinely different bodies, so
|
|
560
|
+
they become **two arm files in a subdirectory** — `prompts/stages/objective-plan/{seed,guidance}.md`
|
|
561
|
+
(filenames mirror the function names) — like 2.1/2.3/2.5 landed despite singular node titles. The
|
|
562
|
+
**branching moved INTO the templates** as `{% if %}` conditionals (the learn-2.4 pattern, enabled by
|
|
563
|
+
`trim_blocks`): block-level tags on their own lines (the cold engagement block, the warm
|
|
564
|
+
node-selection line) and inline tags mid-line (the read clause, the explorer/model clause). The
|
|
565
|
+
helpers now pass **raw** vars — `node_engagement` (the rendered block, `""` when absent),
|
|
566
|
+
`read_clause` (the rendered linear clause, `""` for github/other), `model` (`""` when unset), and
|
|
567
|
+
(warm) `node` (`""` → select-next) — while the in-code arm SELECTION
|
|
568
|
+
(`objective_read_instruction` / `objectiveReadInstruction` backend logic) is unchanged. Both
|
|
569
|
+
templates and their golden files carry **no trailing newline** (the prior literals had none). Four
|
|
570
|
+
`objective-plan-*` golden cases in `cases.yaml` (seed/guidance × github/linear) prove cross-plane
|
|
571
|
+
byte-parity across both arms of every conditional. The per-plane composition tests are **retained**
|
|
572
|
+
(`OBJECTIVE_LINEAR_SUBSTRINGS` survives as a local constant feeding the per-plane selection +
|
|
573
|
+
seed-composition tests); no cross-plane substring lockstep existed between the two different prompts,
|
|
574
|
+
so none is removed.
|
|
575
|
+
|
|
576
|
+
**The learned-docs factory seed + warm guidance moved onto the seam (Node 2.7).** The two
|
|
577
|
+
hand-built learned-docs-factory prompt bodies — the **cold** seed
|
|
578
|
+
(`perk/cli/commands/learn/docs_cmd.py::_seed_prompt`) and the **warm** guidance
|
|
579
|
+
(`extension/doors/learnDocs.ts::learnDocsGuidance`) — moved onto the render seam as the seventh real
|
|
580
|
+
consumer. **Unlike 2.6 they are UNIFIED** (the implement-2.2 / learn-2.4 pattern): the cold/warm
|
|
581
|
+
differences were all **superficial factory house-style** — header wording, a header blank line,
|
|
582
|
+
step-number indentation, a cold-only "from this read-only session" qualifier, and the
|
|
583
|
+
closing-paragraph phrasing — none load-bearing, so they were **converged away** onto the **cold-seed
|
|
584
|
+
orientation form** rather than preserved behind conditionals. The warm guidance gained the "You are
|
|
585
|
+
running…" header + the standalone closing paragraph ("Judgment, user interaction, and durable writes
|
|
586
|
+
stay with you — never delegate them."), and the cold seed lost the `" "` step indent + the "from
|
|
587
|
+
this read-only session" qualifier (the warm session is not read-only, so the qualifier was
|
|
588
|
+
cold-only-accurate anyway; the bare "NEVER write the docs directly" is correct in both planes). The
|
|
589
|
+
result is a single **flat** template `prompts/stages/learn-docs.md` with **zero `{% if %}`
|
|
590
|
+
conditionals**; both planes pass the same two vars (`inbox_path`, `num_list`). The template and its
|
|
591
|
+
golden carry **no trailing newline**. One `learn-docs` golden case in `cases.yaml` proves cross-plane
|
|
592
|
+
byte-parity. No cross-plane substring lockstep existed between cold and warm, so none is removed; the
|
|
593
|
+
per-plane composition tests are retained (one warm header assertion updated from `"perk /learn-docs"`
|
|
594
|
+
to `"learned-docs plan factory"`).
|