@north-light/crouter 0.3.164 → 0.3.166
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.d.ts +6 -6
- package/dist/build-root.js +12 -13
- package/dist/builtin-memory/00-runtime-base.md +3 -4
- package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
- package/dist/builtin-memory/02-lifecycle/00-terminal.md +2 -0
- package/dist/builtin-memory/04-orchestration-kernel.md +16 -18
- package/dist/builtin-memory/05-kinds/advisor/00-base.md +0 -2
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +3 -9
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -3
- package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +2 -10
- package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +0 -2
- package/dist/builtin-memory/05-kinds/general/00-base.md +3 -5
- package/dist/builtin-memory/05-kinds/general/01-orchestrator.md +0 -4
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +12 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -2
- package/dist/builtin-memory/05-kinds/review/00-base.md +0 -2
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -3
- package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +2 -4
- package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -1
- package/dist/builtin-memory/advisor/council.md +40 -0
- package/dist/builtin-memory/design.md +8 -11
- package/dist/builtin-memory/development.md +6 -9
- package/dist/builtin-memory/internal/INDEX.md +4 -5
- package/dist/builtin-memory/internal/agent-shaping.md +5 -7
- package/dist/builtin-memory/internal/examples/imessage-assistant.md +3 -3
- package/dist/builtin-memory/internal/marketplaces.md +13 -14
- package/dist/builtin-memory/internal/nodes-and-canvas.md +4 -4
- package/dist/builtin-memory/internal/plugins.md +61 -45
- package/dist/builtin-memory/planning.md +4 -7
- package/dist/builtin-memory/spec.md +9 -12
- package/dist/builtin-memory/wedged-child-on-runaway-bash.md +8 -22
- package/dist/cli.js +1 -1
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +17 -4
- package/dist/clients/attach/__tests__/context-message.test.js +62 -22
- package/dist/clients/attach/__tests__/crtr-output.test.js +39 -30
- package/dist/clients/attach/render/chat-view.d.ts +20 -20
- package/dist/clients/attach/render/chat-view.js +40 -54
- package/dist/clients/attach/render/{frozen-history.d.ts → condensed-history.d.ts} +1 -18
- package/dist/clients/attach/render/condensed-history.js +60 -0
- package/dist/clients/attach/render/context-message.d.ts +1 -1
- package/dist/clients/attach/render/context-message.js +18 -41
- package/dist/clients/attach/session/bindings.d.ts +5 -3
- package/dist/clients/attach/session/bindings.js +7 -13
- package/dist/clients/attach/session/keys.d.ts +2 -0
- package/dist/clients/attach/session/keys.js +36 -37
- package/dist/clients/attach/session/profile-files.d.ts +8 -0
- package/dist/clients/attach/session/profile-files.js +157 -0
- package/dist/clients/attach/viewer.js +528 -529
- package/dist/commands/node-context.js +3 -2
- package/dist/commands/node.js +2 -2
- package/dist/commands/pkg/plugin-inspect.js +6 -7
- package/dist/commands/pkg/plugin-manage.d.ts +1 -1
- package/dist/commands/pkg/plugin-manage.js +131 -19
- package/dist/commands/pkg/plugin.js +2 -2
- package/dist/commands/pkg.js +6 -11
- package/dist/commands/profile/env.js +3 -3
- package/dist/commands/sys/config.js +17 -76
- package/dist/commands/sys/doctor.js +5 -91
- package/dist/commands/sys/setup-wizard.d.ts +9 -11
- package/dist/commands/sys/setup-wizard.js +47 -81
- package/dist/core/__tests__/base-worker-prompt.test.js +18 -21
- package/dist/core/__tests__/command-plugins-surfaces.test.js +39 -5
- package/dist/core/__tests__/command-plugins.test.js +75 -16
- package/dist/core/__tests__/review-model-floor.test.js +2 -2
- package/dist/core/__tests__/tmux-surface.test.js +10 -1
- package/dist/core/command-manifests/manifest.d.ts +24 -0
- package/dist/core/{configured-clis → command-manifests}/manifest.js +28 -25
- package/dist/core/command-manifests/registry.d.ts +1 -2
- package/dist/core/command-manifests/registry.js +2 -2
- package/dist/core/command-manifests/schema.d.ts +11 -13
- package/dist/core/command-manifests/schema.js +53 -192
- package/dist/core/command-plugins/compose.d.ts +0 -6
- package/dist/core/command-plugins/compose.js +32 -75
- package/dist/core/command-plugins/discovery.d.ts +25 -58
- package/dist/core/command-plugins/discovery.js +171 -261
- package/dist/core/command-plugins/endpoint.d.ts +24 -0
- package/dist/core/command-plugins/endpoint.js +48 -0
- package/dist/core/command-plugins/store.d.ts +16 -0
- package/dist/core/command-plugins/store.js +64 -0
- package/dist/core/command-plugins/{adapter.d.ts → transport/exec-invoke.d.ts} +3 -3
- package/dist/core/command-plugins/{adapter.js → transport/exec-invoke.js} +4 -4
- package/dist/core/{configured-clis/fetch.d.ts → command-plugins/transport/http-fetch.d.ts} +9 -18
- package/dist/core/{configured-clis/fetch.js → command-plugins/transport/http-fetch.js} +15 -35
- package/dist/core/{configured-clis/invoker.d.ts → command-plugins/transport/http-invoke.d.ts} +7 -7
- package/dist/core/{configured-clis/invoker.js → command-plugins/transport/http-invoke.js} +21 -23
- package/dist/core/command.d.ts +8 -9
- package/dist/core/command.js +6 -9
- package/dist/core/config.js +6 -10
- package/dist/core/env-name.d.ts +6 -0
- package/dist/core/env-name.js +9 -0
- package/dist/core/io.d.ts +1 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +40 -3
- package/dist/core/keybindings/attach-control.d.ts +37 -0
- package/dist/core/keybindings/attach-control.js +38 -0
- package/dist/core/keybindings/catalog.d.ts +5 -4
- package/dist/core/keybindings/catalog.js +16 -8
- package/dist/core/keybindings/index.d.ts +1 -0
- package/dist/core/keybindings/index.js +1 -0
- package/dist/core/keybindings/types.d.ts +1 -1
- package/dist/core/preview-registry.js +41 -74
- package/dist/core/runtime/bearings.d.ts +2 -5
- package/dist/core/runtime/bearings.js +2 -5
- package/dist/core/runtime/broker.js +3 -2
- package/dist/core/runtime/front-door.d.ts +1 -1
- package/dist/core/runtime/front-door.js +2 -2
- package/dist/core/runtime/kickoff.d.ts +3 -3
- package/dist/core/runtime/kickoff.js +4 -3
- package/dist/core/runtime/lifecycle.js +2 -2
- package/dist/core/runtime/situational-context.d.ts +1 -1
- package/dist/core/runtime/situational-context.js +1 -1
- package/dist/core/runtime/spawn.js +9 -9
- package/dist/core/runtime/tmux.js +29 -2
- package/dist/core/scope.d.ts +0 -5
- package/dist/core/scope.js +0 -10
- package/dist/core/user-settings.d.ts +193 -0
- package/dist/core/user-settings.js +252 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/pi-extensions/canvas-stophook.js +3 -2
- package/dist/prompts/review.js +4 -2
- package/dist/shared/generated-context.d.ts +34 -0
- package/dist/shared/generated-context.js +98 -0
- package/dist/types.d.ts +23 -16
- package/dist/types.js +3 -14
- package/dist/web-client/assets/index-BgLGlZ3D.css +2 -0
- package/dist/web-client/assets/{index-NIuSCOHM.js → index-CmoNqcCv.js} +19 -19
- package/dist/web-client/index.html +2 -2
- package/dist/web-client/sw.js +1 -1
- package/docs/public-api.md +1 -0
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/builtin-memory/05-kinds/product/00-base.md +0 -25
- package/dist/builtin-memory/05-kinds/product/01-orchestrator.md +0 -15
- package/dist/builtin-memory/05-kinds/product/teardown.md +0 -15
- package/dist/builtin-memory/internal/workflow-codification.md +0 -82
- package/dist/builtin-memory/product.md +0 -80
- package/dist/clients/attach/render/frozen-history.js +0 -100
- package/dist/commands/pkg/cli-inspect.d.ts +0 -17
- package/dist/commands/pkg/cli-inspect.js +0 -190
- package/dist/commands/pkg/cli-manage.d.ts +0 -3
- package/dist/commands/pkg/cli-manage.js +0 -206
- package/dist/commands/pkg/cli.d.ts +0 -1
- package/dist/commands/pkg/cli.js +0 -14
- package/dist/core/configured-clis/cache.d.ts +0 -16
- package/dist/core/configured-clis/cache.js +0 -57
- package/dist/core/configured-clis/compose.d.ts +0 -14
- package/dist/core/configured-clis/compose.js +0 -60
- package/dist/core/configured-clis/discovery.d.ts +0 -47
- package/dist/core/configured-clis/discovery.js +0 -173
- package/dist/core/configured-clis/manifest.d.ts +0 -24
- package/dist/core/configured-clis/registration.d.ts +0 -40
- package/dist/core/configured-clis/registration.js +0 -201
- package/dist/web-client/assets/index-CqLKj8Xu.css +0 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: knowledge
|
|
3
|
+
when-and-why-to-read: When convening an advisor council for a consequential judgment, this knowledge should be read because disciplined independent evidence prevents a confident consensus from concealing a correlated error.
|
|
4
|
+
short-form: Run a bounded, evidence-first advisor council for consequential judgments.
|
|
5
|
+
system-prompt-visibility: none
|
|
6
|
+
file-read-visibility: none
|
|
7
|
+
rationale: >-
|
|
8
|
+
Everyone's instinct for getting the right answer out of a council is to make the agents
|
|
9
|
+
debate until they agree — and that instinct is empirically backwards. Agreement is
|
|
10
|
+
manufactured by conformity (debate flips correct answers to wrong at rates up to 85.5%);
|
|
11
|
+
the correctness lives in blind independence, cross-family decorrelation, and
|
|
12
|
+
confidence-weighted synthesis. Without this methodology an orchestrator runs a persuasion
|
|
13
|
+
contest and ships its overconfident output as a verdict.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Advisor Council Methodology
|
|
17
|
+
|
|
18
|
+
Use a council only for a consequential judgment where the cost of being wrong justifies deliberation. An ordinary second opinion needs one advisor or a few un-orchestrated advisors.
|
|
19
|
+
|
|
20
|
+
## First round
|
|
21
|
+
|
|
22
|
+
Spawn three to five advisors in parallel. Keep their work blind: no member sees another's analysis. Assign each the same question under a distinct evidence frame, prior to steelman, or decomposition. Select members from the live model configuration; when distinct model families are available, span them to reduce correlated error rather than assuming any particular route.
|
|
23
|
+
|
|
24
|
+
Ask every member for a recommendation, calibrated numeric confidence, strongest private reason, and key evidence. Members contribute read-only judgment; the council orchestrator is the only verdict writer.
|
|
25
|
+
|
|
26
|
+
## Synthesis
|
|
27
|
+
|
|
28
|
+
Synthesize as a chairman, not a vote. Weight recommendations by confidence and evidence quality, retain each original answer, and preserve a well-supported minority. Treat unanimity as a cue to check for correlation or false convergence, not as proof. Commit to the best-supported recommendation rather than averaging independent opinions into an under-confident compromise.
|
|
29
|
+
|
|
30
|
+
Before finalizing, give one clean-context advisor a prospective-hindsight pre-mortem: the draft verdict was adopted and failed; explain why. Prefer a model family different from the members that dominated the draft. Incorporate confirmed concerns or report them as accepted risks.
|
|
31
|
+
|
|
32
|
+
## Disagreement
|
|
33
|
+
|
|
34
|
+
Open one targeted second round only when members disagree on a named, verifiable crux such as code, tests, documentation, or quotable evidence. Share only anonymized claim, reason, and evidence snippets about that crux; remove author, model, and conclusion labels. Have advisors verify and attack those claims directly. Stop after that round when positions stabilize.
|
|
35
|
+
|
|
36
|
+
A crux about judgment, taste, or values does not earn a persuasion contest. Adjudicate it or surface it to the owner as a named tradeoff.
|
|
37
|
+
|
|
38
|
+
## Verdict
|
|
39
|
+
|
|
40
|
+
Deliver one conclusion-first verdict: recommendation and confidence, the strongest opposing case and why it lost, and any residual disagreement with its crux. Do not forward raw member output or dissolve disagreement into false consensus.
|
|
@@ -7,12 +7,9 @@ short-form: Use when shaping a design roadmap or producing an
|
|
|
7
7
|
architecture/interface design — covers what a design deliverable is, the
|
|
8
8
|
design-artifact shape, when to go top-down vs bottom-up, and how to decompose
|
|
9
9
|
a large design into composable sub-designs.
|
|
10
|
-
system-prompt-visibility:
|
|
10
|
+
system-prompt-visibility: preview
|
|
11
11
|
file-read-visibility: none
|
|
12
|
-
gate:
|
|
13
|
-
kind:
|
|
14
|
-
imatches: '^design($|/)'
|
|
15
|
-
needs-refinement: true
|
|
12
|
+
gate: {kind: design}
|
|
16
13
|
---
|
|
17
14
|
|
|
18
15
|
## What a design deliverable is — and is not
|
|
@@ -25,11 +22,11 @@ The altitude ceiling: a design stops where implementation detail begins. A plann
|
|
|
25
22
|
|
|
26
23
|
## The design-artifact shape
|
|
27
24
|
|
|
28
|
-
Write the design to
|
|
25
|
+
Write the design to `$CRTR_CONTEXT_DIR/design-<subject>.md`. Structure it with these sections, in order:
|
|
29
26
|
|
|
30
27
|
**Context & constraints** — the problem being solved, the non-goals, the constraints that are not negotiable (existing systems, performance envelopes, team conventions). This is the frame everything else hangs on.
|
|
31
28
|
|
|
32
|
-
**Architecture** — the high-level structure: what major components or layers exist, how they are arranged, what the topology looks like. Lead with a diagram (mermaid `graph TD
|
|
29
|
+
**Architecture** — the high-level structure: what major components or layers exist, how they are arranged, what the topology looks like. Lead with a diagram (mermaid `graph TD`) before prose. Keep it at the level a new engineer would use to orient themselves.
|
|
33
30
|
|
|
34
31
|
**Components & responsibilities** — for each component: one-sentence description of what it owns, a responsibilities table, and explicit boundaries (what it does NOT own). Every responsibility must land in exactly one component; gaps and overlaps here become integration bugs.
|
|
35
32
|
|
|
@@ -37,7 +34,7 @@ Write the design to `context/design-<subject>.md`. Structure it with these secti
|
|
|
37
34
|
|
|
38
35
|
**Data model** — the key entities, their fields with semantic types ("session ID string", "ISO timestamp"), and their relationships. Tables are the right format. No TypeScript, no SQL — shape and semantics only.
|
|
39
36
|
|
|
40
|
-
**Key flows** — the
|
|
37
|
+
**Key flows** — the end-to-end flows that matter most. Walk from trigger to final state, naming which component handles each step and what state changes. This is where seam problems surface; a step whose output doesn't match the next step's expected input is a design gap.
|
|
41
38
|
|
|
42
39
|
**Decisions** — every non-obvious architectural choice, structured as: decision → choice made → alternatives rejected → rationale. If the decision is obvious, omit it. If it closes a real option, it belongs here. This section is what distinguishes a design from a description.
|
|
43
40
|
|
|
@@ -55,8 +52,8 @@ Write the design to `context/design-<subject>.md`. Structure it with these secti
|
|
|
55
52
|
|
|
56
53
|
When a design is too large for one context window or covers genuinely independent surfaces, decompose it along clean seams — by component, by subsystem, or by interaction surface. Each sub-design is a bounded unit: it covers one component or subsystem end-to-end (its own context, architecture, interfaces, data model, flows, and decisions).
|
|
57
54
|
|
|
58
|
-
Before delegating sub-designs, define the shared interface contracts between them explicitly. These contracts are the seams; they must be written down before sub-design begins so that parallel sub-designs don't invent incompatible assumptions. Capture these contracts in
|
|
55
|
+
Before delegating sub-designs, define the shared interface contracts between them explicitly. These contracts are the seams; they must be written down before sub-design begins so that parallel sub-designs don't invent incompatible assumptions. Capture these contracts in `$CRTR_CONTEXT_DIR/design-contracts.md` and give that absolute path to every sub-design agent.
|
|
59
56
|
|
|
60
|
-
Each sub-design agent gets: the overall architecture diagram, the contracts doc, the scope of its piece, and any constraints from the parent design. It writes
|
|
57
|
+
Each sub-design agent gets: the overall architecture diagram, the contracts doc, the scope of its piece, and any constraints from the parent design. It writes `design-<component>.md` in its own context directory and reports the absolute path.
|
|
61
58
|
|
|
62
|
-
After sub-designs land, integration is your job: read every sub-design, check that every contract is honored on both sides, that responsibilities don't overlap or gap, that the data models are consistent, and that the key flows compose correctly across component boundaries. Write the integrated design to
|
|
59
|
+
After sub-designs land, integration is your job: read every sub-design, check that every contract is honored on both sides, that responsibilities don't overlap or gap, that the data models are consistent, and that the key flows compose correctly across component boundaries. Write the integrated design to `$CRTR_CONTEXT_DIR/design-<subject>.md`, synthesizing all sub-designs into one coherent artifact — don't just concatenate them. Reconcile any inconsistencies before declaring the design done.
|
|
@@ -7,12 +7,9 @@ when-and-why-to-read: When shaping or reshaping a build roadmap — choosing a
|
|
|
7
7
|
short-form: Use when shaping or reshaping a build roadmap — choosing a
|
|
8
8
|
development style, selecting a phase skeleton, or setting exit criteria for a
|
|
9
9
|
software goal.
|
|
10
|
-
system-prompt-visibility:
|
|
10
|
+
system-prompt-visibility: preview
|
|
11
11
|
file-read-visibility: none
|
|
12
|
-
gate:
|
|
13
|
-
kind:
|
|
14
|
-
imatches: '^developer$'
|
|
15
|
-
needs-refinement: true
|
|
12
|
+
gate: {kind: developer}
|
|
16
13
|
---
|
|
17
14
|
|
|
18
15
|
# Development Playbook
|
|
@@ -40,9 +37,9 @@ Pick one style as your primary frame before you write phases. Each fits a differ
|
|
|
40
37
|
These are concrete phase skeletons. Adapt names and granularity; don't add phases that serve no exit criterion.
|
|
41
38
|
|
|
42
39
|
### New feature
|
|
43
|
-
1. **Explore** — map the affected subsystems, identify entry points and constraints,
|
|
44
|
-
2. **Spec** — define the interface,
|
|
45
|
-
3. **Plan** — decompose spec into file-level tasks with dependency order
|
|
40
|
+
1. **Explore** — map the affected subsystems, identify entry points and constraints, and report the absolute path to the exploration artifact.
|
|
41
|
+
2. **Spec** — define the interface, behavior, and acceptance criteria, then report the absolute path to the spec.
|
|
42
|
+
3. **Plan** — decompose the spec into file-level tasks with dependency order, then report the absolute path to the plan.
|
|
46
43
|
4. **Vertical slice** — implement the thinnest end-to-end path; validate it works before widening.
|
|
47
44
|
5. **Harden** — fill out the remaining logic, edge cases, error paths.
|
|
48
45
|
6. **Review** — non-implementer critique pass on the whole surface.
|
|
@@ -65,7 +62,7 @@ These are concrete phase skeletons. Adapt names and granularity; don't add phase
|
|
|
65
62
|
### Greenfield
|
|
66
63
|
1. **Explore/research** — understand the problem domain, constraints, and comparable systems.
|
|
67
64
|
2. **Spec** — define the interface and top-level behaviour in enough detail to plan.
|
|
68
|
-
3. **Architecture decision** — commit to the structural shape
|
|
65
|
+
3. **Architecture decision** — commit to the structural shape and report the absolute path to the architecture artifact.
|
|
69
66
|
4. **Spike** (if technical unknowns exist) — validate the risky piece before building around it.
|
|
70
67
|
5. **Bottom-up build** — primitives first, then composition; validate each layer before building on it.
|
|
71
68
|
6. **Integration** — assemble layers; validate end-to-end.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
kind: knowledge
|
|
3
3
|
when-and-why-to-read: When you hit a question about how the crtr runtime itself works or how to extend it — how nodes and the canvas behave, where state lives on disk, how to add plugins/commands/marketplaces to crtr, or how the primitives compose into real systems — this index should be read so runtime-sensitive work follows the canonical model instead of fragile inferences from scattered command help.
|
|
4
|
-
short-form: internal/ is the runtime's self- and developer-documentation — operational guides to nodes/canvas and the storage tiers, plugin
|
|
4
|
+
short-form: internal/ is the runtime's self- and developer-documentation — operational guides to nodes/canvas and the storage tiers, plugin command and marketplace authoring, plus worked example compositions. Open it to understand how crtr works or to extend it.
|
|
5
5
|
system-prompt-visibility: preview
|
|
6
6
|
file-read-visibility: none
|
|
7
7
|
---
|
|
@@ -16,13 +16,12 @@ Open this dir whenever a task turns on understanding the runtime itself or chang
|
|
|
16
16
|
- **storage-tiers** — where every kind of state lives: the two tiers (scope root and canvas home) and their durability/ownership contracts.
|
|
17
17
|
- **memory-loading** — the memory load model: the two hooks (boot catalog, file-read), the four-rung ladder, gates, applies-to/read-when routing, boot-render ordering, and store mounting/precedence — read when diagnosing why a doc did or didn't load.
|
|
18
18
|
- **agent-shaping** — the when-to-use-which layer over the four dials that shape a node: kinds (the builtin roster, sub-kinds, and custom personas), modes (base vs orchestrator), profiles, and the memory tiers (node/profile/project/user/builtin).
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
- **marketplaces** — authoring a crtr marketplace: the marketplace.json index, plugin entries, symlink-based install, auto-bump CI, dual-publishing.
|
|
19
|
+
- **plugins** — authoring a crtr plugin: the plugin.json manifest, directory layout, scopes, install mechanics, versioning, and command-capable plugins (contributing top-level CLI commands through commands.json plus an exec or HTTP transport).
|
|
20
|
+
- **marketplaces** — authoring a crtr marketplace: the marketplace.json index, local-link and remote-Git plugin sources, auto-bump CI, dual-publishing.
|
|
22
21
|
- **examples/** — worked compositions of the primitives into complete systems (the analogue of pi's `examples/` dir), e.g. the iMessage assistant node.
|
|
23
22
|
|
|
24
23
|
Adjacent, outside this dir: authoring memory documents (kind, rungs, gates, routing line, the asked-to-remember workflow) is owned by `crtr memory write -h` — the authoring guide lives on that `-h` surface so it surfaces exactly when you write.
|
|
25
24
|
|
|
26
|
-
Briefly: **plugins**
|
|
25
|
+
Briefly: **plugins** package docs and commands, with command execution selected by `plugin.json.transport` (`exec` for a trusted local executable or `http` for a fetched remote REST manifest); **marketplaces** index and distribute plugins. Plugin commands enter the **external-command** fallthrough, leaving the core fast-path untouched.
|
|
27
26
|
|
|
28
27
|
The individual files surface at `name` (their titles route; open the one the situation calls for); this index surfaces at `preview` so the dir announces when to come looking.
|
|
@@ -38,25 +38,23 @@ A kind is a **persona** (gated memory docs at `kinds/<kind>/00-base.md` and `01-
|
|
|
38
38
|
| **plan** | decompose an approved spec/design into concrete, phased, parallelizable steps with every decision resolved | you have a spec or design and need an executable breakdown a less-capable model can run without re-deciding. A plan 80% right costs more than no plan — pin every decision |
|
|
39
39
|
| **developer** | implement a change and make it *genuinely work* against acceptance criteria, not merely compile | you're building the feature or fix. Green proves it ran, not that it's right — the persona carries the prove-it discipline and the build→review cycle |
|
|
40
40
|
| **review** | critique code, a plan, or a spec once — deliver a complete, severity-rated verdict, **detect don't adjudicate** | substantive work needs one independent check. Use a *separate* node from the author — agents can't self-audit — and prime it neutrally ("review this", never "find what fails", which manufactures false positives) |
|
|
41
|
-
| **product** | discover the real user need behind a request and define the product experience, grounded in comparable products; hands off to spec | the client is non-technical and the *what-and-why* must be found before any spec. **Speculative** — the product→spec baton has not yet run end to end |
|
|
42
|
-
| **personal-assistant** | Silas's standing personal assistant — resident on the canvas, wakes on his iMessage thread, remembers across conversations | only for that standing assistant role (resident lifecycle), not general work |
|
|
43
41
|
|
|
44
|
-
The discriminators that get missed: **explore vs advisor** (mapping vs judgment — cheap vs expensive tier); **spec vs design** (what to build vs how to build it); **design vs plan** (decide the shape vs sequence a decided shape); **review is always a separate node from the implementer**.
|
|
42
|
+
The discriminators that get missed: **explore vs advisor** (mapping vs judgment — cheap vs expensive tier); **spec vs design** (what to build vs how to build it); **design vs plan** (decide the shape vs sequence a decided shape); **review is always a separate node from the implementer**. **Developer is the kind closest to "general with a mood"** — the first merge candidate if the roster ever shrinks.
|
|
45
43
|
|
|
46
44
|
### Sub-kinds
|
|
47
45
|
|
|
48
|
-
Specialist sub-personas hang off a parent kind — `plan/reviewers/*` (architecture-fit, code-smells, pattern-consistency, requirements-coverage, security)
|
|
46
|
+
Specialist sub-personas hang off a parent kind — `plan/reviewers/*` (architecture-fit, code-smells, pattern-consistency, requirements-coverage, security) and `spec/requirements`. They aren't in the top-level `--kind` list but are valid by exact path (`crtr node new --kind plan/reviewers/security`). Use a sub-persona for one narrowly targeted assignment, not as a mandatory lens roster; discover the available roles with `crtr sys prompt-review --list --kind <kind>`.
|
|
49
47
|
|
|
50
48
|
### Custom personas
|
|
51
49
|
|
|
52
|
-
The roster is extensible. Add a `kinds.<name>` entry to a `config.json` at user or project scope (fields: `whenToUse` required, plus optional `model`, `orchestratorModel`, `tools`, `extensions`, `availableTo`) and author the persona prose at `kinds/<name>/00-base.md` (and `01-orchestrator.md`) gated `{kind: <name>, mode: ...}`. The registry merges **project > user > builtin**, so a custom kind can add a new role or shadow a builtin one without restating the rest. Reach for a custom kind when a **recurring role** wants its own standing discipline and model/tool defaults that outlast any single task — not for a one-off instruction, which belongs in the spawn prompt.
|
|
50
|
+
The roster is extensible. Add a `kinds.<name>` entry to a `config.json` at user or project scope (fields: `whenToUse` required, plus optional `model`, `orchestratorModel`, `tools`, `extensions`, `availableTo`) and author the persona prose at `kinds/<name>/00-base.md` (and `01-orchestrator.md`) gated `{kind: <name>, mode: ...}`. A standing personal assistant, for example, is a scope-configured custom `personal-assistant` kind rather than a builtin kind. The registry merges **project > user > builtin**, so a custom kind can add a new role or shadow a builtin one without restating the rest. Reach for a custom kind when a **recurring role** wants its own standing discipline and model/tool defaults that outlast any single task — not for a one-off instruction, which belongs in the spawn prompt.
|
|
53
51
|
|
|
54
52
|
## Modes — base vs orchestrator
|
|
55
53
|
|
|
56
54
|
Every kind has both a `base` and an `orchestrator` persona; mode picks which one splices in.
|
|
57
55
|
|
|
58
|
-
- **base** — hands-on. Do the work yourself and
|
|
59
|
-
- **orchestrator** — you own a goal too large for one window. Decompose it, delegate each piece, integrate what comes back, hold a
|
|
56
|
+
- **base** — hands-on. Do the work yourself and deliver its artifact path. Your scarce resource is the task. Spawn a child only for a cleanly separable unit, never as your first move. When an unsplittable task needs another context window, `crtr node yield` and continue hands-on as base.
|
|
57
|
+
- **orchestrator** — you own a goal too large for one window. Decompose it, delegate each piece, integrate what comes back, hold a `$CRTR_CONTEXT_DIR/roadmap.md` that survives refreshes, and yield (`crtr node yield`) into a clean window when context fills. Your scarce resource is your own context window; the moment you start grinding the goal out by hand you've lost the plot. The shared loop lives in the `orchestration-kernel` doc (auto-gated for orchestrators).
|
|
60
58
|
|
|
61
59
|
**When to reach for orchestrator over base.** When the *shape* of the job needs decomposition across children — many phases visible up front, or a base task that keeps getting extended into independently delegable work. Promote *early* (`crtr node promote`), the moment you recognize that shape, not after the window wears down; or spawn the child directly as a sub-orchestrator (`crtr node new --mode orchestrator`) rather than hoping a base worker promotes itself, which is unreliable. An unsplittable task that merely needs another context window stays base: `crtr node yield` and continue hands-on.
|
|
62
60
|
|
|
@@ -21,7 +21,7 @@ A standing assistant that lives on the canvas, sleeps for free, wakes when a tex
|
|
|
21
21
|
| Sends replies | `osascript` → Messages.app |
|
|
22
22
|
| Memory | Project-scope substrate (`~/assistants/imessage/.crouter/memory/`) for durable knowledge; context dir for the cursor |
|
|
23
23
|
| Identity/behavior | A custom persona kind |
|
|
24
|
-
| Crash recovery | The daemon
|
|
24
|
+
| Crash recovery | The daemon makes bounded recovery attempts for interrupted live exits; after terminalization, use `node lifecycle revive` or let the watcher's `node message send` wake the resident target |
|
|
25
25
|
|
|
26
26
|
## 1. Persona
|
|
27
27
|
|
|
@@ -40,7 +40,7 @@ EOF
|
|
|
40
40
|
|
|
41
41
|
## 3. Wake: event-driven, not polled
|
|
42
42
|
|
|
43
|
-
A trivial launchd agent watches the Messages write-ahead log and pokes the node's inbox. `node message send`
|
|
43
|
+
A trivial launchd agent watches the Messages write-ahead log and pokes the node's inbox. `node message send` wakes the resident target by itself, including after a recoverable disconnection, so the watcher is the *only* off-canvas piece.
|
|
44
44
|
|
|
45
45
|
```xml
|
|
46
46
|
<!-- ~/Library/LaunchAgents/com.user.imessage-watch.plist (key parts) -->
|
|
@@ -56,7 +56,7 @@ Multiple bursts while the node is mid-turn just append to its inbox and coalesce
|
|
|
56
56
|
## 4. Reading chat.db (the verified gotchas)
|
|
57
57
|
|
|
58
58
|
- The process querying needs **Full Disk Access** (the node's shell inherits the terminal/launchd grant). Read-only — never write to chat.db.
|
|
59
|
-
- Cursor on `message.ROWID`, persisted in the node's context dir (e.g.
|
|
59
|
+
- Cursor on `message.ROWID`, persisted in the node's context dir (e.g. `$CRTR_CONTEXT_DIR/cursor`); filter `is_from_me = 0`.
|
|
60
60
|
- **On modern macOS `message.text` is often NULL** — the body lives in the `attributedBody` blob (NSAttributedString archive). Extract with:
|
|
61
61
|
|
|
62
62
|
```python
|
|
@@ -8,7 +8,6 @@ short-form: How to author a crtr marketplace — marketplace.json index, plugin
|
|
|
8
8
|
creating a marketplace or contributing plugins to one.
|
|
9
9
|
system-prompt-visibility: name
|
|
10
10
|
file-read-visibility: none
|
|
11
|
-
needs-refinement: true
|
|
12
11
|
---
|
|
13
12
|
|
|
14
13
|
# Authoring crtr marketplaces
|
|
@@ -42,7 +41,7 @@ If you have one plugin, ship it standalone. Promote to a marketplace later.
|
|
|
42
41
|
└── ...
|
|
43
42
|
```
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
A marketplace can keep a plugin under `plugins/` or index a plugin from another Git repository. Local entries are complete plugins (see [[internal/plugins]]); the marketplace adds an index over either source.
|
|
46
45
|
|
|
47
46
|
## The manifest
|
|
48
47
|
|
|
@@ -72,16 +71,16 @@ Each entry under `plugins/` is a complete plugin (see [[internal/plugins]]). The
|
|
|
72
71
|
| `owner` | optional | |
|
|
73
72
|
| `plugins` | yes | Array. Each entry: `name`, `version`, `source`, `description`. |
|
|
74
73
|
|
|
75
|
-
The `plugins[]` array IS the index — what's installable. A plugin on disk but not in the index won't resolve
|
|
74
|
+
The `plugins[]` array IS the index — what's installable. Each entry's `source` is either a marketplace-relative path to a plugin directory or a remote Git URL. A local plugin on disk but not in the index won't resolve; an indexed local path missing from the marketplace errors on install.
|
|
76
75
|
|
|
77
|
-
## Install mechanics —
|
|
76
|
+
## Install mechanics — local links and remote clones
|
|
78
77
|
|
|
79
|
-
When a user runs `crtr pkg plugin install my-marketplace/plugin-a
|
|
80
|
-
1. Crouter looks up `plugin-a` in the marketplace's manifest.
|
|
81
|
-
2. **Symlinks** `<marketplace-clone>/plugins/plugin-a/` → `<user-scope>/plugins/plugin-a/`.
|
|
82
|
-
3. Records the install in the scope config with `source_marketplace: my-marketplace`.
|
|
78
|
+
When a user runs `crtr pkg plugin install my-marketplace/plugin-a`, crouter looks up `plugin-a` in the marketplace manifest and records the install with `source_marketplace: my-marketplace`.
|
|
83
79
|
|
|
84
|
-
|
|
80
|
+
- A marketplace-relative `source` is symlinked from the marketplace checkout into the target scope, so `crtr pkg market update --name my-marketplace` updates its content through that checkout.
|
|
81
|
+
- A remote Git `source` is cloned into the target scope. Marketplace update refreshes the index; the installed plugin's own checkout is pulled during that update (or `crtr pkg plugin update`).
|
|
82
|
+
|
|
83
|
+
No per-plugin re-install is needed for content updates while the indexed source remains unchanged. Changing a remote entry's `source` requires removing and reinstalling that marketplace plugin so its checkout uses the new remote.
|
|
85
84
|
|
|
86
85
|
## Version-bump automation (recommended)
|
|
87
86
|
|
|
@@ -133,11 +132,11 @@ Existing users pick it up on their next `crtr pkg market update --name <marketpl
|
|
|
133
132
|
|
|
134
133
|
## Updating an existing plugin
|
|
135
134
|
|
|
136
|
-
|
|
135
|
+
For a local plugin, edit `plugins/<name>/` and commit the plugin plus marketplace index together. For a remote Git source, update the plugin in its own repository, then update the marketplace entry's version as needed. If its `source` changes, users remove and reinstall the marketplace plugin to clone the replacement remote. Commit with a conventional-commit subject; CI can bump the marketplace index alongside local plugin changes.
|
|
137
136
|
|
|
138
137
|
## Removing a plugin
|
|
139
138
|
|
|
140
|
-
Delete the
|
|
139
|
+
Delete the entry in `marketplace.json` → `plugins[]`; also delete its directory when it is a local source. Commit with `feat!: remove <plugin>` to signal a major bump (the marketplace's contract changed for anyone depending on that plugin).
|
|
141
140
|
|
|
142
141
|
## Marketplace registration scopes
|
|
143
142
|
|
|
@@ -154,10 +153,10 @@ A marketplace itself registers per-scope:
|
|
|
154
153
|
|
|
155
154
|
`crtr sys doctor` checks marketplaces:
|
|
156
155
|
- `marketplace.json` is valid JSON.
|
|
157
|
-
- Every entry in `plugins[]`
|
|
158
|
-
- Each plugin
|
|
156
|
+
- Every marketplace-relative entry in `plugins[]` resolves to a real local plugin directory. Remote-source validation occurs when crouter installs that plugin.
|
|
157
|
+
- Each installed plugin passes plugin-level validation.
|
|
159
158
|
|
|
160
|
-
A plugin on disk but missing from the manifest is a **warning** (probably forgotten);
|
|
159
|
+
A local plugin on disk but missing from the manifest is a **warning** (probably forgotten); an indexed local path missing on disk is an **error** (install would break).
|
|
161
160
|
|
|
162
161
|
## Cross-publishing with Claude Code
|
|
163
162
|
|
|
@@ -14,10 +14,10 @@ The **daemon** (`crtrd`) is the sole owner of canvas persistent state: it is the
|
|
|
14
14
|
|
|
15
15
|
## Spawn & delegate
|
|
16
16
|
|
|
17
|
-
`crtr node new "<task>" --kind <kind>` launches a managed child broker and returns its id immediately; you **auto-subscribe** to it, so its finish wakes you.
|
|
17
|
+
`crtr node new "<task>" --kind <kind>` launches a managed child broker and returns its id immediately; you **auto-subscribe** to it, so its finish wakes you. A base node works hands-on and only spawns a child for a cleanly separable unit. An orchestrator delegates its decomposed work by default: a child's reading and tokens land in a fresh context window while the coordinator keeps only the conclusions needed to steer.
|
|
18
18
|
|
|
19
19
|
- Match `--kind` to the work (`explore spec design plan developer review general`, plus any custom persona). See `node new -h`.
|
|
20
|
-
-
|
|
20
|
+
- An orchestrator fans **independent** units out concurrently. Serialize only true dependencies; never let two live children edit the same files.
|
|
21
21
|
- `--root` spawns an independent node you neither manage nor are woken by (e.g. one a human will drive).
|
|
22
22
|
- Once you delegate a unit, don't also run it yourself — you'll be woken when it finishes.
|
|
23
23
|
|
|
@@ -46,6 +46,6 @@ Tear-down: `node lifecycle close` cascade-cancels a node + its exclusive subtree
|
|
|
46
46
|
|
|
47
47
|
## Revive & the daemon
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Use `node lifecycle revive <id>` to reopen one dormant or terminal node. It resumes an existing saved conversation by default; `--fresh` starts a new cycle on its existing session file, or a truly fresh session if no file exists. A finalized node requires `--reopen` before it can take a new mandate. Mass-reconnecting every eligible disconnected node after a reboot or outage is `canvas revive --all` instead. `reviveNode()` is the **only** sanctioned launcher of a node's broker engine — it builds the pi invocation, sets `CRTR_NODE_ID` + canvas extensions, runs `transition('revive')`, and starts the headless broker host, keeping the db row and broker process in lockstep. Never spawn `pi --session` raw, and never open a node by spawning pi directly — UIs go through `surface node focus` / `node lifecycle revive`.
|
|
50
50
|
|
|
51
|
-
The daemon (`crtrd`, managed via `sys daemon start/stop/status`)
|
|
51
|
+
The daemon (`crtrd`, managed via `sys daemon start/stop/status`) supervises live broker exits. It applies a bounded respawn policy to interrupted nonterminal nodes: a cleanly aborted saved turn resumes with a continuation, while a dirty interrupted turn, pending refresh, or pending cycle starts a fresh cycle from the saved session. Repeated short-lived exits and boot failures terminalize the node as `dead`; no automatic recovery occurs after terminalization, so use an explicit lifecycle revive or an inbox wake. It does not host agents or open viewers. When activating source changes, build, run `npm run install-runtime`, then restart the daemon because new daemon/brokers select the atomically switched, immutable generation while live brokers retain their own. Restarting is safe: it never signals running nodes.
|
|
@@ -5,8 +5,8 @@ when-and-why-to-read: When creating a crtr plugin, packaging memory docs for
|
|
|
5
5
|
debugging install/resolution, this knowledge should be read so installs resolve
|
|
6
6
|
predictably across scopes and command surfaces do not fail from manifest drift or protocol mistakes.
|
|
7
7
|
short-form: How to author a crtr plugin — plugin.json manifest, directory
|
|
8
|
-
layout, scopes, install mechanics, versioning, and command plugins
|
|
9
|
-
|
|
8
|
+
layout, scopes, install mechanics, versioning, and command-capable plugins
|
|
9
|
+
(commands.json plus an exec or HTTP transport). Use when creating a plugin,
|
|
10
10
|
packaging memory docs, contributing commands, or debugging install/resolution.
|
|
11
11
|
system-prompt-visibility: name
|
|
12
12
|
file-read-visibility: none
|
|
@@ -42,7 +42,7 @@ If it's a one-off note for yourself, scope-owned memory docs are simpler. Promot
|
|
|
42
42
|
└── <name>.md
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
The `<plugin-name>` directory IS the plugin. The manifest's `name` field must match the directory name (install renames if needed). Sibling dirs (`rules/`, `agents/`, and future `hooks/`) hold the other artifact types. A plugin that contributes CLI commands adds a `commands.json` manifest plus
|
|
45
|
+
The `<plugin-name>` directory IS the plugin. The manifest's `name` field must match the directory name (install renames if needed). Sibling dirs (`rules/`, `agents/`, and future `hooks/`) hold the other artifact types. A plugin that contributes CLI commands adds a `commands.json` manifest plus a `transport` declaration — see [Plugin commands](#plugin-commands).
|
|
46
46
|
|
|
47
47
|
## The manifest
|
|
48
48
|
|
|
@@ -68,7 +68,8 @@ The `<plugin-name>` directory IS the plugin. The manifest's `name` field must ma
|
|
|
68
68
|
| `description` | yes | One sentence. |
|
|
69
69
|
| `source` | recommended | Git URL where the plugin lives. Used by `crtr pkg plugin update --name <name>`. |
|
|
70
70
|
| `owner` | optional | Author info. |
|
|
71
|
-
| `commands` | optional | Plugin-root-relative path to a `commands.json` command manifest.
|
|
71
|
+
| `commands` | optional | Plugin-root-relative path to a `commands.json` command manifest. It must appear with `transport`; together they make the plugin contribute `crtr` commands — see [Plugin commands](#plugin-commands). |
|
|
72
|
+
| `transport` | optional | Required exactly when `commands` is present. `{ "kind": "exec", "executable": "bin/cmd.js" }` runs executable leaves; a passthrough-only exec manifest may omit `executable`. `{ "kind": "http", "endpoint": "https://…", "authEnv": "TOKEN_NAME" }` calls a remote HTTP command surface. |
|
|
72
73
|
|
|
73
74
|
## Scopes
|
|
74
75
|
|
|
@@ -83,7 +84,7 @@ Project-scope plugins outrank user-scope on resolution. Both outrank marketplace
|
|
|
83
84
|
|
|
84
85
|
## Install mechanics
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
Four ways a plugin lands in a scope:
|
|
87
88
|
|
|
88
89
|
1. **From a git URL** (`crtr pkg plugin install <url> --scope user`):
|
|
89
90
|
- Clones into `<scope>/plugins/<name>/` using the manifest's name.
|
|
@@ -91,11 +92,15 @@ Three ways a plugin lands in a scope:
|
|
|
91
92
|
- Independent of any marketplace.
|
|
92
93
|
|
|
93
94
|
2. **From a marketplace** (`crtr pkg plugin install <mkt>/<name>`):
|
|
94
|
-
-
|
|
95
|
-
- `crtr pkg market update --name <mkt>`
|
|
95
|
+
- A marketplace-relative `source` is symlinked from the marketplace checkout; a remote Git `source` is cloned into `<scope>/plugins/<name>/`.
|
|
96
|
+
- `crtr pkg market update --name <mkt>` refreshes the marketplace and every installed plugin it sources; relative sources follow the checkout, while remote-source checkouts pull their own Git remote.
|
|
96
97
|
- See [[internal/marketplaces]].
|
|
97
98
|
|
|
98
|
-
3. **
|
|
99
|
+
3. **From an HTTP endpoint** (`crtr pkg plugin install --endpoint <url> --name <name> --scope user`):
|
|
100
|
+
- Fetches the served `commands.json`, then writes the plugin manifest and exact fetched bytes into the selected scope. The endpoint must use `https:`; `http:` is accepted only for `localhost`, `127.0.0.1`, `[::1]`, `::1`, or `host.docker.internal`, with no credentials or fragment.
|
|
101
|
+
- The install fails loudly and writes nothing when that fetch fails. Reinstalling the same HTTP plugin replaces its endpoint/auth-env declaration and stored manifest; it conflicts with an existing non-HTTP plugin of the same name.
|
|
102
|
+
|
|
103
|
+
4. **Authored in place** (you're writing the plugin in a working repo):
|
|
99
104
|
- Symlink for tight dev loop: `ln -s $(pwd) ~/.crouter/plugins/<name>`.
|
|
100
105
|
- Or `crtr pkg plugin install file://$(pwd) --scope project` to clone-install.
|
|
101
106
|
|
|
@@ -131,7 +136,7 @@ Standard semver:
|
|
|
131
136
|
| New doc, new section, new example | minor (0.1.0 → 0.2.0) |
|
|
132
137
|
| Removed doc, renamed doc, changed manifest schema | major (0.1.0 → 1.0.0) |
|
|
133
138
|
|
|
134
|
-
`crtr pkg plugin update --name <name>`
|
|
139
|
+
`crtr pkg plugin update --name <name>` pulls source updates for ordinary and exec-transport plugins, while an HTTP-transport plugin unconditionally refetches and replaces its stored `commands.json`. A failed HTTP refresh preserves the prior bytes and exits nonzero. Plugins published through a marketplace may have their `version` field bumped automatically by CI — see [[internal/marketplaces]].
|
|
135
140
|
|
|
136
141
|
## Enable/disable
|
|
137
142
|
|
|
@@ -154,45 +159,63 @@ Bad plugin scope:
|
|
|
154
159
|
|
|
155
160
|
If your memory doc conceptually depends on another plugin's doc, link via `## Related` with `` `<plugin>/<doc>` ``. Don't fork content; link it.
|
|
156
161
|
|
|
157
|
-
##
|
|
162
|
+
## Plugin commands
|
|
163
|
+
|
|
164
|
+
Beyond docs, a plugin may contribute **top-level `crtr` commands** — new noun branches with their own leaves. It does so through one `commands` pointer and one `transport` declaration. `transport.kind` selects how every leaf runs: `exec` direct-spawns a local executable; `http` calls the remote command surface. crtr owns parsing, native help, rendering, and errors for both.
|
|
158
165
|
|
|
159
|
-
|
|
166
|
+
### The manifest pointer and transport
|
|
160
167
|
|
|
161
|
-
|
|
168
|
+
`commands` and `transport` appear together in `plugin.json`; a docs-only plugin declares neither:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"name": "deploy-tools",
|
|
173
|
+
"version": "0.1.0",
|
|
174
|
+
"description": "...",
|
|
175
|
+
"commands": "commands.json",
|
|
176
|
+
"transport": { "kind": "exec", "executable": "bin/cmd.js" }
|
|
177
|
+
}
|
|
178
|
+
```
|
|
162
179
|
|
|
163
|
-
|
|
180
|
+
An HTTP-transport plugin replaces that declaration with:
|
|
164
181
|
|
|
165
182
|
```json
|
|
166
|
-
|
|
183
|
+
"transport": { "kind": "http", "endpoint": "https://example.com/v1/cli/manifest", "authEnv": "DEPLOY_TOKEN" }
|
|
167
184
|
```
|
|
168
185
|
|
|
169
|
-
|
|
186
|
+
For `exec`, `executable` is required when the manifest has any executable leaf; a passthrough-only manifest omits it. When declared, it is plugin-root-relative, resolves inside the plugin root to a regular file, and carries the POSIX exec bit. For `http`, `endpoint` is an absolute endpoint and `authEnv` is optional. crtr stores only the environment variable **name**, never its credential; it reads the credential when fetching the manifest or invoking a leaf.
|
|
187
|
+
|
|
188
|
+
Only an installed, **enabled** plugin's command manifest contributes. Discovery is per-invocation: enable, disable, update, and remove take effect on the next `crtr` call — no daemon restart or cache clearing.
|
|
170
189
|
|
|
171
190
|
### commands.json shape
|
|
172
191
|
|
|
192
|
+
Both transports use a strict, static `commands.json` with `schemaVersion: 1` and a non-empty `mounts` array:
|
|
193
|
+
|
|
173
194
|
```json
|
|
174
195
|
{
|
|
175
196
|
"schemaVersion": 1,
|
|
176
|
-
"executable": "bin/cmd.js",
|
|
177
197
|
"mounts": [
|
|
178
|
-
{ "parent": [], "node": { "kind": "branch", "name": "app", "...": "..." } }
|
|
198
|
+
{ "parent": [], "node": { "kind": "branch", "name": "app", "...": "..." } },
|
|
199
|
+
{ "parent": ["app"], "node": { "kind": "branch", "name": "deploy", "...": "..." } }
|
|
179
200
|
]
|
|
180
201
|
}
|
|
181
202
|
```
|
|
182
203
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
Each mount is `{ parent, node }`. `parent: []` contributes a top-level branch with `rootEntry { concept, description, whenToUse }`; a non-empty parent path attaches a node below a branch in the same plugin's manifest. Inline children and nested mounts form one forest. A nested mount whose parent is in a top-level inline tree resolves regardless of mount order; when one nested mount supplies another's parent, the parent mount comes first. Branches may have empty `children`, so another mount can fill them.
|
|
205
|
+
|
|
206
|
+
An exec manifest accepts only `schemaVersion` and `mounts`. Its leaves declare `outputKind: "object"`; branches may declare `passthrough`. An HTTP manifest additionally accepts optional absolute HTTP(S) `baseUrl` and positive-integer `timeouts { connectMs?, requestMs?, streamIdleMs? }`. Its leaves declare a `rest` mapping for method, path, parameter placement, and optional NDJSON streaming. The REST mapping is transport detail: generated `-h` presents HTTP and exec commands like native commands.
|
|
207
|
+
|
|
208
|
+
Every branch child is a branch (without `rootEntry`) or leaf. A leaf declares `params`, `output` (array of `{ name, type, required, constraint }`), and a non-empty `effects` array. Params use crtr's public vocabulary — one positional max, long-form `flag`s (types `string|int|bool|path|enum`, `choices` for enum), `stdin`, `context-file`; kebab-case names, no aliases. Two client-side affordances ride on a `positional` or `flag`: `encoding: "text"|"base64"` on a `type: "path"` param sends the named local FILE's content instead of the path string, and `defaultFromEnv: "UPPER_SNAKE"` fills an omitted `string`/`path` param from that environment variable on the calling machine, counting as supplied (so it satisfies `required` and is sent) — unlike a static `default`, which is a parse convenience only and never ships. `defaultFromEnv` is rejected alongside `default` or `repeatable`. The declaration mirrors crtr's stable help descriptors, not its internal TypeScript defs — no closures, dynamic state, or renderers.
|
|
186
209
|
|
|
187
|
-
|
|
210
|
+
### Execution and trust boundaries
|
|
188
211
|
|
|
189
|
-
|
|
212
|
+
An exec leaf direct-spawns its executable (no shell) only on explicit invocation — never on install, help, or discovery — with `--crtr-command-protocol 1`, the caller's cwd, and the full environment. It is **trusted local code running with the caller's authority**: crtr does not sandbox it, filter the environment, mint a credential, or interpret its backend authentication. This is an execution trust boundary, not a sandbox.
|
|
190
213
|
|
|
191
|
-
|
|
214
|
+
An HTTP leaf is **definition plus HTTP only**: crtr fetches its manifest, renders native help from it, and executes the declared REST mapping. There is no local binary to spawn or sandbox. HTTP leaf calls retain their declared timeouts, bearer-token handling, NDJSON streaming, and structured HTTP error-envelope handling.
|
|
192
215
|
|
|
193
|
-
###
|
|
216
|
+
### Exec protocol
|
|
194
217
|
|
|
195
|
-
crtr writes exactly one JSON request to
|
|
218
|
+
For an exec leaf, crtr writes exactly one JSON request to the executable's stdin:
|
|
196
219
|
|
|
197
220
|
```json
|
|
198
221
|
{
|
|
@@ -203,44 +226,37 @@ crtr writes exactly one JSON request to your executable's stdin:
|
|
|
203
226
|
}
|
|
204
227
|
```
|
|
205
228
|
|
|
206
|
-
`input` keys are the parser's camelCase form; a declared `stdin` param arrives as an `input` string, not a second stream.
|
|
229
|
+
`input` keys are the parser's camelCase form; a declared `stdin` param arrives as an `input` string, not a second stream. The executable writes exactly one JSON envelope to stdout and nothing else — diagnostics go to stderr:
|
|
207
230
|
|
|
208
231
|
```json
|
|
209
232
|
{ "protocolVersion": 1, "ok": true, "result": { "app_id": "app_123" } }
|
|
210
233
|
{ "protocolVersion": 1, "ok": false, "error": { "code": "authentication_required", "message": "...", "field": "session", "next": "..." } }
|
|
211
234
|
```
|
|
212
235
|
|
|
213
|
-
`ok` is the source of truth (a valid envelope is honored regardless of exit code). crtr validates `result` against
|
|
214
|
-
|
|
215
|
-
### Two rules that prevent silent breakage
|
|
216
|
-
|
|
217
|
-
- **Generate `commands.json` from your command definitions — never hand-write it.** The manifest must stay in lockstep with the executable's actual command surface; a hand-maintained copy drifts, and a drifted param or output field surfaces as a validation issue or a `plugin_protocol_error` at invocation. Emit it from the same source your executable dispatches on.
|
|
218
|
-
- **A required output field must be non-null.** The adapter treats an explicit `null` for a declared-required field as *absent* → `plugin_protocol_error`. If a value is genuinely optional, declare it `required: false`; if it's required, always return a real value.
|
|
219
|
-
|
|
220
|
-
### Validating your command manifest
|
|
221
|
-
|
|
222
|
-
crtr validates command manifests **statically — it never executes your binary** to check them:
|
|
236
|
+
`ok` is the source of truth (a valid envelope is honored regardless of exit code). crtr validates `result` against the declared `output` (top-level field presence + type) and renders it; `--json` mirrors the same object. An error envelope becomes a normal crtr error with its lowercase snake_case `code`, except crtr-reserved `internal`, `unknown_path`, `command_collision`, and `plugin_protocol_error`. No envelope at all (invalid JSON, empty, extra stdout, output over 10 MiB, signal kill) becomes `plugin_protocol_error`.
|
|
223
237
|
|
|
224
|
-
|
|
225
|
-
- `crtr sys doctor` — validates the manifest + executable path for every effective command plugin and reports structured remediation (disable/update/remove). `--fix` never chmods or rewrites plugin content.
|
|
226
|
-
- `crtr pkg plugin install` / `update` — report the accepted top-level commands and any issues in their result.
|
|
238
|
+
### Keeping command surfaces valid
|
|
227
239
|
|
|
228
|
-
|
|
240
|
+
- **Generate an exec plugin's `commands.json` from its command definitions — never hand-write it.** The manifest must stay in lockstep with the executable's command surface; drifted params or output fields surface as a validation issue or `plugin_protocol_error` at invocation.
|
|
241
|
+
- **A required output field must be non-null.** The adapter treats an explicit `null` for a declared-required field as absent → `plugin_protocol_error`. If a value is optional, declare it `required: false`; if it is required, return a real value.
|
|
242
|
+
- **HTTP plugin manifests are fetched bytes.** `crtr pkg plugin install --endpoint <url> --name <name>` fetches before writing the plugin, then stores the exact response at the plugin's declared `commands` path. `crtr pkg plugin update` unconditionally refetches HTTP plugins; failures preserve the prior bytes and exit nonzero. The stored manifest is authoritative with no TTL, ETag, or revalidation. If its file is missing or unparseable, an unknown-first-token miss fetches each affected HTTP plugin once; diagnostics name `crtr pkg plugin update <name>`.
|
|
229
243
|
|
|
230
|
-
|
|
244
|
+
### Validation and command collisions
|
|
231
245
|
|
|
232
|
-
|
|
246
|
+
crtr validates command manifests statically; it never executes an exec binary to inspect its command surface:
|
|
233
247
|
|
|
234
|
-
|
|
248
|
+
- `crtr pkg plugin show <name>` inventories the plugin manifest, command-manifest path, accepted top-level command names, and validation issues (each with received/expected/next).
|
|
249
|
+
- `crtr sys doctor` validates the command manifest and transport declaration for every effective plugin, including executable-path checks when exec manifests declare executable leaves, and reports structured remediation (disable, update, remove). `--fix` never chmods or rewrites plugin content.
|
|
250
|
+
- `crtr pkg plugin install` and `update` report accepted top-level command names and validation issues.
|
|
235
251
|
|
|
236
|
-
|
|
252
|
+
Core always wins a path collision. A cross-plugin collision drops every claimant with a `command_collision` issue. A fixed manifest goes live on the next invocation; there is nothing to restart.
|
|
237
253
|
|
|
238
254
|
## Validation
|
|
239
255
|
|
|
240
256
|
`crtr sys doctor` checks each plugin's manifest:
|
|
241
257
|
- Manifest exists and is valid JSON.
|
|
242
258
|
- Manifest `name` matches the directory name.
|
|
243
|
-
- When the plugin declares `commands`, its command manifest
|
|
259
|
+
- When the plugin declares `commands`, its command manifest and transport declaration are validated statically; an exec executable is never executed during validation — see [Plugin commands](#plugin-commands).
|
|
244
260
|
|
|
245
261
|
`crtr memory lint` checks the docs under `memory/`: frontmatter parses, valid `kind`, both visibility rungs set. Run `crtr memory write -h` for the authoring + routing guide. Other sibling artifact dirs (`rules/`, `agents/`, `hooks/`) are validated by their respective specs as those land.
|
|
246
262
|
|
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
kind: knowledge
|
|
3
3
|
when-and-why-to-read: When shaping a planning roadmap, deciding plan structure, or preparing a consequential plan for implementation, this knowledge should be read so implementation receives a right-sized, parallel-safe execution map whose gaps are caught while they are still cheap to fix.
|
|
4
4
|
short-form: Use when shaping a planning roadmap, deciding plan structure, or preparing a consequential plan for implementation.
|
|
5
|
-
system-prompt-visibility:
|
|
5
|
+
system-prompt-visibility: preview
|
|
6
6
|
file-read-visibility: none
|
|
7
|
-
gate:
|
|
8
|
-
kind:
|
|
9
|
-
imatches: '^plan($|/)'
|
|
10
|
-
needs-refinement: true
|
|
7
|
+
gate: {kind: plan}
|
|
11
8
|
rationale: >-
|
|
12
9
|
The original playbook required five parallel plan reviewers before every consequential implementation and made “passes all five lenses” the ready bar. Combined with the plan persona's re-review loop, this turned lenses into agents and resolution into reviewer polling rather than plan-owner judgment.
|
|
13
10
|
---
|
|
@@ -18,9 +15,9 @@ rationale: >-
|
|
|
18
15
|
|
|
19
16
|
Every planning effort produces either a flat plan or a decomposed plan (index + part-plans). Choosing the wrong shape wastes a cycle — a flat plan that is too large forces an implementer to hold too much at once; a decomposed plan for something small adds overhead for no gain.
|
|
20
17
|
|
|
21
|
-
**Use a flat plan** when the work is a single coherent domain
|
|
18
|
+
**Use a flat plan** when the work is a single coherent domain and can be written at consistent task granularity in one plan. A flat plan has an overview, ordered phases, and a verification section. No sub-plans. One file.
|
|
22
19
|
|
|
23
|
-
**Use a decomposed plan** when the change spans multiple domains (e.g., data layer, API surface, UI)
|
|
20
|
+
**Use a decomposed plan** when the change spans multiple domains (e.g., data layer, API surface, UI) or would require a master plan that cannot be written at consistent granularity without ballooning. In this case: produce an index plan (the navigable master) and delegate each domain slice to a `plan`-kind child node, giving each child its slice scope, the relevant portion of the spec, and its place in the dependency graph. A slice that itself decomposes further — multiple sub-domains, more than one window's worth of planning — goes to a `plan` sub-orchestrator created directly (`crtr node new --kind plan --mode orchestrator`), not a base child relied on to promote itself. The index plan is the synthesis artifact — it lists all sub-plans by path, defines phases and their dependencies, and contains a task table the implementation orchestrator can execute directly. Detail lives in sub-plans; the master is not allowed to carry it.
|
|
24
21
|
|
|
25
22
|
**The decomposition trigger is domain boundary, not size alone.** Three backend files and three frontend files are two domains even if the total count is modest — plan them separately and synthesize, because the integration seam is where bugs live and one agent reading both halves won't catch them as cleanly as two agents each going deep.
|
|
26
23
|
|