@north-light/crouter 0.3.228 → 0.3.230

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/builtin-memory/04-base-worker.md +1 -1
  2. package/dist/builtin-memory/internal/agent-shaping.md +11 -11
  3. package/dist/clients/attach/viewer.js +1 -1
  4. package/dist/commands/node/create.d.ts +1 -1
  5. package/dist/commands/node/create.js +1 -1
  6. package/dist/commands/node/inspect.js +1 -1
  7. package/dist/commands/node/lifecycle.js +3 -3
  8. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +16 -16
  9. package/dist/core/__tests__/integration/spawn-root.test.js +13 -3
  10. package/dist/core/__tests__/review-model-floor.test.js +12 -4
  11. package/dist/core/config.d.ts +3 -3
  12. package/dist/core/config.js +3 -3
  13. package/dist/core/human/__tests__/integration/inbox-core.test.js +4 -3
  14. package/dist/core/runtime/launch.js +1 -1
  15. package/dist/types.d.ts +8 -11
  16. package/dist/types.js +4 -31
  17. package/package.json +1 -1
  18. package/runtime.lock.json +2 -2
  19. package/dist/builtin-memory/05-kinds/design/00-base.md +0 -16
  20. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +0 -16
  21. package/dist/builtin-memory/05-kinds/design/design-contract.md +0 -16
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +0 -17
  23. package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +0 -15
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +0 -16
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +0 -16
  26. package/dist/builtin-memory/05-kinds/plan/plan-contract.md +0 -20
  27. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -15
  28. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -15
  29. package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +0 -13
  30. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -17
  31. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +0 -17
  32. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -17
  33. package/dist/builtin-memory/05-kinds/spec/00-base.md +0 -17
  34. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +0 -15
  35. package/dist/builtin-memory/05-kinds/spec/requirements.md +0 -15
  36. package/dist/builtin-memory/design/guide.md +0 -57
  37. package/dist/builtin-memory/design/roadmap.md +0 -21
  38. package/dist/builtin-memory/development.md +0 -113
  39. package/dist/builtin-memory/plan/guide.md +0 -53
  40. package/dist/builtin-memory/plan/roadmap.md +0 -27
  41. package/dist/builtin-memory/spec/guide.md +0 -53
  42. package/dist/builtin-memory/spec/requirements.md +0 -29
  43. package/dist/builtin-memory/spec/roadmap.md +0 -36
  44. package/dist/builtin-memory/testing.md +0 -39
@@ -8,7 +8,6 @@ import { tmpdir } from 'node:os';
8
8
  import { join } from 'node:path';
9
9
  import { createServer } from 'node:net';
10
10
  import { spawn as spawnProcess } from 'node:child_process';
11
- import { findDaemonPids, stopDaemonProcess } from '../../../daemon/manage.js';
12
11
  import { createNode, getNode, getRow, subscribersOf } from '../../canvas/canvas.js';
13
12
  import { closeDb } from '../../canvas/db.js';
14
13
  import { nodeDir } from '../../canvas/paths.js';
@@ -21,6 +20,7 @@ import { piSessionsRoot } from '../../runtime/pi-vendored.js';
21
20
  import { emptyContextExposureState, exposureTarget, loadContextExposureState, registerExposure, saveContextExposureState, } from '../../substrate/injected-store.js';
22
21
  import { ROOT_PROFILE_ID } from '../../profiles/manifest.js';
23
22
  let home;
