@crouton-kit/crouter 0.3.17 → 0.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-root.js +6 -0
- package/dist/builtin-memory/crouter-development/marketplaces.md +164 -0
- package/dist/builtin-memory/crouter-development/personas/base-prompt.md +58 -0
- package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +60 -0
- package/dist/builtin-memory/crouter-development/personas.md +117 -0
- package/dist/builtin-memory/crouter-development/plugins.md +163 -0
- package/dist/builtin-memory/design.md +60 -0
- package/dist/builtin-memory/development.md +116 -0
- package/dist/builtin-memory/planning.md +66 -0
- package/dist/builtin-memory/spec.md +99 -0
- package/dist/builtin-personas/design/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/design/orchestrator.md +1 -1
- package/dist/builtin-personas/developer/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/developer/orchestrator.md +1 -1
- package/dist/builtin-personas/explore/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/general/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/lifecycle/resident.md +1 -1
- package/dist/builtin-personas/lifecycle/terminal.md +5 -2
- package/dist/builtin-personas/orchestration-kernel.md +15 -24
- package/dist/builtin-personas/plan/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/plan/orchestrator.md +1 -1
- package/dist/builtin-personas/plan/reviewers/architecture-fit/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/code-smells/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/pattern-consistency/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/requirements-coverage/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/plan/reviewers/security/{base.md → PERSONA.md} +1 -1
- package/dist/builtin-personas/review/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/runtime-base.md +6 -3
- package/dist/builtin-personas/spec/{base.md → PERSONA.md} +4 -0
- package/dist/builtin-personas/spec/orchestrator.md +1 -1
- package/dist/builtin-personas/waiting.md +8 -0
- package/dist/builtin-skills/skills/crouter-development/personas/SKILL.md +24 -14
- package/dist/builtin-skills/skills/crouter-development/personas/base-prompt/SKILL.md +4 -4
- package/dist/builtin-skills/skills/crouter-development/personas/orchestrator-prompt/SKILL.md +1 -1
- package/dist/builtin-skills/skills/crouter-development/plugins/SKILL.md +2 -2
- package/dist/builtin-views/_lib/states.mjs +161 -0
- package/dist/builtin-views/canvas/client.mjs +303 -0
- package/dist/builtin-views/canvas/view.mjs +576 -0
- package/dist/builtin-views/git-pr/client.mjs +440 -0
- package/dist/builtin-views/git-pr/view.mjs +675 -0
- package/dist/builtin-views/inbox/_lib/render.mjs +177 -0
- package/dist/builtin-views/inbox/sources/gmail.mjs +965 -0
- package/dist/builtin-views/inbox/sources/linkedin.mjs +427 -0
- package/dist/builtin-views/inbox/view.mjs +889 -0
- package/dist/builtin-views/linkedin/client.mjs +610 -0
- package/dist/builtin-views/linkedin/view.mjs +1171 -0
- package/dist/clients/attach/attach-cmd.d.ts +2 -0
- package/dist/clients/attach/attach-cmd.js +354 -0
- package/dist/clients/attach/chat-view.d.ts +77 -0
- package/dist/clients/attach/chat-view.js +450 -0
- package/dist/clients/attach/clipboard-image.d.ts +16 -0
- package/dist/clients/attach/clipboard-image.js +113 -0
- package/dist/clients/attach/config-load.d.ts +31 -0
- package/dist/clients/attach/config-load.js +113 -0
- package/dist/clients/attach/extension-dialogs.d.ts +29 -0
- package/dist/clients/attach/extension-dialogs.js +101 -0
- package/dist/clients/attach/input-controller.d.ts +54 -0
- package/dist/clients/attach/input-controller.js +204 -0
- package/dist/clients/attach/slash-commands.d.ts +36 -0
- package/dist/clients/attach/slash-commands.js +200 -0
- package/dist/clients/attach/view-socket.d.ts +48 -0
- package/dist/clients/attach/view-socket.js +126 -0
- package/dist/commands/attention.js +3 -3
- package/dist/commands/canvas-prune.js +1 -1
- package/dist/commands/daemon.js +4 -3
- package/dist/commands/human/prompts.js +4 -10
- package/dist/commands/human/queue.js +43 -8
- package/dist/commands/human/shared.d.ts +28 -1
- package/dist/commands/human/shared.js +48 -10
- package/dist/commands/memory/find.d.ts +1 -0
- package/dist/commands/memory/find.js +180 -0
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +140 -0
- package/dist/commands/memory/list.d.ts +1 -0
- package/dist/commands/memory/list.js +79 -0
- package/dist/commands/memory/read.js +103 -0
- package/dist/commands/memory/shared.d.ts +30 -0
- package/dist/commands/memory/shared.js +122 -0
- package/dist/commands/memory/write.d.ts +1 -0
- package/dist/commands/memory/write.js +85 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +27 -0
- package/dist/commands/node.d.ts +3 -2
- package/dist/commands/node.js +660 -65
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/push.js +6 -6
- package/dist/commands/revive.js +1 -1
- package/dist/commands/skill/author.js +1 -1
- package/dist/commands/skill/shared.d.ts +1 -8
- package/dist/commands/skill/shared.js +2 -55
- package/dist/commands/skill.js +9 -14
- package/dist/commands/sys/doctor.js +1 -1
- package/dist/commands/sys/update.js +1 -1
- package/dist/commands/view-cycle.d.ts +2 -0
- package/dist/commands/view-cycle.js +125 -0
- package/dist/commands/view-list.d.ts +2 -0
- package/dist/commands/view-list.js +66 -0
- package/dist/commands/view-new.d.ts +2 -0
- package/dist/commands/view-new.js +70 -0
- package/dist/commands/view-pick.d.ts +2 -0
- package/dist/commands/view-pick.js +119 -0
- package/dist/commands/view-run.d.ts +2 -0
- package/dist/commands/view-run.js +191 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +29 -0
- package/dist/core/__tests__/broker-lifecycle.test.d.ts +1 -0
- package/dist/core/__tests__/broker-lifecycle.test.js +677 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.d.ts +1 -0
- package/dist/core/__tests__/broker-sdk-wiring.test.js +166 -0
- package/dist/core/__tests__/cascade-close.test.js +12 -2
- package/dist/core/__tests__/child-death-wake.test.d.ts +1 -0
- package/dist/core/__tests__/child-death-wake.test.js +245 -0
- package/dist/core/__tests__/context-intro.test.js +76 -62
- package/dist/core/__tests__/daemon-boot.test.js +14 -5
- package/dist/core/__tests__/daemon-liveness.test.js +34 -9
- package/dist/core/__tests__/detach-focus.test.d.ts +1 -0
- package/dist/core/__tests__/detach-focus.test.js +206 -0
- package/dist/core/__tests__/draw-style.test.d.ts +1 -0
- package/dist/core/__tests__/draw-style.test.js +258 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +2 -0
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +18 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +138 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +614 -0
- package/dist/core/__tests__/fixtures/fake-pi-host.js +1 -0
- package/dist/core/__tests__/flagship-lifecycle.test.js +7 -1
- package/dist/core/__tests__/frame-decoder-perf.test.d.ts +1 -0
- package/dist/core/__tests__/frame-decoder-perf.test.js +198 -0
- package/dist/core/__tests__/helpers/harness.d.ts +9 -0
- package/dist/core/__tests__/helpers/harness.js +111 -1
- package/dist/core/__tests__/home-session.test.js +41 -8
- package/dist/core/__tests__/human-new-window-regression.test.d.ts +1 -0
- package/dist/core/__tests__/human-new-window-regression.test.js +101 -0
- package/dist/core/__tests__/human-surface-target.test.d.ts +1 -0
- package/dist/core/__tests__/human-surface-target.test.js +98 -0
- package/dist/core/__tests__/kickoff.test.js +37 -3
- package/dist/core/__tests__/live-mutation.test.js +50 -33
- package/dist/core/__tests__/memory.test.js +23 -115
- package/dist/core/__tests__/persona-subkind.test.js +18 -15
- package/dist/core/__tests__/placement-focus.test.js +5 -0
- package/dist/core/__tests__/placement-teardown.test.js +54 -11
- package/dist/core/__tests__/relaunch.test.js +4 -3
- package/dist/core/__tests__/review-render-pane-regression.test.d.ts +1 -0
- package/dist/core/__tests__/review-render-pane-regression.test.js +133 -0
- package/dist/core/__tests__/spawn-root.test.js +10 -0
- package/dist/core/__tests__/spike-harness.test.js +1 -0
- package/dist/core/__tests__/wake-bearings.test.d.ts +1 -0
- package/dist/core/__tests__/wake-bearings.test.js +156 -0
- package/dist/core/__tests__/wake-origin.test.d.ts +1 -0
- package/dist/core/__tests__/wake-origin.test.js +110 -0
- package/dist/core/bootstrap.js +1 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.js +24 -2
- package/dist/core/canvas/browse/model.d.ts +38 -2
- package/dist/core/canvas/browse/model.js +134 -10
- package/dist/core/canvas/browse/render.d.ts +6 -12
- package/dist/core/canvas/browse/render.js +72 -104
- package/dist/core/canvas/canvas.js +15 -22
- package/dist/core/canvas/db.js +46 -0
- package/dist/core/canvas/index.d.ts +1 -0
- package/dist/core/canvas/index.js +1 -0
- package/dist/core/canvas/paths.d.ts +4 -1
- package/dist/core/canvas/paths.js +10 -4
- package/dist/core/canvas/pid.d.ts +4 -0
- package/dist/core/canvas/pid.js +23 -0
- package/dist/core/canvas/render.d.ts +11 -2
- package/dist/core/canvas/render.js +69 -0
- package/dist/core/canvas/types.d.ts +85 -3
- package/dist/core/canvas/types.js +2 -2
- package/dist/core/canvas/wakeups.d.ts +76 -0
- package/dist/core/canvas/wakeups.js +185 -0
- package/dist/core/config.js +4 -1
- package/dist/core/frontmatter.js +37 -124
- package/dist/core/help.d.ts +6 -0
- package/dist/core/help.js +7 -0
- package/dist/core/memory-resolver.d.ts +49 -0
- package/dist/core/memory-resolver.js +141 -0
- package/dist/core/personas/index.d.ts +4 -3
- package/dist/core/personas/index.js +3 -2
- package/dist/core/personas/loader.d.ts +41 -16
- package/dist/core/personas/loader.js +133 -29
- package/dist/core/personas/resolve.d.ts +4 -4
- package/dist/core/personas/resolve.js +28 -16
- package/dist/core/predicate.d.ts +63 -0
- package/dist/core/predicate.js +189 -0
- package/dist/core/resolver.js +26 -5
- package/dist/core/runtime/bearings.d.ts +53 -12
- package/dist/core/runtime/bearings.js +132 -59
- package/dist/core/runtime/broker-cli.d.ts +1 -0
- package/dist/core/runtime/broker-cli.js +46 -0
- package/dist/core/runtime/broker-protocol.d.ts +332 -0
- package/dist/core/runtime/broker-protocol.js +153 -0
- package/dist/core/runtime/broker-sdk.d.ts +48 -0
- package/dist/core/runtime/broker-sdk.js +72 -0
- package/dist/core/runtime/broker.d.ts +55 -0
- package/dist/core/runtime/broker.js +1128 -0
- package/dist/core/runtime/close.js +35 -6
- package/dist/core/runtime/host.d.ts +53 -0
- package/dist/core/runtime/host.js +186 -0
- package/dist/core/runtime/kickoff.d.ts +2 -1
- package/dist/core/runtime/kickoff.js +91 -5
- package/dist/core/runtime/launch.d.ts +45 -2
- package/dist/core/runtime/launch.js +65 -2
- package/dist/core/runtime/lifecycle.js +23 -6
- package/dist/core/runtime/memory.d.ts +2 -42
- package/dist/core/runtime/memory.js +11 -162
- package/dist/core/runtime/nodes.d.ts +33 -0
- package/dist/core/runtime/nodes.js +59 -1
- package/dist/core/runtime/persona.js +21 -11
- package/dist/core/runtime/pi-vendored.d.ts +18 -0
- package/dist/core/runtime/pi-vendored.js +49 -0
- package/dist/core/runtime/placement.d.ts +42 -14
- package/dist/core/runtime/placement.js +228 -38
- package/dist/core/runtime/promote.d.ts +0 -6
- package/dist/core/runtime/promote.js +1 -12
- package/dist/core/runtime/{demote.d.ts → recycle.d.ts} +5 -5
- package/dist/core/runtime/{demote.js → recycle.js} +27 -11
- package/dist/core/runtime/reset.js +8 -6
- package/dist/core/runtime/revive.d.ts +2 -0
- package/dist/core/runtime/revive.js +34 -34
- package/dist/core/runtime/spawn.d.ts +19 -0
- package/dist/core/runtime/spawn.js +75 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +6 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +28 -0
- package/dist/core/runtime/tmux.js +80 -6
- package/dist/core/scope.d.ts +11 -0
- package/dist/core/scope.js +39 -0
- package/dist/core/spawn.d.ts +25 -1
- package/dist/core/spawn.js +72 -7
- package/dist/core/substrate/gate.d.ts +13 -0
- package/dist/core/substrate/gate.js +21 -0
- package/dist/core/substrate/index.d.ts +7 -0
- package/dist/core/substrate/index.js +18 -0
- package/dist/core/substrate/on-read.d.ts +14 -0
- package/dist/core/substrate/on-read.js +292 -0
- package/dist/core/substrate/render.d.ts +25 -0
- package/dist/core/substrate/render.js +256 -0
- package/dist/core/substrate/schema.d.ts +76 -0
- package/dist/core/substrate/schema.js +124 -0
- package/dist/core/substrate/session-cache.d.ts +30 -0
- package/dist/core/substrate/session-cache.js +77 -0
- package/dist/core/substrate/subject.d.ts +41 -0
- package/dist/core/substrate/subject.js +54 -0
- package/dist/core/tui/contract.d.ts +83 -0
- package/dist/core/tui/contract.js +8 -0
- package/dist/core/tui/draw.d.ts +96 -0
- package/dist/core/tui/draw.js +339 -0
- package/dist/core/tui/host.d.ts +29 -0
- package/dist/core/tui/host.js +379 -0
- package/dist/core/tui/loader.d.ts +16 -0
- package/dist/core/tui/loader.js +94 -0
- package/dist/core/{canvas/browse → tui}/terminal.js +7 -6
- package/dist/core/wake.d.ts +86 -0
- package/dist/core/wake.js +308 -0
- package/dist/daemon/crtrd.d.ts +29 -4
- package/dist/daemon/crtrd.js +662 -46
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +171 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +19 -12
- package/dist/pi-extensions/canvas-commands.d.ts +3 -0
- package/dist/pi-extensions/canvas-commands.js +10 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +17 -0
- package/dist/pi-extensions/canvas-context-intro.js +55 -15
- package/dist/pi-extensions/canvas-doc-substrate.d.ts +44 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +112 -0
- package/dist/pi-extensions/canvas-nav.d.ts +3 -0
- package/dist/pi-extensions/canvas-nav.js +145 -34
- package/dist/pi-extensions/canvas-stophook.js +17 -8
- package/dist/pi-extensions/canvas-view.d.ts +21 -0
- package/dist/pi-extensions/canvas-view.js +75 -0
- package/dist/prompts/skill.js +19 -26
- package/dist/prompts/view.d.ts +7 -0
- package/dist/prompts/view.js +101 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -0
- package/package.json +9 -4
- package/dist/commands/skill/find.d.ts +0 -4
- package/dist/commands/skill/find.js +0 -257
- package/dist/commands/skill/read.js +0 -91
- /package/dist/commands/{skill → memory}/read.d.ts +0 -0
- /package/dist/core/{canvas/browse → tui}/terminal.d.ts +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Shared constants + helpers for the `crtr memory` command family (task B2).
|
|
2
|
+
// The leaf handlers (list/read/find/write) consume the resolver, substrate
|
|
3
|
+
// schema, scope, and skill-resolver modules and build their documented output
|
|
4
|
+
// objects on top of the small helpers here. Nothing in this file forks on kind
|
|
5
|
+
// or re-implements the schema/gate/resolver — it only composes them.
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
|
|
8
|
+
import { usage } from '../../core/errors.js';
|
|
9
|
+
import { scopeMemoryDir, projectScopeRoot, ensureProjectScopeRoot, } from '../../core/scope.js';
|
|
10
|
+
// The three memory kinds — procedural (skill), referential (reference),
|
|
11
|
+
// preferential (preference). Used as the `--kind` enum choices everywhere.
|
|
12
|
+
export const MEMORY_KINDS = ['skill', 'reference', 'preference'];
|
|
13
|
+
// Visibility rungs — how much of a document surfaces (none → name → preview →
|
|
14
|
+
// content). Shared by --system-prompt-visibility and --file-read-visibility.
|
|
15
|
+
export const VISIBILITY_RUNGS = ['none', 'name', 'preview', 'content'];
|
|
16
|
+
// Scope choices for filtering / targeting (builtin is read-only, not writable).
|
|
17
|
+
export const MEMORY_SCOPES = ['user', 'project'];
|
|
18
|
+
/** Scope sort weight matching resolution precedence (project > user > builtin).
|
|
19
|
+
* Used by `list` for its "scope then kind then name" ordering. */
|
|
20
|
+
export function scopeRank(scope) {
|
|
21
|
+
return scope === 'project' ? 0 : scope === 'user' ? 1 : 2;
|
|
22
|
+
}
|
|
23
|
+
/** Resolve the write target scope + its memory dir. Default: project when a
|
|
24
|
+
* project scope exists for the cwd, else user. An explicit `--scope project`
|
|
25
|
+
* with no project scope yet scaffolds one (ensureProjectScopeRoot). User scope
|
|
26
|
+
* always resolves. Returns the absolute `<root>/memory` dir to write under. */
|
|
27
|
+
export function resolveWriteTarget(scopeArg) {
|
|
28
|
+
let scope;
|
|
29
|
+
if (scopeArg === 'user' || scopeArg === 'project') {
|
|
30
|
+
scope = scopeArg;
|
|
31
|
+
}
|
|
32
|
+
else if (scopeArg !== undefined) {
|
|
33
|
+
throw usage(`invalid --scope: ${scopeArg} (expected user|project)`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
scope = projectScopeRoot() !== null ? 'project' : 'user';
|
|
37
|
+
}
|
|
38
|
+
let memoryDir = scopeMemoryDir(scope);
|
|
39
|
+
if (!memoryDir && scope === 'project') {
|
|
40
|
+
// Explicit --scope project with no project root yet → scaffold it.
|
|
41
|
+
memoryDir = join(ensureProjectScopeRoot(), 'memory');
|
|
42
|
+
}
|
|
43
|
+
if (!memoryDir)
|
|
44
|
+
throw usage(`no ${scope} scope available for writing memory documents`);
|
|
45
|
+
return { scope, memoryDir };
|
|
46
|
+
}
|
|
47
|
+
/** Map a path-derived name (`topic` or `area/topic`) to its file path under a
|
|
48
|
+
* memory dir, guarding against traversal/absolute escapes. */
|
|
49
|
+
export function memoryFilePath(memoryDir, name) {
|
|
50
|
+
const segments = name.split('/').filter((s) => s.length > 0);
|
|
51
|
+
if (segments.length === 0)
|
|
52
|
+
throw usage('memory document name required');
|
|
53
|
+
if (segments.some((s) => s === '.' || s === '..')) {
|
|
54
|
+
throw usage(`invalid memory document name: ${name}`);
|
|
55
|
+
}
|
|
56
|
+
return join(memoryDir, ...segments) + '.md';
|
|
57
|
+
}
|
|
58
|
+
/** Coerce a `--gate` string into a predicate tree. The gate field MUST be a
|
|
59
|
+
* YAML/JSON object (the field→matcher map the schema expects). Throws a usage
|
|
60
|
+
* error when the input fails to parse or does not parse to a non-null,
|
|
61
|
+
* non-array object — a scalar or array gate silently makes a doc never-eligible
|
|
62
|
+
* (the matcher engine ignores non-object predicates), so passing one is always
|
|
63
|
+
* a mistake and must be caught at authoring time rather than stored. */
|
|
64
|
+
function parseYamlObject(raw) {
|
|
65
|
+
const parsed = yamlParse(raw);
|
|
66
|
+
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
67
|
+
return parsed;
|
|
68
|
+
}
|
|
69
|
+
return `expected an object, got ${JSON.stringify(parsed)}`;
|
|
70
|
+
}
|
|
71
|
+
export function coerceGate(raw) {
|
|
72
|
+
const result = parseYamlObject(raw);
|
|
73
|
+
if (typeof result === 'string') {
|
|
74
|
+
throw usage(`--gate must be a YAML/JSON object (field→matcher map): ${result}. ` +
|
|
75
|
+
`Example: --gate '{kind: design}' or --gate '{orchestration.depth: {gte: 2}}'`);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/** Coerce a `--applies-to` string to the schema's glob form: a comma-separated
|
|
80
|
+
* list becomes an array, a single glob stays a string. */
|
|
81
|
+
export function coerceAppliesTo(raw) {
|
|
82
|
+
const parts = raw
|
|
83
|
+
.split(',')
|
|
84
|
+
.map((s) => s.trim())
|
|
85
|
+
.filter((s) => s.length > 0);
|
|
86
|
+
if (parts.length === 0)
|
|
87
|
+
return raw;
|
|
88
|
+
return parts.length === 1 ? parts[0] : parts;
|
|
89
|
+
}
|
|
90
|
+
// Canonical frontmatter field order for a substrate document. Known fields come
|
|
91
|
+
// first in this order; any preserved-on-update extras append after.
|
|
92
|
+
const FRONTMATTER_ORDER = [
|
|
93
|
+
'kind',
|
|
94
|
+
'when',
|
|
95
|
+
'why',
|
|
96
|
+
'short-form',
|
|
97
|
+
'system-prompt-visibility',
|
|
98
|
+
'file-read-visibility',
|
|
99
|
+
'gate',
|
|
100
|
+
'applies-to',
|
|
101
|
+
];
|
|
102
|
+
/** Serialize a substrate frontmatter record + body into a complete `.md`
|
|
103
|
+
* document. Frontmatter is emitted as a `---` fenced YAML block (the `yaml`
|
|
104
|
+
* package — the same one the parser uses — so nested gate maps and applies-to
|
|
105
|
+
* arrays round-trip), in canonical field order with preserved extras last. The
|
|
106
|
+
* skill-shaped `serializeFrontmatter` in core can only represent
|
|
107
|
+
* name/description/type/keywords, so it cannot carry the substrate fields —
|
|
108
|
+
* hence this focused serializer. */
|
|
109
|
+
export function serializeMemoryDoc(frontmatter, body) {
|
|
110
|
+
const ordered = {};
|
|
111
|
+
for (const key of FRONTMATTER_ORDER) {
|
|
112
|
+
if (frontmatter[key] !== undefined)
|
|
113
|
+
ordered[key] = frontmatter[key];
|
|
114
|
+
}
|
|
115
|
+
for (const key of Object.keys(frontmatter)) {
|
|
116
|
+
if (!(key in ordered) && frontmatter[key] !== undefined)
|
|
117
|
+
ordered[key] = frontmatter[key];
|
|
118
|
+
}
|
|
119
|
+
const yamlText = yamlStringify(ordered).replace(/\n+$/, '');
|
|
120
|
+
const cleanBody = body.replace(/^\n+/, '').replace(/\s+$/, '');
|
|
121
|
+
return `---\n${yamlText}\n---\n\n${cleanBody}\n`;
|
|
122
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const writeLeaf: import("../../core/command.js").LeafDef;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { defineLeaf } from '../../core/command.js';
|
|
2
|
+
import { usage } from '../../core/errors.js';
|
|
3
|
+
import { parseFrontmatterGeneric } from '../../core/frontmatter.js';
|
|
4
|
+
import { readText, writeText, pathExists } from '../../core/fs-utils.js';
|
|
5
|
+
import { MEMORY_KINDS, MEMORY_SCOPES, VISIBILITY_RUNGS, resolveWriteTarget, memoryFilePath, coerceGate, coerceAppliesTo, serializeMemoryDoc, } from './shared.js';
|
|
6
|
+
export const writeLeaf = defineLeaf({
|
|
7
|
+
name: 'write',
|
|
8
|
+
description: 'create or update a memory document',
|
|
9
|
+
whenToUse: 'you are recording a new skill, reference, or preference — or revising one that already exists. Writes memory/<name>.md at the resolved scope from the frontmatter flags plus a body piped on stdin. Identity is path-derived: if <name> already exists at the scope it is updated in place, otherwise it is created.',
|
|
10
|
+
help: {
|
|
11
|
+
name: 'memory write',
|
|
12
|
+
summary: 'create or update memory/<name>.md at the resolved scope from frontmatter flags + a stdin body',
|
|
13
|
+
params: [
|
|
14
|
+
{ kind: 'positional', name: 'name', required: true, constraint: 'Path-derived identity (e.g. `topic` or `area/topic`) → memory/<name>.md at the resolved scope. Updated in place if it already exists, otherwise created.' },
|
|
15
|
+
{ kind: 'flag', name: 'kind', type: 'enum', choices: [...MEMORY_KINDS], required: true, constraint: 'Document kind.' },
|
|
16
|
+
{ kind: 'flag', name: 'when', type: 'string', required: false, constraint: 'Frontmatter whenText — a short string describing when this document should be read.' },
|
|
17
|
+
{ kind: 'flag', name: 'why', type: 'string', required: false, constraint: 'Frontmatter whyText — a short string describing why this document matters.' },
|
|
18
|
+
{ kind: 'flag', name: 'short-form', type: 'string', required: false, constraint: 'Frontmatter short-form — a very abbreviated version of the content, the hook shown in `crtr memory list`.' },
|
|
19
|
+
{ kind: 'flag', name: 'system-prompt-visibility', type: 'enum', choices: [...VISIBILITY_RUNGS], required: false, constraint: 'Rung controlling how much of this document auto-loads into the system prompt / CLI help.' },
|
|
20
|
+
{ kind: 'flag', name: 'file-read-visibility', type: 'enum', choices: [...VISIBILITY_RUNGS], required: false, constraint: 'Rung controlling how much of this document surfaces when it is read off disk.' },
|
|
21
|
+
{ kind: 'flag', name: 'gate', type: 'string', required: false, constraint: 'Frontmatter gate — expression/condition that determines when this document applies.' },
|
|
22
|
+
{ kind: 'flag', name: 'applies-to', type: 'string', required: false, constraint: 'Frontmatter applies-to — glob/path scope the document applies to.' },
|
|
23
|
+
{ kind: 'flag', name: 'scope', type: 'enum', choices: [...MEMORY_SCOPES], required: false, constraint: 'Target scope. Default: project when inside a project, else user.' },
|
|
24
|
+
{ kind: 'stdin', name: 'body', required: true, constraint: 'Document body (markdown, no frontmatter). Piped on stdin, or passed as the bare positional after <name>.' },
|
|
25
|
+
],
|
|
26
|
+
output: [
|
|
27
|
+
{ name: 'name', type: 'string', required: true, constraint: 'The path-derived document name written.' },
|
|
28
|
+
{ name: 'kind', type: 'string', required: true, constraint: 'Kind recorded in frontmatter.' },
|
|
29
|
+
{ name: 'scope', type: 'string', required: true, constraint: 'Scope the document was written to: user or project.' },
|
|
30
|
+
{ name: 'path', type: 'string', required: true, constraint: 'Absolute path to the written document.' },
|
|
31
|
+
{ name: 'created', type: 'boolean', required: true, constraint: 'true when a new document was created, false when an existing one was updated in place.' },
|
|
32
|
+
{ name: 'follow_up', type: 'string', required: true, constraint: 'Concrete next commands — read it back or list the inventory.' },
|
|
33
|
+
],
|
|
34
|
+
outputKind: 'object',
|
|
35
|
+
effects: [
|
|
36
|
+
'Creates or overwrites memory/<name>.md at the resolved scope with the given frontmatter fields + stdin body.',
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
run: async (input) => {
|
|
40
|
+
const name = input['name'];
|
|
41
|
+
const kind = input['kind'];
|
|
42
|
+
const scopeArg = input['scope'];
|
|
43
|
+
const body = input['body'] ?? '';
|
|
44
|
+
const { scope, memoryDir } = resolveWriteTarget(scopeArg);
|
|
45
|
+
const path = memoryFilePath(memoryDir, name);
|
|
46
|
+
const created = !pathExists(path);
|
|
47
|
+
// CREATE requires the two prose fields that compose the generated preview
|
|
48
|
+
// routing line — without them every preview renders the degenerate
|
|
49
|
+
// '", read this <kind>. ."'. UPDATE inherits them from the existing doc.
|
|
50
|
+
if (created && (input['when'] === undefined || input['why'] === undefined)) {
|
|
51
|
+
throw usage(`creating ${name} requires --when and --why (they compose the preview routing line "{when}, read this ${kind}. {why}.")`);
|
|
52
|
+
}
|
|
53
|
+
// In-place update: start from the existing frontmatter (preserving fields
|
|
54
|
+
// not passed this time), then overlay the provided ones. Create: start clean.
|
|
55
|
+
const frontmatter = created
|
|
56
|
+
? {}
|
|
57
|
+
: { ...(parseFrontmatterGeneric(readText(path)).data ?? {}) };
|
|
58
|
+
// kind is required, always set. Optionals only overlay when provided so an
|
|
59
|
+
// update never erases a field the caller did not mention.
|
|
60
|
+
frontmatter['kind'] = kind;
|
|
61
|
+
const setIf = (key, value) => {
|
|
62
|
+
if (value !== undefined)
|
|
63
|
+
frontmatter[key] = value;
|
|
64
|
+
};
|
|
65
|
+
setIf('when', input['when']);
|
|
66
|
+
setIf('why', input['why']);
|
|
67
|
+
setIf('short-form', input['shortForm']);
|
|
68
|
+
setIf('system-prompt-visibility', input['systemPromptVisibility']);
|
|
69
|
+
setIf('file-read-visibility', input['fileReadVisibility']);
|
|
70
|
+
if (input['gate'] !== undefined)
|
|
71
|
+
frontmatter['gate'] = coerceGate(input['gate']);
|
|
72
|
+
if (input['appliesTo'] !== undefined) {
|
|
73
|
+
frontmatter['applies-to'] = coerceAppliesTo(input['appliesTo']);
|
|
74
|
+
}
|
|
75
|
+
writeText(path, serializeMemoryDoc(frontmatter, body));
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
kind,
|
|
79
|
+
scope,
|
|
80
|
+
path,
|
|
81
|
+
created,
|
|
82
|
+
follow_up: `Read it back with \`crtr memory read ${name}\`, or browse the inventory with \`crtr memory list\`.`,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// `crtr memory` subtree — the document substrate (skills, references,
|
|
2
|
+
// preferences) accessed via the CLI. Four flat leaves: list, read, find, write.
|
|
3
|
+
// SKELETON ONLY (task B1): the `-h` contracts here are final; the leaf handlers
|
|
4
|
+
// are stubs that B2 fills in. Mirrors `skill.ts` minus the loaded-skills
|
|
5
|
+
// catalog dynamicState.
|
|
6
|
+
import { defineBranch } from '../core/command.js';
|
|
7
|
+
import { listLeaf } from './memory/list.js';
|
|
8
|
+
import { readLeaf } from './memory/read.js';
|
|
9
|
+
import { findLeaf } from './memory/find.js';
|
|
10
|
+
import { writeLeaf } from './memory/write.js';
|
|
11
|
+
import { lintLeaf } from './memory/lint.js';
|
|
12
|
+
export function registerMemory() {
|
|
13
|
+
return defineBranch({
|
|
14
|
+
name: 'memory',
|
|
15
|
+
rootEntry: {
|
|
16
|
+
concept: 'a memory document you read on demand — a skill, reference, or preference',
|
|
17
|
+
desc: 'list, read, search, and write memory documents',
|
|
18
|
+
useWhen: 'a task matches a stored skill, reference, or preference — read it before improvising. `crtr memory read <name>` loads one by name; `crtr memory list` browses the inventory; `crtr memory find` searches by topic when you do not yet know the name. Names are path-derived crtr identifiers, not file paths — never cat or find the markdown off disk.',
|
|
19
|
+
},
|
|
20
|
+
help: {
|
|
21
|
+
name: 'memory',
|
|
22
|
+
summary: 'list, read, search, and write memory documents — skills, references, preferences',
|
|
23
|
+
model: '`list` for a human inventory of what is stored — one line per document, the only surface that shows short-form. `read` (leaf) loads one document body by name, resolved project > user > builtin with leaf-name fallback; --frontmatter keeps the YAML header. `find` when you do not yet know which document applies — it ranks by relevance over name/when/why/short-form, --body to also weigh bodies, --grep for an exact regex over bodies. `write` creates or updates memory/<name>.md at a scope from frontmatter flags + a body piped on stdin. `lint` strict-parses the whole bounded corpus and fails on any invalid frontmatter — run it after authoring. Append `-h` at any leaf for its full schema.',
|
|
24
|
+
},
|
|
25
|
+
children: [listLeaf, readLeaf, findLeaf, writeLeaf, lintLeaf],
|
|
26
|
+
});
|
|
27
|
+
}
|
package/dist/commands/node.d.ts
CHANGED
|
@@ -6,8 +6,9 @@ import { type BranchDef } from '../core/command.js';
|
|
|
6
6
|
export declare function childFollowUp(spawnerId: string | undefined): string;
|
|
7
7
|
/** The live node occupying a tmux pane (pane → window → node), or undefined.
|
|
8
8
|
* Defaults to $TMUX_PANE / the caller's current pane when `pane` is omitted —
|
|
9
|
-
* shared by `node
|
|
10
|
-
*
|
|
9
|
+
* shared by `node recycle` / `node demote` / `node lifecycle` / `node close` /
|
|
10
|
+
* `node cycle`, all of which act on "the agent in front of you". Exported for
|
|
11
|
+
* the `canvas chord` / `canvas tmux-spread` leaves,
|
|
11
12
|
* which resolve the active pane's node the same way. */
|
|
12
13
|
export declare function nodeInPane(pane?: string): string | undefined;
|
|
13
14
|
export declare function registerNode(): BranchDef;
|