@crouton-kit/crouter 0.3.17 → 0.3.19
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/dist/build-root.js +6 -0
- package/dist/builtin-memory/crouter-development/marketplaces.md +164 -0
- package/dist/builtin-memory/crouter-development/personas/base-prompt.md +58 -0
- package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +60 -0
- package/dist/builtin-memory/crouter-development/personas.md +117 -0
- package/dist/builtin-memory/crouter-development/plugins.md +163 -0
- package/dist/builtin-memory/design.md +60 -0
- package/dist/builtin-memory/development.md +116 -0
- package/dist/builtin-memory/planning.md +66 -0
- package/dist/builtin-memory/spec.md +99 -0
- package/dist/builtin-personas/design/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/design/orchestrator.md +1 -1
- package/dist/builtin-personas/developer/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/developer/orchestrator.md +1 -1
- package/dist/builtin-personas/explore/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/general/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/lifecycle/resident.md +1 -1
- package/dist/builtin-personas/lifecycle/terminal.md +5 -2
- package/dist/builtin-personas/orchestration-kernel.md +15 -24
- package/dist/builtin-personas/plan/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/plan/orchestrator.md +1 -1
- package/dist/builtin-personas/plan/reviewers/architecture-fit/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/code-smells/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/pattern-consistency/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/requirements-coverage/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/security/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/review/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/runtime-base.md +6 -3
- package/dist/builtin-personas/spec/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/spec/orchestrator.md +1 -1
- package/dist/builtin-personas/waiting.md +8 -0
- package/dist/builtin-skills/skills/crouter-development/personas/SKILL.md +24 -14
- package/dist/builtin-skills/skills/crouter-development/personas/base-prompt/SKILL.md +4 -4
- package/dist/builtin-skills/skills/crouter-development/personas/orchestrator-prompt/SKILL.md +1 -1
- package/dist/builtin-skills/skills/crouter-development/plugins/SKILL.md +2 -2
- package/dist/builtin-views/_lib/states.mjs +161 -0
- package/dist/builtin-views/canvas/client.mjs +303 -0
- package/dist/builtin-views/canvas/view.mjs +576 -0
- package/dist/builtin-views/git-pr/client.mjs +440 -0
- package/dist/builtin-views/git-pr/view.mjs +675 -0
- package/dist/builtin-views/inbox/_lib/render.mjs +177 -0
- package/dist/builtin-views/inbox/sources/gmail.mjs +965 -0
- package/dist/builtin-views/inbox/sources/linkedin.mjs +427 -0
- package/dist/builtin-views/inbox/view.mjs +889 -0
- package/dist/builtin-views/linkedin/client.mjs +610 -0
- package/dist/builtin-views/linkedin/view.mjs +1171 -0
- package/dist/clients/attach/attach-cmd.d.ts +2 -0
- package/dist/clients/attach/attach-cmd.js +354 -0
- package/dist/clients/attach/chat-view.d.ts +77 -0
- package/dist/clients/attach/chat-view.js +450 -0
- package/dist/clients/attach/clipboard-image.d.ts +16 -0
- package/dist/clients/attach/clipboard-image.js +113 -0
- package/dist/clients/attach/config-load.d.ts +31 -0
- package/dist/clients/attach/config-load.js +113 -0
- package/dist/clients/attach/extension-dialogs.d.ts +29 -0
- package/dist/clients/attach/extension-dialogs.js +101 -0
- package/dist/clients/attach/input-controller.d.ts +54 -0
- package/dist/clients/attach/input-controller.js +204 -0
- package/dist/clients/attach/slash-commands.d.ts +36 -0
- package/dist/clients/attach/slash-commands.js +200 -0
- package/dist/clients/attach/view-socket.d.ts +48 -0
- package/dist/clients/attach/view-socket.js +126 -0
- package/dist/commands/attention.js +3 -3
- package/dist/commands/canvas-prune.js +1 -1
- package/dist/commands/daemon.js +4 -3
- package/dist/commands/human/prompts.js +4 -10
- package/dist/commands/human/queue.js +43 -8
- package/dist/commands/human/shared.d.ts +28 -1
- package/dist/commands/human/shared.js +48 -10
- package/dist/commands/memory/find.d.ts +1 -0
- package/dist/commands/memory/find.js +180 -0
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +140 -0
- package/dist/commands/memory/list.d.ts +1 -0
- package/dist/commands/memory/list.js +79 -0
- package/dist/commands/memory/read.js +103 -0
- package/dist/commands/memory/shared.d.ts +30 -0
- package/dist/commands/memory/shared.js +122 -0
- package/dist/commands/memory/write.d.ts +1 -0
- package/dist/commands/memory/write.js +85 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +27 -0
- package/dist/commands/node.d.ts +3 -2
- package/dist/commands/node.js +660 -65
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/push.js +6 -6
- package/dist/commands/revive.js +1 -1
- package/dist/commands/skill/author.js +1 -1
- package/dist/commands/skill/shared.d.ts +1 -8
- package/dist/commands/skill/shared.js +2 -55
- package/dist/commands/skill.js +9 -14
- package/dist/commands/sys/doctor.js +1 -1
- package/dist/commands/sys/update.js +1 -1
- package/dist/commands/view-cycle.d.ts +2 -0
- package/dist/commands/view-cycle.js +125 -0
- package/dist/commands/view-list.d.ts +2 -0
- package/dist/commands/view-list.js +66 -0
- package/dist/commands/view-new.d.ts +2 -0
- package/dist/commands/view-new.js +70 -0
- package/dist/commands/view-pick.d.ts +2 -0
- package/dist/commands/view-pick.js +119 -0
- package/dist/commands/view-run.d.ts +2 -0
- package/dist/commands/view-run.js +191 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +29 -0
- package/dist/core/__tests__/broker-lifecycle.test.d.ts +1 -0
- package/dist/core/__tests__/broker-lifecycle.test.js +677 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.d.ts +1 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.js +166 -0
- package/dist/core/__tests__/cascade-close.test.js +12 -2
- package/dist/core/__tests__/child-death-wake.test.d.ts +1 -0
- package/dist/core/__tests__/child-death-wake.test.js +245 -0
- package/dist/core/__tests__/context-intro.test.js +76 -62
- package/dist/core/__tests__/daemon-boot.test.js +14 -5
- package/dist/core/__tests__/daemon-liveness.test.js +34 -9
- package/dist/core/__tests__/detach-focus.test.d.ts +1 -0
- package/dist/core/__tests__/detach-focus.test.js +206 -0
- package/dist/core/__tests__/draw-style.test.d.ts +1 -0
- package/dist/core/__tests__/draw-style.test.js +258 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +2 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +18 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +138 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +614 -0
- package/dist/core/__tests__/fixtures/fake-pi-host.js +1 -0
- package/dist/core/__tests__/flagship-lifecycle.test.js +7 -1
- package/dist/core/__tests__/frame-decoder-perf.test.d.ts +1 -0
- package/dist/core/__tests__/frame-decoder-perf.test.js +198 -0
- package/dist/core/__tests__/helpers/harness.d.ts +9 -0
- package/dist/core/__tests__/helpers/harness.js +111 -1
- package/dist/core/__tests__/home-session.test.js +41 -8
- package/dist/core/__tests__/human-new-window-regression.test.d.ts +1 -0
- package/dist/core/__tests__/human-new-window-regression.test.js +101 -0
- package/dist/core/__tests__/human-surface-target.test.d.ts +1 -0
- package/dist/core/__tests__/human-surface-target.test.js +98 -0
- package/dist/core/__tests__/kickoff.test.js +37 -3
- package/dist/core/__tests__/live-mutation.test.js +50 -33
- package/dist/core/__tests__/memory.test.js +23 -115
- package/dist/core/__tests__/persona-subkind.test.js +18 -15
- package/dist/core/__tests__/placement-focus.test.js +5 -0
- package/dist/core/__tests__/placement-teardown.test.js +54 -11
- package/dist/core/__tests__/relaunch.test.js +4 -3
- package/dist/core/__tests__/review-render-pane-regression.test.d.ts +1 -0
- package/dist/core/__tests__/review-render-pane-regression.test.js +133 -0
- package/dist/core/__tests__/spawn-root.test.js +10 -0
- package/dist/core/__tests__/spike-harness.test.js +1 -0
- package/dist/core/__tests__/wake-bearings.test.d.ts +1 -0
- package/dist/core/__tests__/wake-bearings.test.js +156 -0
- package/dist/core/__tests__/wake-origin.test.d.ts +1 -0
- package/dist/core/__tests__/wake-origin.test.js +110 -0
- package/dist/core/bootstrap.js +1 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.js +24 -2
- package/dist/core/canvas/browse/model.d.ts +38 -2
- package/dist/core/canvas/browse/model.js +134 -10
- package/dist/core/canvas/browse/render.d.ts +6 -12
- package/dist/core/canvas/browse/render.js +72 -104
- package/dist/core/canvas/canvas.js +15 -22
- package/dist/core/canvas/db.js +46 -0
- package/dist/core/canvas/index.d.ts +1 -0
- package/dist/core/canvas/index.js +1 -0
- package/dist/core/canvas/paths.d.ts +4 -1
- package/dist/core/canvas/paths.js +10 -4
- package/dist/core/canvas/pid.d.ts +4 -0
- package/dist/core/canvas/pid.js +23 -0
- package/dist/core/canvas/render.d.ts +11 -2
- package/dist/core/canvas/render.js +69 -0
- package/dist/core/canvas/types.d.ts +85 -3
- package/dist/core/canvas/types.js +2 -2
- package/dist/core/canvas/wakeups.d.ts +76 -0
- package/dist/core/canvas/wakeups.js +185 -0
- package/dist/core/config.js +4 -1
- package/dist/core/frontmatter.js +37 -124
- package/dist/core/help.d.ts +6 -0
- package/dist/core/help.js +7 -0
- package/dist/core/memory-resolver.d.ts +49 -0
- package/dist/core/memory-resolver.js +141 -0
- package/dist/core/personas/index.d.ts +4 -3
- package/dist/core/personas/index.js +3 -2
- package/dist/core/personas/loader.d.ts +41 -16
- package/dist/core/personas/loader.js +133 -29
- package/dist/core/personas/resolve.d.ts +4 -4
- package/dist/core/personas/resolve.js +28 -16
- package/dist/core/predicate.d.ts +63 -0
- package/dist/core/predicate.js +189 -0
- package/dist/core/resolver.js +26 -5
- package/dist/core/runtime/bearings.d.ts +53 -12
- package/dist/core/runtime/bearings.js +132 -59
- package/dist/core/runtime/broker-cli.d.ts +1 -0
- package/dist/core/runtime/broker-cli.js +46 -0
- package/dist/core/runtime/broker-protocol.d.ts +332 -0
- package/dist/core/runtime/broker-protocol.js +153 -0
- package/dist/core/runtime/broker-sdk.d.ts +48 -0
- package/dist/core/runtime/broker-sdk.js +72 -0
- package/dist/core/runtime/broker.d.ts +55 -0
- package/dist/core/runtime/broker.js +1128 -0
- package/dist/core/runtime/close.js +35 -6
- package/dist/core/runtime/host.d.ts +53 -0
- package/dist/core/runtime/host.js +186 -0
- package/dist/core/runtime/kickoff.d.ts +2 -1
- package/dist/core/runtime/kickoff.js +91 -5
- package/dist/core/runtime/launch.d.ts +45 -2
- package/dist/core/runtime/launch.js +65 -2
- package/dist/core/runtime/lifecycle.js +23 -6
- package/dist/core/runtime/memory.d.ts +2 -42
- package/dist/core/runtime/memory.js +11 -162
- package/dist/core/runtime/nodes.d.ts +33 -0
- package/dist/core/runtime/nodes.js +59 -1
- package/dist/core/runtime/persona.js +21 -11
- package/dist/core/runtime/pi-vendored.d.ts +18 -0
- package/dist/core/runtime/pi-vendored.js +49 -0
- package/dist/core/runtime/placement.d.ts +42 -14
- package/dist/core/runtime/placement.js +228 -38
- package/dist/core/runtime/promote.d.ts +0 -6
- package/dist/core/runtime/promote.js +1 -12
- package/dist/core/runtime/{demote.d.ts → recycle.d.ts} +5 -5
- package/dist/core/runtime/{demote.js → recycle.js} +27 -11
- package/dist/core/runtime/reset.js +8 -6
- package/dist/core/runtime/revive.d.ts +2 -0
- package/dist/core/runtime/revive.js +34 -34
- package/dist/core/runtime/spawn.d.ts +19 -0
- package/dist/core/runtime/spawn.js +75 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +6 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +28 -0
- package/dist/core/runtime/tmux.js +80 -6
- package/dist/core/scope.d.ts +11 -0
- package/dist/core/scope.js +39 -0
- package/dist/core/spawn.d.ts +25 -1
- package/dist/core/spawn.js +72 -7
- package/dist/core/substrate/gate.d.ts +13 -0
- package/dist/core/substrate/gate.js +21 -0
- package/dist/core/substrate/index.d.ts +7 -0
- package/dist/core/substrate/index.js +18 -0
- package/dist/core/substrate/on-read.d.ts +14 -0
- package/dist/core/substrate/on-read.js +292 -0
- package/dist/core/substrate/render.d.ts +25 -0
- package/dist/core/substrate/render.js +256 -0
- package/dist/core/substrate/schema.d.ts +76 -0
- package/dist/core/substrate/schema.js +124 -0
- package/dist/core/substrate/session-cache.d.ts +30 -0
- package/dist/core/substrate/session-cache.js +77 -0
- package/dist/core/substrate/subject.d.ts +41 -0
- package/dist/core/substrate/subject.js +54 -0
- package/dist/core/tui/contract.d.ts +83 -0
- package/dist/core/tui/contract.js +8 -0
- package/dist/core/tui/draw.d.ts +96 -0
- package/dist/core/tui/draw.js +339 -0
- package/dist/core/tui/host.d.ts +29 -0
- package/dist/core/tui/host.js +379 -0
- package/dist/core/tui/loader.d.ts +16 -0
- package/dist/core/tui/loader.js +94 -0
- package/dist/core/{canvas/browse → tui}/terminal.js +7 -6
- package/dist/core/wake.d.ts +86 -0
- package/dist/core/wake.js +308 -0
- package/dist/daemon/crtrd.d.ts +29 -4
- package/dist/daemon/crtrd.js +662 -46
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +171 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +19 -12
- package/dist/pi-extensions/canvas-commands.d.ts +3 -0
- package/dist/pi-extensions/canvas-commands.js +10 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +17 -0
- package/dist/pi-extensions/canvas-context-intro.js +55 -15
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +44 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +112 -0
- package/dist/pi-extensions/canvas-nav.d.ts +3 -0
- package/dist/pi-extensions/canvas-nav.js +145 -34
- package/dist/pi-extensions/canvas-stophook.js +17 -8
- package/dist/pi-extensions/canvas-view.d.ts +21 -0
- package/dist/pi-extensions/canvas-view.js +75 -0
- package/dist/prompts/skill.js +19 -26
- package/dist/prompts/view.d.ts +7 -0
- package/dist/prompts/view.js +101 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/package.json +9 -4
- package/dist/commands/skill/find.d.ts +0 -4
- package/dist/commands/skill/find.js +0 -257
- package/dist/commands/skill/read.js +0 -91
- /package/dist/commands/{skill → memory}/read.d.ts +0 -0
- /package/dist/core/{canvas/browse → tui}/terminal.d.ts +0 -0
|
@@ -10,7 +10,7 @@ Hand any self-contained unit of work to a child instead of doing it inline — t
|
|
|
10
10
|
|
|
11
11
|
You auto-subscribe to every child you spawn, so you're woken when it finishes; read what they reported with `crtr feed read` and dereference the reports that matter. Prefer delegating over grinding it out yourself.
|
|
12
12
|
|
|
13
|
-
## When blocked or
|
|
13
|
+
## When blocked, want feedback, or need a human
|
|
14
14
|
Don't stall and don't guess at a decision a person should make:
|
|
15
15
|
|
|
16
16
|
crtr human ask "<question>"
|
|
@@ -18,6 +18,9 @@ Don't stall and don't guess at a decision a person should make:
|
|
|
18
18
|
## When your task is too big for one context window
|
|
19
19
|
If you discover the job is far larger than one node can hold — many phases, or work that won't fit before you run low on context — **promote yourself** instead of grinding it out:
|
|
20
20
|
|
|
21
|
-
crtr node promote --kind <kind>
|
|
21
|
+
crtr node promote --kind <kind> # `crtr node promote -h`: what an orchestrator is, --kind, roadmap, terminal vs resident
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Don't promote for work that fits one window — finish it.
|
|
24
|
+
|
|
25
|
+
## When you are blocked on a future event or time
|
|
26
|
+
You are not stuck and you are not done — you are waiting. Don't busy-loop or finish: just stop and go dormant, and the runtime wakes you when the thing you wait on happens. See *Waiting* for the details — including the one case where you instead schedule the wake yourself.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
whenToUse: Write a specification — pin down behavior, non-goals, interfaces, edge cases, and testable acceptance criteria from a goal.
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
You are a spec writer. Given a goal or feature request, you produce a specification a planner turns into tasks without guessing your intent — that, not emitting a document, is the bar for done.
|
|
2
6
|
|
|
3
7
|
A spec is genuinely done only when it pins down every dimension a downstream reader would otherwise have to guess: the behavior (what the feature does), the non-goals (what it deliberately does not do — the boundary is as load-bearing as the behavior), the inputs, outputs, and interfaces, the edge cases, and acceptance criteria written so each is testable — an implementer can check it pass or fail without coming back to ask you. Stay at the level of intent and constraint; include implementation detail only where it is genuinely constraining, and cut anything a planner would rewrite anyway. The cost of a flaw here is asymmetric — a planner builds confidently on a wrong premise — so a guessed spec is worse than an admitted gap. Deliver the full spec, complete and self-contained, nothing truncated. The spec states current intent as settled fact, not the path that reached it — fold every clarified decision into the section it belongs in and carry no decision log, superseded framing, or already-answered question; surface a question only when it is genuinely unresolved and needs the human.
|
|
@@ -4,7 +4,7 @@ roadmapSkill: spec
|
|
|
4
4
|
|
|
5
5
|
You are a **spec orchestrator** — you own a specification effort and deliver a spec a planner turns into tasks with zero guessing. You reach that through three gated stages: **SHAPE** (clarify intent with the human until the goal is unambiguous), **DESIGN** (produce the blueprint), and **REQUIREMENTS** (derive precise, testable requirements from the finished design). This is one of the few kinds where human engagement is load-bearing — Shape is interactive, and the human gates each stage before the next begins. You drive and decide; the human answers questions and signs off the artifact each stage produces.
|
|
6
6
|
|
|
7
|
-
Before you shape the roadmap or open any stage, read `crtr
|
|
7
|
+
Before you shape the roadmap or open any stage, read `crtr memory read spec` for the stage gates, the rule for delegating design to a base vs. orchestrator child, and what a finished spec contains. Delegate the design stage to a `design` child — a base node for a bounded surface, a design orchestrator when it spans multiple surfaces or phases.
|
|
8
8
|
|
|
9
9
|
Yield for a fresh window between stages, and derive requirements from the *rendered design text in isolation*, never from the design conversation that produced it — a requirements pass that inherits the design's working context reproduces its blind spots instead of testing them. The effort is done only when every stage has cleared its human gate and the requirements are testable enough that a planner needs nothing further from you.
|
|
10
10
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## Waiting is a way to end a turn
|
|
2
|
+
|
|
3
|
+
Finishing is for a goal that is *met*. When your goal is sound but your next step is blocked on something that has not happened yet — a child's report, a human, a CI run, tomorrow morning — you are not finished, you are **waiting**. Waiting is free: you end your turn, hold no window, and burn no compute, and the runtime brings you back the instant the thing you wait on happens. A dormant node is waiting, not finished.
|
|
4
|
+
|
|
5
|
+
- **Never finish to stop waiting.** `crtr push final` reaps you and cancels your pending one-shot wakes. Reaching for it because you have nothing to do *right now* throws the goal away and leaves a human to re-kick the work. If the goal is not met, wait — do not finish.
|
|
6
|
+
- **Never busy-wait.** Do not hold your window open to re-poll a URL or watch a clock. A wait that costs a live window is a defect — just stop: end your turn and go dormant.
|
|
7
|
+
- **For anything the runtime delivers — a child's report, a human's reply, a sibling's message — just stop.** Go dormant; the runtime wakes you the moment it lands. There is nothing to arm, poll, or verify, and a deadline set to "check in" on a delegate is a belt-and-suspenders the runtime makes unnecessary — your children auto-wake you when they push. A pending wait is reason enough to go dormant: you are released dormant, not re-prompted to finish.
|
|
8
|
+
- **Schedule a wake yourself only when nothing can push to you** — recurring or scheduled standing work, or polling an external the spine can't deliver (CI, a deploy, a clock). With no event to wait for, a self-scheduled wake is the only way to wait at all: `crtr node wake -h`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: crouter-development/personas
|
|
3
3
|
type: playbook
|
|
4
|
-
description: How to define a custom node kind (persona) for crtr —
|
|
5
|
-
keywords: [persona, node kind, --kind, orchestrator,
|
|
4
|
+
description: How to define a custom node kind (persona) for crtr — the PERSONA.md/orchestrator files, the frontmatter contract (incl. whenToUse), nested sub-personas, scope resolution and overrides, and how to write the prose. Use when adding a new `--kind`, overriding a builtin agent, or debugging persona resolution.
|
|
5
|
+
keywords: [persona, node kind, --kind, orchestrator, PERSONA.md, whenToUse, sub-persona, system prompt]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Authoring crtr personas (custom node kinds)
|
|
@@ -26,13 +26,14 @@ Never edit `src/builtin-personas/` for a local need — that ships to everyone.
|
|
|
26
26
|
```
|
|
27
27
|
<root>/personas/
|
|
28
28
|
├── <kind>/
|
|
29
|
-
│ ├──
|
|
30
|
-
│
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
│ ├── PERSONA.md # worker persona (mode=base)
|
|
30
|
+
│ ├── orchestrator.md # orchestrator persona (mode=orchestrator) — optional
|
|
31
|
+
│ └── <sub>/PERSONA.md # nested sub-persona — kind string `<kind>/<sub>` (any depth)
|
|
32
|
+
├── orchestration-kernel.md # shared; @include-d by orchestrator files
|
|
33
|
+
└── runtime-base.md # shared; prepended to EVERY persona automatically
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
A kind exists once `<kind>/` holds a `
|
|
36
|
+
The role-body file is **`PERSONA.md`** (not `base.md` — that layout was retired). A kind exists once `<kind>/` holds a `PERSONA.md` **or** `orchestrator.md`; it then appears in the live `<kinds>` list at `crtr node new -h` / `crtr node promote -h` (each row built from the kind's `whenToUse` frontmatter) — your fast existence check. Note `node new` does **not** validate `--kind` (so a sub-persona string like `plan/reviewers/security` spawns fine); `node promote` / `node yield` do validate against the top-level kind set.
|
|
36
37
|
|
|
37
38
|
## Scope + precedence
|
|
38
39
|
|
|
@@ -48,11 +49,11 @@ Personas are **scope-root content, not plugin content** — they don't ship via
|
|
|
48
49
|
|
|
49
50
|
## The two files
|
|
50
51
|
|
|
51
|
-
**`
|
|
52
|
+
**`PERSONA.md`** — the worker (mode=base). Second person. State scope → method → deliverable, and end by reporting via `crtr push final`. Default lifecycle `terminal` (finishes in one window). → how to write one: `[[crouter-development/personas/base-prompt]]`.
|
|
52
53
|
|
|
53
54
|
**`orchestrator.md`** — the owner that delegates to children and never does the work itself. Name the child kinds it drives and set per-phase exit criteria. **Must end with `@include orchestration-kernel.md`** — the loader inlines it; without it the orchestrator boots with no fan-out protocol. Default lifecycle `resident`. → how to write one: `[[crouter-development/personas/orchestrator-prompt]]`.
|
|
54
55
|
|
|
55
|
-
If a kind has only `
|
|
56
|
+
If a kind has only `PERSONA.md`, `--mode orchestrator` composes `PERSONA.md body + kernel` and forces `resident` — so write `orchestrator.md` only when the worker and owner prose genuinely differ.
|
|
56
57
|
|
|
57
58
|
## Frontmatter contract
|
|
58
59
|
|
|
@@ -66,6 +67,8 @@ YAML frontmatter on either file supplies launch knobs; the body is the system pr
|
|
|
66
67
|
| `extensions` | string[] | pi extensions, **added after** the always-on canvas extensions. |
|
|
67
68
|
| `skills` | string[] | skills attached at launch. |
|
|
68
69
|
| `roadmapSkill` | string | orchestrator only — a skill whose body is injected as roadmap-shaping guidance when the node runs as an orchestrator. |
|
|
70
|
+
| `whenToUse` | string | on a `<kind>/PERSONA.md` — the one-line "when to use this kind" gloss shown in the `<kinds>` list at `node new -h` / `node promote -h`. |
|
|
71
|
+
| `availableTo` | string[] \| `*` | sub-persona only — which kinds see it in their spawn menu. Default: its top-level ancestor kind. `*` / `all` = every kind. |
|
|
69
72
|
|
|
70
73
|
`resolve()` never throws: a missing/empty persona falls back to `"You are a <kind> agent…"` defaults, so a node always boots. `runtime-base.md` (the push/finish/delegate/feed/ask protocol) is prepended to every persona — **don't restate it in the body.**
|
|
71
74
|
|
|
@@ -73,23 +76,30 @@ YAML frontmatter on either file supplies launch knobs; the body is the system pr
|
|
|
73
76
|
|
|
74
77
|
`@include <filename>` inlines another persona-root file, resolved through the same project>user>builtin chain. Used for `orchestration-kernel.md`; drop an `orchestration-kernel.md` at user/project scope to change orchestrator protocol fleet-wide.
|
|
75
78
|
|
|
79
|
+
## Sub-personas
|
|
80
|
+
|
|
81
|
+
A **sub-persona** is a specialist nested under a kind — any descendant dir (any depth) that holds a `PERSONA.md`, e.g. `plan/reviewers/security/PERSONA.md`. It is reachable only by its **full kind string** (`plan/reviewers/security`) and surfaces in a kind's composed prompt (a "Sub-personas you may spawn" menu), never in the global kind list. Intermediate dirs without a `PERSONA.md` (e.g. `reviewers/`) are transparent grouping namespaces — they stay in the kind string but register nothing themselves.
|
|
82
|
+
|
|
83
|
+
Visibility is its `availableTo` frontmatter: omit it and the sub-persona is visible only to its top-level ancestor kind (so `plan/reviewers/*` show up only for `plan`); set `availableTo: [plan, developer]` to surface it in those kinds; set `availableTo: "*"` for every kind. Sub-personas are visibility-only — they are NOT validated at `node new`, so any kind can still spawn one explicitly by its full string.
|
|
84
|
+
|
|
76
85
|
## Dev loop
|
|
77
86
|
|
|
78
87
|
```bash
|
|
79
88
|
mkdir -p ~/.crouter/personas/researcher
|
|
80
|
-
$EDITOR ~/.crouter/personas/researcher/
|
|
81
|
-
crtr node new
|
|
89
|
+
$EDITOR ~/.crouter/personas/researcher/PERSONA.md # whenToUse frontmatter + prose
|
|
90
|
+
crtr node new -h # confirm `researcher` now appears in the <kinds> list
|
|
91
|
+
crtr node new --kind researcher "map the auth flow" # spawn it
|
|
82
92
|
```
|
|
83
93
|
|
|
84
|
-
No scaffold command — create the dir + files by hand. Copy a builtin (`explore/
|
|
94
|
+
No scaffold command — create the dir + files by hand. Copy a builtin (`explore/PERSONA.md`, `developer/orchestrator.md`) as a starting template.
|
|
85
95
|
|
|
86
96
|
## Failure modes
|
|
87
97
|
|
|
88
98
|
- **Orchestrator with no `@include orchestration-kernel.md`** — boots without the fan-out protocol; can't delegate. Always include it.
|
|
89
99
|
- **Restating runtime-base** — the push/finish/delegate protocol is already prepended. Duplicating it wastes context and drifts out of sync.
|
|
90
|
-
- **`lifecycle: resident` on a worker `
|
|
100
|
+
- **`lifecycle: resident` on a worker `PERSONA.md`** — the node never finishes. Reserve `resident` for interactive/long-lived kinds.
|
|
91
101
|
- **Editing `src/builtin-personas/` for a local need** — ships to everyone. Override at user/project scope.
|
|
92
|
-
- **Kind not listed after creating the dir** — neither `
|
|
102
|
+
- **Kind not listed after creating the dir** — neither `PERSONA.md` nor `orchestrator.md` is present, or the filename is wrong (it must be exactly `PERSONA.md` — `base.md` no longer registers a kind). The dir alone doesn't register a kind.
|
|
93
103
|
|
|
94
104
|
## Related
|
|
95
105
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: crouter-development/personas/base-prompt
|
|
3
3
|
type: playbook
|
|
4
|
-
description: How to write a base persona prompt (base.md) — the system prompt for a single-window worker node. Covers what a base persona is for, what to put in it, the identity/deliverable/boundary/report shape, and the voice to use. Use when writing or revising a <kind>/
|
|
5
|
-
keywords: [base persona,
|
|
4
|
+
description: How to write a base persona prompt (the mode=base PERSONA.md) — the system prompt for a single-window worker node. Covers what a base persona is for, what to put in it, the identity/deliverable/boundary/report shape, and the voice to use. Use when writing or revising a <kind>/PERSONA.md.
|
|
5
|
+
keywords: [base persona, PERSONA.md, worker prompt, system prompt, terminal node]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Writing a base persona prompt
|
|
9
9
|
|
|
10
|
-
`
|
|
10
|
+
`PERSONA.md` (mode=base) is the system prompt for a **terminal worker** — a node that does one job in one context window and finishes. Its whole purpose is to make a focused specialist that produces a deliverable and reports it. This skill is the philosophy of what belongs in a base persona; for file mechanics and frontmatter, see `[[crouter-development/personas]]`.
|
|
11
11
|
|
|
12
|
-
Audience: LLM agents writing a `<kind>/
|
|
12
|
+
Audience: LLM agents writing a `<kind>/PERSONA.md`.
|
|
13
13
|
|
|
14
14
|
## What a base persona is for
|
|
15
15
|
|
package/dist/builtin-skills/skills/crouter-development/personas/orchestrator-prompt/SKILL.md
CHANGED
|
@@ -23,7 +23,7 @@ So your `orchestrator.md` body carries **only the delta** — what is specific t
|
|
|
23
23
|
|
|
24
24
|
2. **The child kinds it drives, and the pipeline.** Name the specialists this orchestrator delegates to and the order it runs them: developer drives `explore → spec → plan → developer → review` as a "spec → plan → implement → review → fix → validate" pipeline; spec runs `SHAPE → DESIGN → REQUIREMENTS` stages; review fans `review` children across units. The flow is the kind's signature — make it explicit so delegation isn't ad hoc.
|
|
25
25
|
|
|
26
|
-
3. **A pointer to the methodology skill — don't inline it.** Set `roadmapSkill: <skill>` in frontmatter and tell the body to read `crtr
|
|
26
|
+
3. **A pointer to the methodology skill — don't inline it.** Set `roadmapSkill: <skill>` in frontmatter and tell the body to read `crtr memory read <kind>` before shaping the roadmap. The methodology (roadmap shapes, styles, decomposition rules) lives in that skill, not the persona. The persona points; the skill teaches.
|
|
27
27
|
|
|
28
28
|
4. **The kind's quality bar.** State the domain-specific exit criteria the kernel can't: developer's "implementation is done when provably correct against the spec, review done when a non-implementer cleared all Major/Critical findings, validation done end-to-end in the real runtime." This is where you set the ceiling for *this* kind of work.
|
|
29
29
|
|
|
@@ -104,7 +104,7 @@ ln -s $(pwd) ~/.crouter/plugins/my-plugin
|
|
|
104
104
|
# Verify
|
|
105
105
|
crtr pkg plugin inspect list # my-plugin appears
|
|
106
106
|
crtr pkg plugin inspect show my-plugin # lists its skills
|
|
107
|
-
crtr
|
|
107
|
+
crtr memory list --plugin my-plugin # just my-plugin's skills
|
|
108
108
|
crtr sys doctor # validates manifest + every skill
|
|
109
109
|
```
|
|
110
110
|
|
|
@@ -124,7 +124,7 @@ Standard semver:
|
|
|
124
124
|
|
|
125
125
|
## Enable/disable
|
|
126
126
|
|
|
127
|
-
`crtr pkg plugin manage disable <name>` flips the per-scope config without removing files. Disabled plugins are hidden from `crtr
|
|
127
|
+
`crtr pkg plugin manage disable <name>` flips the per-scope config without removing files. Disabled plugins are hidden from `crtr memory list` and don't resolve via `crtr memory read <name>`. Re-enable with `crtr pkg plugin manage enable <name>`.
|
|
128
128
|
|
|
129
129
|
Individual skills inside an enabled plugin can also be disabled: `crtr skill state disable <plugin>/<skill>`.
|
|
130
130
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* Standard view states — the four states every crtr view must *design* rather
|
|
4
|
+
* than leave bare (design §4): loading-skeleton, empty-reward, error-keeps-its-
|
|
5
|
+
* shape, and the guided not-ready takeover.
|
|
6
|
+
*
|
|
7
|
+
* Copy-pasteable BODY HELPERS: this is a sibling lib the builtin views import
|
|
8
|
+
* RELATIVELY (`import { loadingState } from '../_lib/states.mjs'`). It imports
|
|
9
|
+
* NOTHING from crtr — the view passes in the `draw` + content `rect` the host
|
|
10
|
+
* already handed it, and these paint the state into `draw`.
|
|
11
|
+
*
|
|
12
|
+
* Discipline (design §2): all color is NUMERIC SGR codes ('32' green, '31' red,
|
|
13
|
+
* '36' cyan, '33' yellow); color NEVER carries meaning alone — every colored
|
|
14
|
+
* element pairs its hue with a glyph or weight so it survives NO_COLOR / dumb
|
|
15
|
+
* terminals. Hue is the framework's job to gate (draw.ts gates fg/bg on caps);
|
|
16
|
+
* structural weight (bold/dim) always renders.
|
|
17
|
+
*
|
|
18
|
+
* @module _lib/states
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** @typedef {import('../../core/tui/draw.js').Draw} Draw */
|
|
22
|
+
/** @typedef {import('../../core/tui/draw.js').Rect} Rect */
|
|
23
|
+
/** @typedef {import('../../core/tui/draw.js').Span} Span */
|
|
24
|
+
/** @typedef {import('../../core/tui/draw.js').Style} Style */
|
|
25
|
+
|
|
26
|
+
// ── internal ──────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/** @param {Span[]} spans @returns {number} */
|
|
29
|
+
function spanWidth(spans) {
|
|
30
|
+
let n = 0;
|
|
31
|
+
for (const s of spans) n += Array.from(s.text).length;
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @param {string|string[]|undefined|null} v @returns {string[]} */
|
|
36
|
+
function toLines(v) {
|
|
37
|
+
if (v == null) return [];
|
|
38
|
+
if (Array.isArray(v)) return v.map((s) => String(s == null ? '' : s));
|
|
39
|
+
return [String(v)];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Place a vertically + horizontally centered stack of span-lines in `rect`.
|
|
44
|
+
* Each entry is one line's spans; rows that fall outside the rect are skipped.
|
|
45
|
+
* @param {Draw} draw @param {Rect} rect @param {Span[][]} lines
|
|
46
|
+
*/
|
|
47
|
+
function centeredStack(draw, rect, lines) {
|
|
48
|
+
if (!rect || rect.width <= 0 || rect.height <= 0 || lines.length === 0) return;
|
|
49
|
+
const start = rect.row + Math.max(0, Math.floor((rect.height - lines.length) / 2));
|
|
50
|
+
lines.forEach((spans, i) => {
|
|
51
|
+
const row = start + i;
|
|
52
|
+
if (row < rect.row || row >= rect.row + rect.height) return;
|
|
53
|
+
const w = spanWidth(spans);
|
|
54
|
+
const col = rect.col + Math.max(0, Math.floor((rect.width - w) / 2));
|
|
55
|
+
draw.spans(row, col, spans, rect.col + rect.width - col);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── states ─────────────────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Loading — paint a SKELETON of where content will land (dim `····` placeholder
|
|
63
|
+
* rows), not a lone centered "Loading…". The layout is legible before data
|
|
64
|
+
* arrives. Pair with the host's `⟳ working` chip + a `setStatus('Loading…')`.
|
|
65
|
+
*
|
|
66
|
+
* @param {Draw} draw
|
|
67
|
+
* @param {Rect} rect
|
|
68
|
+
* @param {{ rows?: number, label?: string }} [opts]
|
|
69
|
+
* rows — how many skeleton rows (default 4); label — optional dim caption below.
|
|
70
|
+
*/
|
|
71
|
+
export function loadingState(draw, rect, opts = {}) {
|
|
72
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return;
|
|
73
|
+
const n = Math.max(1, Math.min(opts.rows ?? 4, rect.height));
|
|
74
|
+
const snippetLens = [10, 8, 12, 7, 11];
|
|
75
|
+
for (let i = 0; i < n; i++) {
|
|
76
|
+
const row = rect.row + i;
|
|
77
|
+
const label = '·'.repeat(4);
|
|
78
|
+
const snipLen = Math.min(snippetLens[i % snippetLens.length], Math.max(0, rect.width - 8));
|
|
79
|
+
/** @type {Span[]} */
|
|
80
|
+
const spans = [{ text: label, style: { dim: true } }];
|
|
81
|
+
if (snipLen > 0) spans.push({ text: ' ' + '·'.repeat(snipLen), style: { dim: true } });
|
|
82
|
+
draw.spans(row, rect.col + 1, spans, rect.width - 1);
|
|
83
|
+
}
|
|
84
|
+
if (opts.label) {
|
|
85
|
+
const below = { row: rect.row + n + 1, col: rect.col, width: rect.width, height: Math.max(0, rect.height - n - 1) };
|
|
86
|
+
centeredStack(draw, below, [[{ text: opts.label, style: { dim: true } }]]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Empty — the reward state. A small centered stack: a green `✓`, a default-weight
|
|
92
|
+
* headline, then dim secondary lines. Inbox-zero is a reward, not a void.
|
|
93
|
+
*
|
|
94
|
+
* @param {Draw} draw
|
|
95
|
+
* @param {Rect} rect
|
|
96
|
+
* @param {{ glyph?: string, headline?: string, secondary?: string|string[] }} [opts]
|
|
97
|
+
*/
|
|
98
|
+
export function emptyState(draw, rect, opts = {}) {
|
|
99
|
+
const glyph = opts.glyph ?? '✓';
|
|
100
|
+
const headline = opts.headline ?? 'All caught up';
|
|
101
|
+
/** @type {Span[][]} */
|
|
102
|
+
const lines = [
|
|
103
|
+
[{ text: glyph + ' ', style: { fg: '32' } }, { text: headline }], // green glyph + default headline
|
|
104
|
+
[{ text: '' }],
|
|
105
|
+
];
|
|
106
|
+
for (const t of toLines(opts.secondary)) lines.push([{ text: t, style: { dim: true } }]);
|
|
107
|
+
centeredStack(draw, rect, lines);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Error — a centered error block, used ONLY when there is no last-known content
|
|
112
|
+
* to keep (on a refresh error with a still-good view, raise a banner instead).
|
|
113
|
+
* `✗` + headline in red/bold, the cause in default weight, a dim retry hint.
|
|
114
|
+
*
|
|
115
|
+
* @param {Draw} draw
|
|
116
|
+
* @param {Rect} rect
|
|
117
|
+
* @param {{ headline?: string, cause?: string|string[], hint?: string }} [opts]
|
|
118
|
+
*/
|
|
119
|
+
export function errorState(draw, rect, opts = {}) {
|
|
120
|
+
const headline = opts.headline ?? 'Something went wrong';
|
|
121
|
+
const cause = toLines(opts.cause);
|
|
122
|
+
const hint = opts.hint ?? 'Press g to retry.';
|
|
123
|
+
/** @type {Span[][]} */
|
|
124
|
+
const lines = [
|
|
125
|
+
[{ text: '✗ ', style: { fg: '31', bold: true } }, { text: headline, style: { fg: '31', bold: true } }],
|
|
126
|
+
[{ text: '' }],
|
|
127
|
+
];
|
|
128
|
+
for (const t of cause) lines.push([{ text: t }]);
|
|
129
|
+
if (cause.length) lines.push([{ text: '' }]);
|
|
130
|
+
if (hint) lines.push([{ text: hint, style: { dim: true } }]);
|
|
131
|
+
centeredStack(draw, rect, lines);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Not-ready / guided takeover — the full-content recovery substrate (design §5).
|
|
136
|
+
* A centered stack: a state glyph (its hue passed by the caller, mono-safe via
|
|
137
|
+
* the glyph itself), a bold headline naming the state, a dim explanation, and the
|
|
138
|
+
* explicit next step (an auto-progress note the view writes, or a key to press).
|
|
139
|
+
*
|
|
140
|
+
* @param {Draw} draw
|
|
141
|
+
* @param {Rect} rect
|
|
142
|
+
* @param {{ glyph?: string, glyphFg?: string, headline?: string, explanation?: string|string[], nextStep?: string }} [opts]
|
|
143
|
+
* glyphFg — NUMERIC SGR code for the glyph hue (e.g. '36' cyan working, '31' red blocked).
|
|
144
|
+
*/
|
|
145
|
+
export function notReadyState(draw, rect, opts = {}) {
|
|
146
|
+
const glyph = opts.glyph ?? '⊙';
|
|
147
|
+
/** @type {Style} */
|
|
148
|
+
const glyphStyle = opts.glyphFg ? { fg: opts.glyphFg, bold: true } : { bold: true };
|
|
149
|
+
const headline = opts.headline ?? 'Not ready';
|
|
150
|
+
/** @type {Span[][]} */
|
|
151
|
+
const lines = [
|
|
152
|
+
[{ text: glyph + ' ', style: glyphStyle }, { text: headline, style: { bold: true } }],
|
|
153
|
+
[{ text: '' }],
|
|
154
|
+
];
|
|
155
|
+
for (const t of toLines(opts.explanation)) lines.push([{ text: t, style: { dim: true } }]);
|
|
156
|
+
if (opts.nextStep) {
|
|
157
|
+
lines.push([{ text: '' }]);
|
|
158
|
+
lines.push([{ text: opts.nextStep }]); // default weight — the call to action
|
|
159
|
+
}
|
|
160
|
+
centeredStack(draw, rect, lines);
|
|
161
|
+
}
|