23
+ let previousPidfile;
24
24
  function spawner(id) {
25
25
  return {
26
26
  node_id: id,
@@ -38,15 +38,25 @@ before(() => {
38
38
  // canvas home short because root readiness now opens a real view.sock.
39
39
  home = mkdtempSync('/tmp/crtr-spawn-root-');
40
40
  process.env['CRTR_HOME'] = home;
41
+ previousPidfile = process.env['CRTR_PIDFILE'];
42
+ process.env['CRTR_PIDFILE'] = join(home, 'crtrd.pid');
41
43
  });
42
44
  beforeEach(() => {
43
45
  closeDb();
44
46
  rmSync(home, { recursive: true, force: true });
47
+ mkdirSync(home, { recursive: true });
48
+ // These tests exercise direct spawn behavior, not daemon autostart. Keep
49
+ // ensureDaemon() from launching a background daemon whose startup verifier
50
+ // would outlive the test's next CRTR_HOME reset.
51
+ writeFileSync(join(home, 'crtrd.pid'), `${process.pid}\n`);
45
52
  });
46
- after(async () => {
53
+ after(() => {
47
54
  closeDb();
48
- await Promise.all(findDaemonPids().map((pid) => stopDaemonProcess(pid)));
49
55
  rmSync(home, { recursive: true, force: true });
56
+ if (previousPidfile === undefined)
57
+ delete process.env['CRTR_PIDFILE'];
58
+ else
59
+ process.env['CRTR_PIDFILE'] = previousPidfile;
50
60
  });
51
61
  test('managed child: parent on the spine + active subscription + provenance', () => {
52
62
  createNode(spawner('A'));
@@ -5,7 +5,7 @@
5
5
  // persona keeps the stronger default needed to synthesise a broad review.
6
6
  import { after, before, test } from 'node:test';
7
7
  import assert from 'node:assert/strict';
8
- import { mkdtempSync, rmSync } from 'node:fs';
8
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
9
9
  import { tmpdir } from 'node:os';
10
10
  import { join } from 'node:path';
11
11
  import { defaultKindsConfig, defaultModelLaddersConfig } from '../../types.js';
@@ -19,6 +19,15 @@ let home = '';
19
19
  before(() => {
20
20
  home = mkdtempSync(join(tmpdir(), 'crtr-review-model-floor-'));
21
21
  process.env['HOME'] = home;
22
+ mkdirSync(join(home, '.crouter'), { recursive: true });
23
+ writeFileSync(join(home, '.crouter', 'config.json'), JSON.stringify({
24
+ kinds: {
25
+ 'audit/reviewers/security': {
26
+ whenToUse: 'Review one security surface.',
27
+ model: 'medium',
28
+ },
29
+ },
30
+ }));
22
31
  });
23
32
  after(() => {
24
33
  if (priorHome === undefined)
@@ -43,9 +52,8 @@ test('base review ignores a light override and keeps its medium floor', () => {
43
52
  assert.equal(spec('review', 'light'), expected(REVIEW_FLOOR));
44
53
  assert.equal(spec('review', 'haiku'), expected(REVIEW_FLOOR));
45
54
  });
46
- test('plan reviewer sub-kinds also keep their medium worker floor', () => {
47
- assert.equal(spec('plan/reviewers/security', 'light'), expected('medium'));
48
- assert.equal(spec('plan/reviewers/requirements-coverage', 'light'), expected('medium'));
55
+ test('plugin-shaped reviewer sub-kinds keep their configured worker floor', () => {
56
+ assert.equal(spec('audit/reviewers/security', 'light'), expected('medium'));
49
57
  });
50
58
  test('review orchestrator uses its stronger coordinating model', () => {
51
59
  assert.equal(buildLaunchSpec('review', 'orchestrator', { lifecycle: 'terminal', hasManager: true, cwd: home, profileId: null }).launch.model, expected(defaultKindsConfig()['review'].orchestratorModel));
@@ -147,7 +147,7 @@ export interface MergedLaunchConfig {
147
147
  * follow-up fix this parameterization exists for). */
148
148
  export declare function readMergedLaunchConfig(targetCwd?: string, targetProfileId?: string | null): MergedLaunchConfig;
149
149
  /** The effective `KindConfig` for one full kind string (top-level, e.g.
150
- * `developer`, or sub-kind, e.g. `plan/reviewers/security`), across
150
+ * `developer`, or sub-kind, e.g. `audit/security`), across
151
151
  * project > user > builtin precedence. Returns `undefined` for a kind no
152
152
  * scope registers — existence is deliberately NOT validated here (kind
153
153
  * existence/launch-menu enumeration is a caller concern); this only
@@ -160,8 +160,8 @@ export declare function resolveKindConfig(kind: string): KindConfig | undefined;
160
160
  export declare function assertInstalledKind(kind: string): void;
161
161
  /** The sub-kinds available to spawn FROM a given top-level kind — every
162
162
  * registered sub-kind (full path contains `/`) whose `availableTo` (default:
163
- * its own top-level ancestor, e.g. `plan/reviewers/security` defaults to
164
- * `['plan']`) includes `kind` or `'*'`. The single source both `sys
163
+ * its own top-level ancestor, e.g. `audit/security` defaults to
164
+ * `['audit']`) includes `kind` or `'*'`. The single source both `sys
165
165
  * prompt-review --list`'s `subPersonas` metadata and the live sub-persona
166
166
  * spawn-menu splice (`core/substrate/render.ts`) read, so the two can never
167
167
  * drift apart. Sorted by full kind name for stable rendering. */
@@ -796,7 +796,7 @@ export function readMergedLaunchConfig(targetCwd = process.cwd(), targetProfileI
796
796
  return { kinds, modelLadders, ...(Object.keys(modelRoutes).length > 0 ? { modelRoutes } : {}), ...(modelRouting !== undefined ? { modelRouting } : {}), spawnEnv };
797
797
  }
798
798
  /** The effective `KindConfig` for one full kind string (top-level, e.g.
799
- * `developer`, or sub-kind, e.g. `plan/reviewers/security`), across
799
+ * `developer`, or sub-kind, e.g. `audit/security`), across
800
800
  * project > user > builtin precedence. Returns `undefined` for a kind no
801
801
  * scope registers — existence is deliberately NOT validated here (kind
802
802
  * existence/launch-menu enumeration is a caller concern); this only
@@ -820,8 +820,8 @@ export function assertInstalledKind(kind) {
820
820
  }
821
821
  /** The sub-kinds available to spawn FROM a given top-level kind — every
822
822
  * registered sub-kind (full path contains `/`) whose `availableTo` (default:
823
- * its own top-level ancestor, e.g. `plan/reviewers/security` defaults to
824
- * `['plan']`) includes `kind` or `'*'`. The single source both `sys
823
+ * its own top-level ancestor, e.g. `audit/security` defaults to
824
+ * `['audit']`) includes `kind` or `'*'`. The single source both `sys
825
825
  * prompt-review --list`'s `subPersonas` metadata and the live sub-persona
826
826
  * spawn-menu splice (`core/substrate/render.ts`) read, so the two can never
827
827
  * drift apart. Sorted by full kind name for stable rendering. */
@@ -17,10 +17,11 @@ writeFileSync(pageSource, 'export default () => (\n <Page title="A page" subtit
17
17
  const page = (id, emittedAt) => submitPage({ dir: ticketDir(id), sourceFile: pageSource, source: { emittedAt, nodeId: 'node-1' }, delivery: { placement: 'inline', inbox: true, reply: true } });
18
18
  const answer = { go: { text: 'yes', edited: true } };
19
19
  async function waitFor(paths) {
20
- for (let attempts = 0; !paths.every(existsSync); attempts++) {
21
- if (attempts > 1_000)
20
+ const deadline = Date.now() + 10_000;
21
+ while (!paths.every(existsSync)) {
22
+ if (Date.now() >= deadline)
22
23
  throw new Error(`workers did not reach barrier: ${paths.join(', ')}`);
23
- await new Promise((resolvePromise) => setTimeout(resolvePromise, 1));
24
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 10));
24
25
  }
25
26
  }
26
27
  page('z-last', '2025-01-01T00:00:00.000Z');
@@ -106,7 +106,7 @@ function resolvedModelStrength(model, ladders = modelLadders()) {
106
106
  return cell?.strength ?? null;
107
107
  }
108
108
  function isReviewQualityKind(kind) {
109
- return kind === 'review' || kind.startsWith('plan/reviewers/');
109
+ return kind === 'review' || kind.startsWith('review/') || kind.includes('/reviewers/');
110
110
  }
111
111
  function floorReviewModel(kind, requestedModel, kindModel, ladders = modelLadders()) {
112
112
  if (requestedModel === undefined)
package/dist/types.d.ts CHANGED
@@ -62,7 +62,7 @@ export interface PluginManifest {
62
62
  source?: string;
63
63
  owner?: OwnerRef;
64
64
  /** Kind-registry contributions, keyed by full kind string (top-level e.g.
65
- * `applet-builder`, or sub-kind e.g. `plan/reviewers/security`). Each entry
65
+ * `applet-builder`, or sub-kind e.g. `audit/security`). Each entry
66
66
  * is any subset of `KindConfig` fields: it FIELD-MERGES over a kind a lower
67
67
  * layer already defines (`whenToUse` included — overriding just the spawn
68
68
  * guidance never strips the kind's model tier), and defines a NEW kind when
@@ -202,14 +202,14 @@ export interface ModelRoutingConfig {
202
202
  strengthFallback?: ModelStrength[];
203
203
  }
204
204
  /** Launch metadata for one kind (a top-level kind like `developer`, or a full
205
- * sub-kind string like `plan/reviewers/security`) — the settings-file
205
+ * sub-kind string like `audit/security`) — the settings-file
206
206
  * replacement for per-kind persona frontmatter. `model`/`tools`/`extensions`
207
207
  * are launch knobs consumed by `buildLaunchSpec`; `whenToUse` is the
208
208
  * one-line gloss shown in `node new -h` / `node promote -h`. `availableTo` is
209
209
  * VISIBILITY-ONLY (never launch validation): the list of top-level kind names
210
210
  * whose spawn menus surface this sub-kind, `'*'` meaning every kind; omitted
211
211
  * defaults to the sub-kind's own top-level ancestor (e.g.
212
- * `plan/reviewers/security` defaults to `['plan']`). A direct launch by full kind
212
+ * `audit/security` defaults to `['audit']`). A direct launch by full kind
213
213
  * string is always valid regardless of `availableTo`. */
214
214
  export interface KindConfig {
215
215
  model?: string;
@@ -320,7 +320,7 @@ export interface ScopeConfig {
320
320
  modelRouting?: ModelRoutingConfig;
321
321
  /** The kind registry (spec §1.5): kind existence + launch knobs, keyed by
322
322
  * full kind string (top-level e.g. `developer`, or sub-kind e.g.
323
- * `plan/reviewers/security`). Builtins ship a default registry via
323
+ * `audit/security`). Builtins ship a default registry via
324
324
  * `defaultScopeConfig()`; user/project `config.json` adds or shadows
325
325
  * entries at the same scope precedence as the rest of `ScopeConfig`. */
326
326
  kinds: Record<string, KindConfig>;
@@ -483,13 +483,10 @@ export declare function defaultScopeConfig(): ScopeConfig;
483
483
  /** No remote canvas targets are configured out of the box — every one is
484
484
  * registered via `crtr canvas config add` (see `RemoteCanvasConfig`). */
485
485
  export declare function defaultRemoteCanvasConfig(): RemoteCanvasConfig;
486
- /** The builtin kind registry (spec §1.5): the built-in defaults for every
487
- * top-level kind and its sub-persona kinds. `whenToUse`/`model` are the
488
- * base-worker defaults; `orchestratorModel` optionally raises the default
489
- * for a coordinating persona. Roadmap-shaping guidance is orchestrator-only —
490
- * an orchestrator-gated memory doc keyed to the kind, not baked into the
491
- * registry entry. Sub-persona `availableTo` is omitted where it only
492
- * reproduces the default (its own top-level ancestor). */
486
+ /** The builtin kind registry (spec §1.5): core role discovery and launch
487
+ * defaults. `whenToUse`/`model` are the base-worker defaults;
488
+ * `orchestratorModel` optionally raises the default for a coordinating
489
+ * persona. Optional plugins contribute their own specialist sub-personas. */
493
490
  export declare function defaultKindsConfig(): Record<string, KindConfig>;
494
491
  export declare function defaultModelLaddersConfig(): ModelLaddersConfig;
495
492
  export declare function defaultScopeState(): ScopeState;
package/dist/types.js CHANGED
@@ -111,13 +111,10 @@ export function defaultScopeConfig() {
111
111
  export function defaultRemoteCanvasConfig() {
112
112
  return { targets: {} };
113
113
  }
114
- /** The builtin kind registry (spec §1.5): the built-in defaults for every
115
- * top-level kind and its sub-persona kinds. `whenToUse`/`model` are the
116
- * base-worker defaults; `orchestratorModel` optionally raises the default
117
- * for a coordinating persona. Roadmap-shaping guidance is orchestrator-only —
118
- * an orchestrator-gated memory doc keyed to the kind, not baked into the
119
- * registry entry. Sub-persona `availableTo` is omitted where it only
120
- * reproduces the default (its own top-level ancestor). */
114
+ /** The builtin kind registry (spec §1.5): core role discovery and launch
115
+ * defaults. `whenToUse`/`model` are the base-worker defaults;
116
+ * `orchestratorModel` optionally raises the default for a coordinating
117
+ * persona. Optional plugins contribute their own specialist sub-personas. */
121
118
  export function defaultKindsConfig() {
122
119
  return {
123
120
  general: {
@@ -156,34 +153,10 @@ export function defaultKindsConfig() {
156
153
  whenToUse: 'Debug failures, investigate why something is broken or misbehaving, diagnose live/runtime issues, or give engineering advice and second opinions — reason from evidence and recommend the next move. Use advisor (not explore) whenever the task is to find out what is going wrong.',
157
154
  model: 'anthropic/strong',
158
155
  },
159
- 'plan/reviewers/requirements-coverage': {
160
- whenToUse: 'every requirement and design constraint maps to a concrete plan task, classified Covered/Partial/Missing; flags only blocking gaps',
161
- model: 'medium',
162
- },
163
- 'plan/reviewers/pattern-consistency': {
164
- whenToUse: "the plan honors the codebase's real conventions; reads actual source and cites the pattern each finding deviates from; owns contract-level conflicts between parts",
165
- model: 'medium',
166
- },
167
- 'plan/reviewers/code-smells': {
168
- whenToUse: 'nullability mismatches, type conflicts across parts, hidden N+1s, over-fetching, missing error boundaries, leaky abstractions; owns file-level conflicts between parts',
169
- model: 'medium',
170
- },
171
- 'plan/reviewers/security': {
172
- whenToUse: 'input validation, injection surfaces, auth/authz gaps, data exposure, races; reports only validated concrete exploit paths and asks the user about material unknown threat-model assumptions',
173
- model: 'medium',
174
- },
175
156
  'review/companion': {
176
157
  whenToUse: 'Born by the daemon for one human review; never spawned by an agent.',
177
158
  availableTo: [],
178
159
  },
179
- 'plan/reviewers/architecture-fit': {
180
- whenToUse: "proposed files/modules/abstractions fit the system's existing decomposition; flags new units that duplicate existing ones or cross layer boundaries",
181
- model: 'medium',
182
- },
183
- 'spec/requirements': {
184
- whenToUse: 'Derive testable EARS requirements from a finished, approved design — in isolation, from the rendered design text alone.',
185
- model: 'medium',
186
- },
187
160
  };
188
161
  }
189
162
  export function defaultModelLaddersConfig() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/crouter",
3
- "version": "0.3.228",
3
+ "version": "0.3.230",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/crouter",
3
- "version": "0.3.228",
3
+ "version": "0.3.230",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/crouter",
9
- "version": "0.3.228",
9
+ "version": "0.3.230",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -1,16 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind design in base mode, this preference should be read so implementers inherit one coherent architecture instead of reopening load-bearing decisions.
4
- gate: {kind: design, mode: base}
5
- rationale: >-
6
- A bounded design needs one owner across evidence gathering, user decisions, and artifact delivery. The shared method lives in [[design/guide]] so this role layer carries only bounded-node lifecycle and promotion behavior.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## When designing a bounded system
13
-
14
- Given one bounded component, subsystem, or interaction surface, follow [[design/guide]] and produce a design an implementer can build from without re-deciding architecture. If decisive evidence is unavailable, report the blocker instead of presenting an unresolved design as settled.
15
-
16
- Deliver the design path plus one sentence per consequential decision stating what was chosen and what it closed off. Promote into a design orchestrator only when settled contracts expose independent design surfaces large enough for parallel work to repay synthesis cost; keep tightly coupled architecture in one base node across yields.
@@ -1,16 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind design in orchestrator mode, this preference should be read so parallel sub-designs compose across their interfaces instead of producing a fragmented or contradictory architecture.
4
- gate: {kind: design, mode: orchestrator}
5
- rationale: >-
6
- A design orchestrator owns contract-first delegation and integration. Decomposition mechanics live in [[design/roadmap]] so this role layer does not duplicate them.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Coordinating a design effort
13
-
14
- Follow [[design/roadmap]] for decomposition and [[design/guide]] for the integrated artifact. You own the shared contracts before delegation and the coherent whole after children return; sub-designs are evidence, not sections to concatenate.
15
-
16
- Deliver one integrated design whose responsibilities, sources of truth, interface semantics, data model, and success and failure flows agree across every boundary. Reconcile conflicts before reporting the artifact path and consequential decisions.
@@ -1,16 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind design, this preference should be read so the design closes the expensive decisions at the right altitude instead of drifting into implementation or over-specifying what the implementer could safely decide.
4
- gate: {kind: design}
5
- rationale: >-
6
- The design personas described how to write the artifact but routed to no shared design guidance, so a design node booted with no stable altitude rule and duplicated a fixed template that later diverged. Gates on the kind with no mode so design orchestrators load it too.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## What a design must settle
13
-
14
- A design fixes the consequential, expensive-to-reverse structure before implementation. It is not requirements, which state the behavior the system must satisfy, and it is not a plan, which maps implementation work against the settled design. A planner should inherit no architectural choice; a coder should retain cheap local implementation choices.
15
-
16
- Follow `crtr memory read design/guide` as the single design method and artifact format. Use `crtr memory read design/roadmap` only when settled contracts expose genuinely independent design surfaces worth parallelizing.
@@ -1,17 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind developer in base mode, this preference should be read so implementation is proven against the requested behavior rather than declared done at compile time.
4
- gate: {kind: developer, mode: base}
5
- rationale: >-
6
- Agents treated polish as a completion dependency, spending long iterations on nits while their parents could not advance the larger build. The developer needs to prove and report the first sound end-to-end path early, while retaining its existing done-bar for the final result. External critique works because agents can't self-audit; the reviewer must be primed neutrally — "review this", never "find what fails", which biases toward false positives.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## When implementing
13
- Work directly. Read the relevant files before editing, match the existing code style and module conventions, and keep your delegation shallow — a focused exploration or a review pass is worth handing off, but most of the work is yours. Throw errors early; no silent fallbacks. Break things correctly rather than patching them badly. Compatibility is governed by the approved spec or migration decision.
14
-
15
- Done means **provably correct against the spec's acceptance criteria** — not "it builds," not "the tests pass." Green output proves the code ran, not that it does what was asked; check the result against each acceptance criterion yourself. On a load-bearing change, get it critiqued by something other than you before calling it done — spawn a reviewer on the diff and fold in what it finds. Every Critical, Major, or acceptance-violating finding is fixed, always — keep the fix net-neutral-or-simpler, never bolt on complexity to patch it. A Minor or cosmetic finding that doesn't affect acceptance is fixed when the fix is net-neutral-or-simpler, or else closed with a one-line reason — closing is a resolution, not a deferral. But validate judiciously: a delegate's green report is settled evidence — don't re-run a suite or re-read a diff that already cleared its gate; check only what changed since. Promote into a developer orchestrator only when the change splits into genuinely independent implementation lanes; a long or tightly coupled build stays base across yields.
16
-
17
- When a working steel thread proves the task's end-to-end path and the remaining work cannot change its interface or acceptance outcome, report that readiness before polishing — name what is proven, what remains, and that whoever waits on this gate may advance. Then use judgment: finish net-simple polish in this window, but do not let nits or other non-blocking refinements hold the larger build. The final result still clears the full done-bar.
@@ -1,15 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind developer in orchestrator mode, this preference should be read so feature-sized builds move coherently from implementation through independent review and end-to-end validation.
4
- gate: {kind: developer, mode: orchestrator}
5
- rationale: >-
6
- Developer orchestrators need fact-dependent decisions sequenced behind shared evidence without blocking independent work. They also turned post-implementation “lenses” into mandatory parallel reviewers and then sought a fresh PASS after fixes, helping review dominate the canvas; one independent review assignment must own all relevant lenses, and changed behavior closes through evidence.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## When shaping a software roadmap
13
- Before you shape a software roadmap, read `crtr memory read development` for development styles, roadmap shapes, and exit criteria that fit the goal's risk.
14
-
15
- Treat implementation as complete only when it is **provably correct against the spec's acceptance criteria**, not merely when it compiles.
@@ -1,16 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan in base mode, this preference should be read so ambiguities and unsafe task boundaries are resolved before implementation makes them expensive.
4
- gate: {kind: plan, mode: base}
5
- rationale: >-
6
- A bounded planning task needs one owner across repository grounding and artifact delivery. The shared implementation-unit method lives in [[plan/guide]] so this role layer carries only bounded-node lifecycle and promotion behavior.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## When planning from a contract
13
-
14
- Given one bounded requirement, specification, or design, follow [[plan/guide]] and produce a concrete plan a fresh implementer can execute without guessing. Do not implement. When repository evidence exposes an unresolved expensive-to-reverse choice, return it to design instead of settling architecture inside the plan.
15
-
16
- If your task is one slice of a larger effort, stay within its ownership boundary and expose cross-slice dependencies for the synthesizer. Promote into a plan orchestrator only when settled dependencies and non-overlapping edit ownership expose independent planning slices large enough for parallel work to repay synthesis cost; keep a large sequential plan in one base node across yields.
@@ -1,16 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan in orchestrator mode, this preference should be read so cross-domain work becomes one parallel-safe, reviewed execution map rather than conflicting part-plans.
4
- gate: {kind: plan, mode: orchestrator}
5
- rationale: >-
6
- The prior orchestrator prompt defaulted to splitting by domain and duplicated index mechanics, which produced part-plans before dependencies and ownership made them independent. Decomposition and synthesis now live in [[plan/roadmap]].
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Coordinating a planning effort
13
-
14
- Follow [[plan/roadmap]] for the decomposition decision and index synthesis, and [[plan/guide]] for every part-plan's units and proof. You own the dependency graph, edit ownership, cross-lane acceptance coverage, and final runtime gate; children own only their bounded slices.
15
-
16
- Deliver one navigable index over coherent part-plans. Reconcile conflicts and integration gaps before review, and do not claim parallelism or acceptance coverage that the synthesized dependency and proof map does not establish.
@@ -1,20 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan, this preference should be read so the plan stays inside the approved contract and hands implementation units that can be executed cold and in parallel where dependencies permit.
4
- gate: {kind: plan}
5
- rationale: >-
6
- Planners turned plausible improvements outside the specification into implementation tasks, silently expanded scope, and duplicated a task format that diverged from the shared guide. An earlier playbook also turned review lenses into five agents. Gates on the kind with no mode so plan orchestrators load the same scope and review contract.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Hold the approved scope
13
-
14
- Follow `crtr memory read plan/guide` as the single planning method and artifact format. The approved requirements, specification, and design are fixed inputs. Merely plausible additions stay out; ask the user only when an input is genuinely ambiguous or the requested outcome cannot be completed without a scope decision. Return an expensive-to-reverse architectural gap to design.
15
-
16
- ## Plan review
17
-
18
- Give a consequential plan one independent review pass. Use one base `review` node for a coherent review across yields; use one bounded `review` orchestrator only when the artifact splits into independent review surfaces large enough for parallel coverage to repay synthesis cost. The assignment applies whichever lenses matter — requirements coverage, pattern consistency, code smells, security, architecture fit — within one verdict. Lenses are questions, not separate reviewer assignments.
19
-
20
- Fold the report into the plan once. Resolve every Critical, Major, or implementation-blocking finding; dismiss a false positive or out-of-scope finding with a reason. The revised plan is ready when each finding has a disposition and the artifact still clears the acceptance-proof contract in [[plan/guide]].
@@ -1,15 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan/reviewers/architecture-fit, this preference should be read so a plan cannot satisfy requirement wording while structurally missing the intended outcome.
4
- gate: {kind: plan/reviewers/architecture-fit}
5
- rationale: >-
6
- the lens that checks the plan actually ACHIEVES what the spec promised — semantic achievement of intent, distinct from requirement->task mapping (requirements-coverage) and convention adherence (pattern-consistency).
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Assessing architecture fit
13
- You are an **architecture-fit reviewer**. Given a plan and the spec it serves, verify that the architecture the plan proposes actually *achieves* what the spec set out to achieve — not merely that tasks exist, but that the structure they build delivers the spec's intent.
14
-
15
- Read the spec's goals and the plan's proposed architecture together, then check that the shape the plan builds toward genuinely realizes each outcome the spec promised. Flag where the architecture would satisfy the letter of a requirement while missing its intent, where a structural choice quietly forecloses a capability the spec calls for, and where the pieces as planned don't compose into the behavior the spec describes. Anchor each finding in the specific spec intent it fails to achieve.
@@ -1,15 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan/reviewers/code-smells, this preference should be read so expensive design flaws are caught before they become code.
4
- gate: {kind: plan/reviewers/code-smells}
5
- rationale: >-
6
- agents produce design flaws that are cheap to catch at plan stage and expensive after code exists; the lens is the smell-hunting disposition, not a fixed checklist — all smells are bad.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Checking for design flaws
13
- You are a **code-smells / design reviewer**. Given a plan, find the design flaws that would ship if it were implemented as written — before any code makes them expensive.
14
-
15
- Hunt design flaws in the disposition, not down a checklist — any smell that would make the code worse is in scope. Common ones, as examples rather than the whole set: nullability mismatches (a value treated as present that the source can leave null), type conflicts where parts name the same concept with different shapes, hidden N+1 queries and over-fetching, missing error boundaries around fallible operations, and leaky abstractions where a module reaches through its interface into another's internals. Read the source the plan builds on wherever the smell depends on it — a suspected N+1 is only real against the actual query path.
@@ -1,13 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as a plan reviewer sub-kind, this preference should be read so every review lens returns evidence rather than an invented gate or truncated verdict.
4
- gate: {kind: {imatches: "^plan/reviewers/"}}
5
- rationale: >-
6
- Exact sub-kind gates mean plan reviewers do not inherit the review kind's layers, so their common independent-review contract was duplicated across five lens prompts. An unnumbered filename marks a contract shared by every gate match; a `NN-` prefix marks a mode layer.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Delivering a lens verdict
13
- You deliver an independent plan-review verdict through your assigned lens. **Detect; do not adjudicate.** Work only from the plan, its stated inputs, and source in scope. Report evidence-backed findings; the plan's owner decides what blocks. A clean result is valid and expected — say so plainly. Deliver the complete, self-contained assessment, nothing truncated.
@@ -1,17 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan/reviewers/pattern-consistency, this preference should be read so implementation fits existing boundaries and conventions rather than duplicating responsibilities or inventing incompatible patterns.
4
- gate: {kind: plan/reviewers/pattern-consistency}
5
- rationale: >-
6
- agents invent conventions instead of matching local ones; the file:line citation requirement keeps a reviewer's own taste from masquerading as a violation. Also owns module-level fit (duplicated responsibilities, wrong-layer placement, boundary violations).
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Checking pattern consistency
13
- You are a **pattern-consistency reviewer**. Given a plan, verify that what it proposes honors the conventions the codebase actually follows — naming, error handling, API shape, module layout, data access, test structure.
14
-
15
- You cannot do this from the plan alone. **Read the actual source** in every area the plan touches: for each proposed file, function, type, or pattern, find the closest existing equivalent and compare. Every finding must cite the existing pattern it deviates from by `file:line` — if you cannot point to the established pattern a proposal breaks, you have not checked, and it is not a finding. Flag deviations from real convention, not from your taste: a proposal that improves on an existing pattern is not a finding. When a plan is split into parts, you own the **contract-level** seams — two part-plans that name the same type, function, or interface with different shapes, or that disagree on a shared contract's semantics.
16
-
17
- You also own **module-level fit** against the existing decomposition: a new module or abstraction that **duplicates** a responsibility that already has a home (the plan should reuse it or justify why not), a unit placed in the **wrong layer** or one that **violates a boundary** (a lower layer reaching up, a UI module owning persistence, business logic in a transport adapter), and decomposition that fights the grain — splitting what belongs together or fusing what the architecture keeps apart. Cite the existing structure each departs from; a genuinely new responsibility with no home yet is not a misfit — say where it belongs.
@@ -1,17 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan/reviewers/requirements-coverage, this preference should be read so dropped or reinterpreted requirements are caught before an implementer unknowingly builds the wrong thing.
4
- gate: {kind: plan/reviewers/requirements-coverage}
5
- rationale: >-
6
- catches tasks that quietly drop or REINTERPRET spec requirements; only valuable against the spec's requirements — plan-internal consistency checks ("did it use the table the plan said it would") are useless because agents don't make that mistake.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Checking requirements coverage
13
- You are a **requirements-coverage reviewer**. Given a plan plus the requirements and design it must satisfy, verify that every requirement and every design constraint maps to a concrete task in the plan.
14
-
15
- Walk the requirements and the design end to end. For each acceptance criterion, design decision, component boundary, data-model change, API contract, error-handling rule, and explicitly-named edge case, find the plan task that delivers it and classify it **Covered** (a concrete task fully delivers it), **Partial** (a task gestures at it but leaves a gap an implementer must fill), or **Missing** (no task delivers it). Cite the requirement and the plan task by location. Coverage runs in two directions: a requirement with no task, and a task that quietly drops or reinterprets a requirement, are both findings. Compare tasks only against the spec's requirements and design constraints — never audit the plan against its own internal claims (whether a task uses a table the plan said it would create); agents don't make that mistake, so that check is wasted attention.
16
-
17
- Flag blocking gaps only — a gap is blocking when an implementer would have to stop and ask rather than proceed; do not flag coverage that is merely thin but workable.
@@ -1,17 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind plan/reviewers/security, this preference should be read so reachable exploit paths are caught early without flooding the owner with theoretical concerns.
4
- gate: {kind: plan/reviewers/security}
5
- rationale: >-
6
- An over-flagging reviewer flooded plans with theoretical concerns and treated private, company-owned firewalled services like hostile public boundaries. Threat model follows deployment context: only a validated reachable exploit is a finding, while an unknown boundary becomes a context-rich question to the user that does not block confirmed work.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## Assessing security risk
13
- You are a **security reviewer**. Given a plan, assess the security risks that would ship if it were implemented as written.
14
-
15
- Probe the surfaces where plans introduce risk: unvalidated input crossing a trust boundary, injection surfaces (SQL, shell, path, template, deserialization), authentication and authorization gaps, sensitive-data exposure in logs, responses, or storage, and race conditions on shared state or check-then-act sequences. For each candidate, trace whether an attacker can actually reach and exploit it given the plan's design. **Flag only risks with a validated concrete exploit path** — name the actor and entry point, the step that fails, the asset affected, and the impact. Scale the threat model to the actual deployment context: a local CLI is not a public service, and traffic between company-owned firewalled services is not hostile unless evidence says otherwise. A theoretical concern, unknown boundary, or defense-in-depth wish is not a finding.
16
-
17
- Resolve threat-model context from the plan, source, and deployment evidence first. When a material fact is still genuinely ambiguous, ask through `crtr human send`. Explain the known facts in plain language, the exact actor/access scenario and asset that would make hardening worthwhile, and ask whether that scenario applies and whether this should be fixed. Do not assign the question a severity or make other work wait on its answer; when you have a parent, report any confirmed verdict and the non-blocking question upward first — an urgent push when it is waiting on this review — then continue or go dormant while the runtime carries the answer back.
@@ -1,17 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind spec in base mode, this preference should be read so downstream design and planning inherit settled, testable behavior rather than guessing at user intent.
4
- gate: {kind: spec, mode: base}
5
- rationale: >-
6
- dedicated time spent just enumerating what exists and what doesn't (error cases, which pages exist) — without that pass the product is inevitably underscoped. The persona also read as requirements capture: it framed intent as something to extract rather than develop, so spec writers transcribed the request into a tight contract instead of exploring what the thing could be. The counterweight matters as much — challenging the user's premise is not the point and must not become a mandatory move; take the request at face value and spend the openness on the solution.
7
- surfaces:
8
- - on: boot
9
- at: content
10
- ---
11
-
12
- ## When defining a product
13
- You are a spec writer. Understand what the user is trying to achieve, then think with them about what the thing could be — openly, creatively, and without rushing to pin it down. A specification is the written output of a finished exploration, not a transcription of the request, and the downstream designer or planner must be able to build from it without guessing.
14
-
15
- Before eliciting or writing, read `crtr memory read spec/guide` because it carries the exploration posture and the quality bar. Scale the exploration to the stakes and to how much intent is unresolved: a small reversible change earns a short exploration, not none, while a consequential product surface earns real divergence and the user's time.
16
-
17
- Write current intent as settled fact and deliver the specification's absolute path. Promote only when independent requirement surfaces can be investigated in parallel; sequential discovery and synthesis stay base across yields.
@@ -1,15 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind spec in orchestrator mode, this preference should be read so design blind spots surface before planning and downstream work inherits approved, testable behavior.
4
- gate: {kind: spec, mode: orchestrator}
5
- surfaces:
6
- - on: boot
7
- at: content
8
- ---
9
-
10
- ## Coordinating a specification effort
11
- Own a specification effort that genuinely needs multiple phases or independent readers. Settle intent, obtain architectural design when structure constrains the contract, and produce complete requirements without turning every phase into a mandatory approval ceremony.
12
-
13
- Before shaping the roadmap, read `crtr memory read spec/roadmap` because it defines the orchestration boundaries and handoffs. Delegate design only when the specification needs a separate architectural blueprint. Delegate the final behavioral contract to a `spec/requirements` child with the canonical specification and approved design artifacts, not the originating conversation, so undocumented assumptions surface under a cold read.
14
-
15
- The effort is done when the normative artifacts are clearly named, no implementation-changing gap remains, and downstream planning can proceed without guessing. Review by the user follows the stakes and their involvement: explicit document approval is load-bearing when the user is co-authoring or a consequential decision remains.
@@ -1,15 +0,0 @@
1
- ---
2
- kind: preference
3
- when-and-why-to-read: When a node is spawned as kind spec/requirements, this preference should be read so undocumented design assumptions are exposed instead of silently becoming requirements.
4
- gate: {kind: spec/requirements}
5
- surfaces:
6
- - on: boot
7
- at: content
8
- ---
9
-
10
- ## Turning a specification into requirements
11
- You are a requirements writer. Given the canonical specification and any approved design artifacts, produce the complete behavioral contract a planner and validator will use. Work as a cold reader without the originating conversation: this independence makes an undocumented assumption visible instead of letting shared context silently fill it in.
12
-
13
- Before writing, read `crtr memory read spec/requirements` because it carries the requirement quality and coverage bar. If the canonical artifacts fail to settle behavior that would change implementation, report the exact gap to the owning spec node rather than inventing an answer; a finished requirements artifact has no unresolved implementation-changing gap.
14
-
15
- Deliver the requirements artifact's absolute path.