@north-light/crouter 0.3.220 → 0.3.222
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/api/client.d.ts +29 -0
- package/dist/api/client.js +44 -0
- package/dist/api/dto/chat-inventory.d.ts +56 -0
- package/dist/api/dto/chat-inventory.js +11 -0
- package/dist/api/dto/human-requests.d.ts +88 -0
- package/dist/api/dto/human-requests.js +4 -0
- package/dist/api/dto/human.d.ts +3 -0
- package/dist/api/dto/profiles.d.ts +19 -5
- package/dist/api/dto/profiles.js +2 -1
- package/dist/api/dto/reviews.d.ts +2 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/routes.d.ts +8 -0
- package/dist/api/routes.js +11 -0
- package/dist/build-root.d.ts +2 -6
- package/dist/build-root.js +51 -4
- package/dist/builtin-memory/00-runtime-base/00-authoring.md +31 -0
- package/dist/builtin-memory/00-runtime-base/01-escalation.md +14 -0
- package/dist/builtin-memory/{insights/listen.md → 00-runtime-base/02-insight-capture.md} +1 -0
- package/dist/builtin-memory/02-turn-lifecycle/00-ending-a-turn.md +27 -0
- package/dist/builtin-memory/{02-lifecycle/01-resident.md → 02-turn-lifecycle/02-resident.md} +5 -0
- package/dist/builtin-memory/04-base-worker.md +4 -8
- package/dist/builtin-memory/04-orchestration-kernel.md +1 -1
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/advisor/advice-contract.md +1 -0
- package/dist/builtin-memory/05-kinds/design/00-base.md +2 -1
- package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +2 -1
- package/dist/builtin-memory/05-kinds/design/design-contract.md +19 -0
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/general/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/00-base.md +2 -1
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +2 -1
- package/dist/builtin-memory/05-kinds/plan/plan-contract.md +28 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -0
- package/dist/builtin-memory/05-kinds/review/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/review/security-findings.md +1 -0
- package/dist/builtin-memory/05-kinds/spec/00-base.md +4 -3
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -0
- package/dist/builtin-memory/design/guide.md +35 -0
- package/dist/builtin-memory/design/roadmap.md +21 -0
- package/dist/builtin-memory/insights/capture.md +1 -1
- package/dist/builtin-memory/internal/agent-shaping.md +3 -1
- package/dist/builtin-memory/internal/memory-loading.md +4 -0
- package/dist/builtin-memory/internal/plugins.md +10 -1
- package/dist/builtin-memory/internal/storage-tiers.md +1 -1
- package/dist/builtin-memory/plan/roadmap.md +6 -22
- package/dist/builtin-memory/spec/guide.md +23 -6
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +7 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +34 -16
- package/dist/clients/attach/__tests__/ref-autocomplete.test.js +1 -1
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -1
- package/dist/clients/attach/overlays/file-review.js +2 -2
- package/dist/clients/attach/render/markdown-source.js +106 -1
- package/dist/clients/attach/session/file-links.d.ts +13 -4
- package/dist/clients/attach/session/file-links.js +54 -58
- package/dist/clients/attach/session/keys.d.ts +1 -1
- package/dist/clients/attach/session/profile-files.js +1 -1
- package/dist/clients/attach/viewer.js +698 -696
- package/dist/clients/inbox/controller.js +1 -1
- package/dist/clients/inbox/resolve.d.ts +1 -0
- package/dist/clients/inbox/review/launch.d.ts +8 -4
- package/dist/clients/inbox/review/launch.js +55 -5
- package/dist/clients/inbox/review/review-client.d.ts +1 -0
- package/dist/clients/inbox/review/review-client.js +7 -1
- package/dist/clients/inbox/review-adapter.d.ts +1 -8
- package/dist/clients/inbox/review-adapter.js +4 -52
- package/dist/commands/__tests__/human.test.js +2 -2
- package/dist/commands/human/request.d.ts +2 -0
- package/dist/commands/human/request.js +281 -0
- package/dist/commands/human.js +5 -2
- package/dist/commands/memory/lint.js +2 -1
- package/dist/commands/memory/read.js +1 -0
- package/dist/commands/memory.js +1 -1
- package/dist/commands/pkg/market-manage.js +165 -75
- package/dist/commands/pkg/plugin-inspect.js +19 -2
- package/dist/commands/pkg/plugin-manage.d.ts +8 -3
- package/dist/commands/pkg/plugin-manage.js +72 -24
- package/dist/commands/profile/default.js +6 -10
- package/dist/commands/profile/list.js +5 -3
- package/dist/commands/profile/new.js +21 -8
- package/dist/commands/profile/project.js +25 -19
- package/dist/commands/profile/show.js +3 -3
- package/dist/commands/surface-inbox.js +1 -0
- package/dist/commands/sys/__tests__/migrate.test.js +16 -5
- package/dist/commands/sys/config.js +2 -2
- package/dist/commands/sys/doctor.js +87 -5
- package/dist/commands/sys/migrate.js +38 -19
- package/dist/commands/sys/setup-core.js +1 -1
- package/dist/commands/sys/sync-project-guidance.js +1 -1
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +7 -4
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +1 -1
- package/dist/core/__tests__/fixtures/c5-command-boundary-ext.js +24 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +24 -18
- package/dist/core/__tests__/fixtures/fake-engine.js +8 -1
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +71 -0
- package/dist/core/__tests__/human-action-delivery.test.d.ts +1 -0
- package/dist/core/__tests__/human-action-delivery.test.js +140 -0
- package/dist/core/__tests__/human-actions.test.d.ts +1 -0
- package/dist/core/__tests__/human-actions.test.js +116 -0
- package/dist/core/__tests__/inline-memory-refs.test.js +36 -2
- package/dist/core/__tests__/profile-project-memory-delivery.test.d.ts +1 -0
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +217 -0
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +1 -0
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +91 -0
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +1 -0
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +127 -0
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +1 -0
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +31 -0
- package/dist/core/__tests__/serial/broker-sdk-wiring.test.js +102 -2
- package/dist/core/bootstrap.js +6 -0
- package/dist/core/canvas/browse/app.js +5 -2
- package/dist/core/canvas/browse/model.d.ts +25 -15
- package/dist/core/canvas/browse/model.js +86 -65
- package/dist/core/canvas/db.js +23 -0
- package/dist/core/canvas/human-deliveries.d.ts +53 -0
- package/dist/core/canvas/human-deliveries.js +75 -0
- package/dist/core/canvas/render-source.d.ts +6 -0
- package/dist/core/canvas/render-source.js +7 -1
- package/dist/core/canvas/render.js +10 -2
- package/dist/core/command-hooks/artifact.d.ts +10 -0
- package/dist/core/command-hooks/artifact.js +129 -0
- package/dist/core/command-hooks/catalog.d.ts +14 -0
- package/dist/core/command-hooks/catalog.js +38 -0
- package/dist/core/command-hooks/compose.d.ts +15 -0
- package/dist/core/command-hooks/compose.js +99 -0
- package/dist/core/command-hooks/discovery.d.ts +87 -0
- package/dist/core/command-hooks/discovery.js +174 -0
- package/dist/core/command-hooks/help.d.ts +5 -0
- package/dist/core/command-hooks/help.js +18 -0
- package/dist/core/command-hooks/index.d.ts +6 -0
- package/dist/core/command-hooks/index.js +6 -0
- package/dist/core/command-hooks/report.d.ts +23 -0
- package/dist/core/command-hooks/report.js +19 -0
- package/dist/core/command-hooks/schema.d.ts +27 -0
- package/dist/core/command-hooks/schema.js +68 -0
- package/dist/core/command-hooks/transport/exec-invoke.d.ts +22 -0
- package/dist/core/command-hooks/transport/exec-invoke.js +274 -0
- package/dist/core/command-plugins/presence.d.ts +2 -0
- package/dist/core/command-plugins/presence.js +17 -0
- package/dist/core/command-plugins/transport/exec-invoke.d.ts +5 -0
- package/dist/core/command-plugins/transport/exec-invoke.js +58 -5
- package/dist/core/command.d.ts +8 -1
- package/dist/core/command.js +12 -10
- package/dist/core/config.d.ts +13 -1
- package/dist/core/config.js +51 -1
- package/dist/core/feed/inbox.d.ts +6 -0
- package/dist/core/feed/inbox.js +9 -1
- package/dist/core/help.d.ts +7 -1
- package/dist/core/human/action-binding.d.ts +21 -0
- package/dist/core/human/action-binding.js +40 -0
- package/dist/core/human/completion.d.ts +38 -0
- package/dist/core/human/completion.js +27 -0
- package/dist/core/human/convention.d.ts +2 -0
- package/dist/core/human/convention.js +2 -0
- package/dist/core/human/tickets.d.ts +25 -6
- package/dist/core/human/tickets.js +19 -13
- package/dist/core/human/types.d.ts +5 -0
- package/dist/core/human-actions.d.ts +25 -0
- package/dist/core/human-actions.js +101 -0
- package/dist/core/io.d.ts +9 -1
- package/dist/core/io.js +44 -2
- package/dist/core/memory/inline-ref-inventory.d.ts +2 -1
- package/dist/core/memory/inline-ref-inventory.js +15 -8
- package/dist/core/memory-resolver.d.ts +13 -1
- package/dist/core/memory-resolver.js +26 -20
- package/dist/core/profiles/manifest.d.ts +13 -2
- package/dist/core/profiles/manifest.js +84 -18
- package/dist/core/profiles/select.d.ts +2 -0
- package/dist/core/profiles/select.js +29 -12
- package/dist/core/render.js +11 -0
- package/dist/core/runtime/advertised-command-invocation.d.ts +20 -0
- package/dist/core/runtime/advertised-command-invocation.js +233 -0
- package/dist/core/runtime/bearings.js +1 -1
- package/dist/core/runtime/broker/event-projection.js +7 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
- package/dist/core/runtime/broker/frame-dispatch.js +13 -11
- package/dist/core/runtime/broker/read-ops.d.ts +4 -0
- package/dist/core/runtime/broker/read-ops.js +6 -2
- package/dist/core/runtime/broker-extension-render.js +1 -1
- package/dist/core/runtime/broker-inventory.d.ts +4 -0
- package/dist/core/runtime/broker-inventory.js +116 -0
- package/dist/core/runtime/broker-persona-guidance.js +1 -1
- package/dist/core/runtime/broker-protocol.d.ts +9 -2
- package/dist/core/runtime/broker.js +10 -1
- package/dist/core/runtime/chat-inventory-rows.d.ts +8 -0
- package/dist/core/runtime/chat-inventory-rows.js +105 -0
- package/dist/core/runtime/command-surface.d.ts +38 -0
- package/dist/core/runtime/command-surface.js +117 -0
- package/dist/core/runtime/launch-target.d.ts +25 -0
- package/dist/core/runtime/launch-target.js +54 -0
- package/dist/core/runtime/node-read.js +5 -0
- package/dist/core/runtime/persona.js +3 -3
- package/dist/core/runtime/prospective-inventory-cli.d.ts +1 -0
- package/dist/core/runtime/prospective-inventory-cli.js +61 -0
- package/dist/core/runtime/prospective-inventory.d.ts +10 -0
- package/dist/core/runtime/prospective-inventory.js +88 -0
- package/dist/core/runtime/spawn.d.ts +3 -1
- package/dist/core/runtime/spawn.js +5 -3
- package/dist/core/scope.d.ts +26 -1
- package/dist/core/scope.js +52 -12
- package/dist/core/substrate/on-read.d.ts +7 -1
- package/dist/core/substrate/on-read.js +30 -32
- package/dist/core/substrate/render-node.d.ts +3 -2
- package/dist/core/substrate/render-node.js +3 -2
- package/dist/core/substrate/render.js +65 -24
- package/dist/core/substrate/schema.d.ts +16 -2
- package/dist/core/substrate/schema.js +14 -5
- package/dist/core/user-settings.d.ts +4 -0
- package/dist/core/user-settings.js +1 -0
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +56 -7
- package/dist/daemon/api/handlers/chat-inventory.d.ts +2 -0
- package/dist/daemon/api/handlers/chat-inventory.js +25 -0
- package/dist/daemon/api/handlers/human-requests.d.ts +2 -0
- package/dist/daemon/api/handlers/human-requests.js +409 -0
- package/dist/daemon/api/handlers/human.js +3 -0
- package/dist/daemon/api/handlers/inbox.js +3 -0
- package/dist/daemon/api/handlers/nodes.d.ts +1 -3
- package/dist/daemon/api/handlers/nodes.js +11 -46
- package/dist/daemon/api/handlers/profiles.js +7 -1
- package/dist/daemon/api/handlers/prospective-chat-inventory.d.ts +2 -0
- package/dist/daemon/api/handlers/prospective-chat-inventory.js +59 -0
- package/dist/daemon/api/handlers/reviews.js +10 -2
- package/dist/daemon/api/map.d.ts +2 -1
- package/dist/daemon/api/map.js +3 -2
- package/dist/daemon/api/server.js +6 -0
- package/dist/daemon/crtrd.js +6 -0
- package/dist/daemon/human/deliver-action.d.ts +16 -0
- package/dist/daemon/human/deliver-action.js +168 -0
- package/dist/daemon/human/finish.d.ts +8 -5
- package/dist/daemon/human/finish.js +45 -6
- package/dist/daemon/human/sweep.js +4 -1
- package/dist/daemon/reconcilers/human-delivery-lane.d.ts +10 -0
- package/dist/daemon/reconcilers/human-delivery-lane.js +41 -0
- package/dist/daemon/review/finish.d.ts +8 -3
- package/dist/daemon/review/finish.js +19 -1
- package/dist/hook-authoring.d.ts +75 -0
- package/dist/hook-authoring.js +358 -0
- package/dist/hook-process.d.ts +7 -0
- package/dist/hook-process.js +34 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/migrations/002-profile-project-memory.d.ts +2 -0
- package/dist/migrations/002-profile-project-memory.js +71 -0
- package/dist/migrations/profile-manifests.d.ts +30 -0
- package/dist/migrations/profile-manifests.js +70 -0
- package/dist/migrations/registry.js +10 -5
- package/dist/migrations/types.d.ts +28 -1
- package/dist/migrations/types.js +15 -9
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +21 -4
- package/dist/pi-extensions/canvas-structured-output.js +85 -2
- package/dist/types.d.ts +23 -6
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/builtin-memory/00-runtime-base.md +0 -55
- package/dist/builtin-memory/design.md +0 -55
- package/dist/clients/attach/__tests__/file-review-focus.test.js +0 -49
- /package/dist/builtin-memory/{02-lifecycle/00-terminal.md → 02-turn-lifecycle/01-terminal.md} +0 -0
- /package/dist/{clients/attach/__tests__/file-review-focus.test.d.ts → core/__tests__/fixtures/memory-slash-live-probe.d.ts} +0 -0
package/dist/core/scope.js
CHANGED
|
@@ -6,6 +6,9 @@ import { assetRoot } from './asset-root.js';
|
|
|
6
6
|
import { usage } from './errors.js';
|
|
7
7
|
import { loadProfileManifest } from './profiles/manifest.js';
|
|
8
8
|
import { realpathOrSelf } from './fs-utils.js';
|
|
9
|
+
/** The ceiling a project root carries when no profile relationship contributes
|
|
10
|
+
* it — the top rung, i.e. no cap at all. */
|
|
11
|
+
export const NEUTRAL_PROJECT_MEMORY = 'content';
|
|
9
12
|
// Cache of resolved project-scope-root STACKS, keyed by (resolved cwd, profile
|
|
10
13
|
// id). A profile widens the pointer set beyond the bare cwd (see
|
|
11
14
|
// findProjectScopeRoots below), so the cache key must carry both — the same
|
|
@@ -13,7 +16,8 @@ import { realpathOrSelf } from './fs-utils.js';
|
|
|
13
16
|
// `resetScopeCache()` (called by every profile mutation in
|
|
14
17
|
// src/core/profiles/manifest.ts) clears the whole cache; there is no
|
|
15
18
|
// per-entry invalidation because a profile edit can change which pointer set
|
|
16
|
-
// any cached cwd belongs to.
|
|
19
|
+
// any cached cwd belongs to. Path-only callers read `roots`, which is the same
|
|
20
|
+
// array in the same order as `annotated`.
|
|
17
21
|
const scopeRootsCache = new Map();
|
|
18
22
|
function scopeRootsCacheKey(resolvedStartDir, profileId) {
|
|
19
23
|
return `${resolvedStartDir}\u0000${profileId ?? ''}`;
|
|
@@ -94,19 +98,40 @@ function collectAncestorScopeRoots(startDir, userRoot) {
|
|
|
94
98
|
* selected profile (`CRTR_PROFILE_ID`); a null/unresolvable profile collapses
|
|
95
99
|
* to the single `[startDir]` pointer, reproducing today's behavior exactly.
|
|
96
100
|
* Results are cached per (resolved startDir, profileId) — `resetScopeCache()`
|
|
97
|
-
* invalidates on any profile mutation that can change project dirs or names.
|
|
101
|
+
* invalidates on any profile mutation that can change project dirs or names.
|
|
102
|
+
*
|
|
103
|
+
* Each root also carries the selected profile relationship's memory ceiling
|
|
104
|
+
* (`findProjectScopeRootsWithMemory`), a projection layered onto this order
|
|
105
|
+
* rather than part of it: discovery provenance decides precedence, the
|
|
106
|
+
* relationship decides the ceiling, and the two never influence each other. */
|
|
98
107
|
export function findProjectScopeRoots(startDir = process.cwd(), profileId = process.env['CRTR_PROFILE_ID'] || null) {
|
|
108
|
+
return resolveProjectScopeRoots(startDir, profileId).roots;
|
|
109
|
+
}
|
|
110
|
+
/** `findProjectScopeRoots` with each root's profile memory ceiling attached —
|
|
111
|
+
* same roots, same order. A root contributed by a profile entry's ancestor
|
|
112
|
+
* walk takes that entry's `memory` (first entry in manifest order wins, even
|
|
113
|
+
* when cwd also reaches the root); every other root takes the neutral
|
|
114
|
+
* `content` ceiling. */
|
|
115
|
+
export function findProjectScopeRootsWithMemory(startDir = process.cwd(), profileId = process.env['CRTR_PROFILE_ID'] || null) {
|
|
116
|
+
return resolveProjectScopeRoots(startDir, profileId).annotated;
|
|
117
|
+
}
|
|
118
|
+
function resolveProjectScopeRoots(startDir, profileId) {
|
|
99
119
|
const resolvedStart = resolve(startDir);
|
|
100
120
|
const key = scopeRootsCacheKey(resolvedStart, profileId);
|
|
101
121
|
const cached = scopeRootsCache.get(key);
|
|
102
122
|
if (cached !== undefined)
|
|
103
123
|
return cached;
|
|
104
124
|
const userRoot = userScopeRoot();
|
|
105
|
-
|
|
125
|
+
// A null `memory` marks the cwd pointer: it decides precedence like any
|
|
126
|
+
// other pointer but contributes no ceiling.
|
|
127
|
+
const pointers = [
|
|
128
|
+
{ dir: resolvedStart, memory: null },
|
|
129
|
+
];
|
|
106
130
|
if (profileId !== null && profileId !== '') {
|
|
107
131
|
try {
|
|
108
132
|
const { manifest } = loadProfileManifest(profileId);
|
|
109
|
-
|
|
133
|
+
for (const project of manifest.projects)
|
|
134
|
+
pointers.push({ dir: project.path, memory: project.memory });
|
|
110
135
|
}
|
|
111
136
|
catch {
|
|
112
137
|
// Missing/deleted/invalid profile: this is a hot path every memory and
|
|
@@ -116,16 +141,23 @@ export function findProjectScopeRoots(startDir = process.cwd(), profileId = proc
|
|
|
116
141
|
}
|
|
117
142
|
const seen = new Set();
|
|
118
143
|
const roots = [];
|
|
144
|
+
const caps = new Map();
|
|
119
145
|
for (const pointer of pointers) {
|
|
120
|
-
for (const root of collectAncestorScopeRoots(pointer, userRoot)) {
|
|
121
|
-
if (seen.has(root))
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
for (const root of collectAncestorScopeRoots(pointer.dir, userRoot)) {
|
|
147
|
+
if (!seen.has(root)) {
|
|
148
|
+
seen.add(root);
|
|
149
|
+
roots.push(root);
|
|
150
|
+
}
|
|
151
|
+
// Independent of the order dedupe above: a root already discovered from
|
|
152
|
+
// cwd still takes the first profile entry's ceiling.
|
|
153
|
+
if (pointer.memory !== null && !caps.has(root))
|
|
154
|
+
caps.set(root, pointer.memory);
|
|
125
155
|
}
|
|
126
156
|
}
|
|
127
|
-
|
|
128
|
-
|
|
157
|
+
const annotated = roots.map((root) => ({ root, memory: caps.get(root) ?? NEUTRAL_PROJECT_MEMORY }));
|
|
158
|
+
const entry = { roots, annotated };
|
|
159
|
+
scopeRootsCache.set(key, entry);
|
|
160
|
+
return entry;
|
|
129
161
|
}
|
|
130
162
|
export function projectScopeRoot(startDir) {
|
|
131
163
|
return findProjectScopeRoot(startDir);
|
|
@@ -133,6 +165,9 @@ export function projectScopeRoot(startDir) {
|
|
|
133
165
|
export function projectScopeRoots(startDir, profileId) {
|
|
134
166
|
return findProjectScopeRoots(startDir, profileId);
|
|
135
167
|
}
|
|
168
|
+
export function projectScopeRootsWithMemory(startDir, profileId) {
|
|
169
|
+
return findProjectScopeRootsWithMemory(startDir, profileId);
|
|
170
|
+
}
|
|
136
171
|
export function scopeRoot(scope) {
|
|
137
172
|
// The builtin scope has no scope-root dir; its content lives in dedicated
|
|
138
173
|
// package directories such as builtinMemoryRoot().
|
|
@@ -160,7 +195,12 @@ export function ensureProjectScopeRoot(startDir = process.cwd()) {
|
|
|
160
195
|
const resolvedStart = resolve(startDir);
|
|
161
196
|
const root = join(resolvedStart, CRTR_DIR_NAME);
|
|
162
197
|
const profileId = process.env['CRTR_PROFILE_ID'] || null;
|
|
163
|
-
|
|
198
|
+
// Neutral ceiling: the empty cached stack proves no profile entry's ancestor
|
|
199
|
+
// walk reached this root, since it did not exist to be walked into.
|
|
200
|
+
scopeRootsCache.set(scopeRootsCacheKey(resolvedStart, profileId), {
|
|
201
|
+
roots: [root],
|
|
202
|
+
annotated: [{ root, memory: NEUTRAL_PROJECT_MEMORY }],
|
|
203
|
+
});
|
|
164
204
|
return root;
|
|
165
205
|
}
|
|
166
206
|
export function pluginsDir(scope) {
|
|
@@ -15,7 +15,13 @@ export declare function renderOnReadDocsForSubject(subject: NodeConfigSubject, r
|
|
|
15
15
|
/** Workspace boot docs using the snapshot's cwd/profile instead of a canvas
|
|
16
16
|
* lookup. `seen` is the transcript-scoped dedup set shared with the on-read
|
|
17
17
|
* hook, so a front door delivered here never re-delivers on a later read
|
|
18
|
-
* beneath its store.
|
|
18
|
+
* beneath its store.
|
|
19
|
+
*
|
|
20
|
+
* Each candidate's authored rung is clamped to its project's profile
|
|
21
|
+
* relationship cap BEFORE the `none` filter, the ordering, the render, and the
|
|
22
|
+
* seen-map recording — so a capped doc never renders above its cap, a `none`
|
|
23
|
+
* project contributes nothing, and a later explicit `crtr memory read` can
|
|
24
|
+
* still upgrade what workspace-open disclosed at a lower rung. */
|
|
19
25
|
export declare function renderWorkspaceOpenDocsForSubject(subject: NodeConfigSubject, cwd: string, profileId: string | null, seen?: InjectedDocs): string;
|
|
20
26
|
/** Inner `<memory>` blocks for the memory-read event: docs whose
|
|
21
27
|
* `memory-read` entries match the doc a `crtr memory read` just resolved
|
|
@@ -33,11 +33,11 @@ import { CRTR_DIR_NAME } from '../../types.js';
|
|
|
33
33
|
import { pathExists, readText, walkFiles } from '../fs-utils.js';
|
|
34
34
|
import { parseFrontmatterGeneric } from '../frontmatter.js';
|
|
35
35
|
import { listAllMemoryDocs, listProjectMemoryDocs } from '../memory-resolver.js';
|
|
36
|
-
import { userScopeRoot } from '../scope.js';
|
|
36
|
+
import { NEUTRAL_PROJECT_MEMORY, userScopeRoot } from '../scope.js';
|
|
37
37
|
import { gatePasses } from './gate.js';
|
|
38
38
|
import { commandDeliveryRung, memoryReadDeliveryRung, owningRootOf, readDeliveryRung, workspaceOpenRung } from './surface-match.js';
|
|
39
39
|
import { deliveredAtOrAbove, recordDelivery } from './injected-store.js';
|
|
40
|
-
import { normalizeDocName, parseSubstrateDoc, parseSubstrateFrontmatter, previewLine, resolveDocName } from './schema.js';
|
|
40
|
+
import { minRung, normalizeDocName, parseSubstrateDoc, parseSubstrateFrontmatter, previewLine, resolveDocName } from './schema.js';
|
|
41
41
|
import { cachedSubstrateDocsInclusive } from './session-cache.js';
|
|
42
42
|
import { realpathOrSelf } from '../fs-utils.js';
|
|
43
43
|
const JUNK_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache', '.yalc']);
|
|
@@ -48,27 +48,6 @@ function attr(s) {
|
|
|
48
48
|
.replace(/</g, '<')
|
|
49
49
|
.replace(/>/g, '>');
|
|
50
50
|
}
|
|
51
|
-
function gitRootOf(p) {
|
|
52
|
-
let d = p;
|
|
53
|
-
const root = parse(d).root;
|
|
54
|
-
while (true) {
|
|
55
|
-
if (pathExists(`${d}${sep}.git`))
|
|
56
|
-
return d;
|
|
57
|
-
if (d === root)
|
|
58
|
-
return null;
|
|
59
|
-
const parent = dirname(d);
|
|
60
|
-
if (parent === d)
|
|
61
|
-
return null;
|
|
62
|
-
d = parent;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function disp(p) {
|
|
66
|
-
const root = gitRootOf(p);
|
|
67
|
-
if (!root)
|
|
68
|
-
return p;
|
|
69
|
-
const rel = relative(root, p);
|
|
70
|
-
return rel === '' ? '.' : rel;
|
|
71
|
-
}
|
|
72
51
|
function isJunkAncestor(dir) {
|
|
73
52
|
return dir.split(sep).some((segment) => JUNK_DIRS.has(segment));
|
|
74
53
|
}
|
|
@@ -91,6 +70,9 @@ function loadProjectDoc(file, memoryDir) {
|
|
|
91
70
|
scope: 'project',
|
|
92
71
|
path: file,
|
|
93
72
|
body,
|
|
73
|
+
// The read event is uncapped by design: this walk is reached only by an
|
|
74
|
+
// explicit file read, never by automatic boot/workspace-open delivery.
|
|
75
|
+
projectMemory: NEUTRAL_PROJECT_MEMORY,
|
|
94
76
|
};
|
|
95
77
|
}
|
|
96
78
|
catch {
|
|
@@ -181,16 +163,26 @@ function docContentKey(doc) {
|
|
|
181
163
|
return null;
|
|
182
164
|
return `content-sha256:${createHash('sha256').update(body).digest('hex')}`;
|
|
183
165
|
}
|
|
166
|
+
// Two shapes: element-with-body means the content is here; self-closing means
|
|
167
|
+
// it is not — a preview carries its routing line as `readWhen` metadata so the
|
|
168
|
+
// one-liner can never be mistaken for the document's content. No disk path:
|
|
169
|
+
// agents address memory by name through the command surface, and the explicit
|
|
170
|
+
// read leaf already returns `path`.
|
|
184
171
|
function renderDocEnvelope(doc, rung) {
|
|
185
172
|
if (rung === 'none')
|
|
186
173
|
return null;
|
|
187
|
-
let
|
|
188
|
-
if (rung === 'content')
|
|
189
|
-
body = doc.body.trim();
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
174
|
+
let attrs = `kind="${attr(doc.kind)}" name="${attr(doc.name)}"`;
|
|
175
|
+
if (rung === 'content') {
|
|
176
|
+
const body = doc.body.trim();
|
|
177
|
+
if (body !== '')
|
|
178
|
+
return `<memory ${attrs}>\n${body}\n</memory>`;
|
|
179
|
+
}
|
|
180
|
+
else if (rung === 'preview') {
|
|
181
|
+
const pl = previewLine(doc);
|
|
182
|
+
if (pl !== '')
|
|
183
|
+
attrs += ` readWhen="${attr(pl)}"`;
|
|
184
|
+
}
|
|
185
|
+
return `<memory ${attrs} />`;
|
|
194
186
|
}
|
|
195
187
|
/** Render candidates at their matched rungs, gate-checked and deduped against
|
|
196
188
|
* the transcript set (higher rungs pierce lower; a delivery records at its
|
|
@@ -244,7 +236,13 @@ export function renderOnReadDocsForSubject(subject, readFilePath, seen = new Map
|
|
|
244
236
|
/** Workspace boot docs using the snapshot's cwd/profile instead of a canvas
|
|
245
237
|
* lookup. `seen` is the transcript-scoped dedup set shared with the on-read
|
|
246
238
|
* hook, so a front door delivered here never re-delivers on a later read
|
|
247
|
-
* beneath its store.
|
|
239
|
+
* beneath its store.
|
|
240
|
+
*
|
|
241
|
+
* Each candidate's authored rung is clamped to its project's profile
|
|
242
|
+
* relationship cap BEFORE the `none` filter, the ordering, the render, and the
|
|
243
|
+
* seen-map recording — so a capped doc never renders above its cap, a `none`
|
|
244
|
+
* project contributes nothing, and a later explicit `crtr memory read` can
|
|
245
|
+
* still upgrade what workspace-open disclosed at a lower rung. */
|
|
248
246
|
export function renderWorkspaceOpenDocsForSubject(subject, cwd, profileId, seen = new Map()) {
|
|
249
247
|
let docs;
|
|
250
248
|
try {
|
|
@@ -256,7 +254,7 @@ export function renderWorkspaceOpenDocsForSubject(subject, cwd, profileId, seen
|
|
|
256
254
|
return '';
|
|
257
255
|
}
|
|
258
256
|
const candidates = dedupeByPhysicalPath(docs)
|
|
259
|
-
.map((doc) => ({ doc, rung: workspaceOpenRung(doc) }))
|
|
257
|
+
.map((doc) => ({ doc, rung: minRung(workspaceOpenRung(doc), doc.projectMemory) }))
|
|
260
258
|
.filter(({ rung }) => rung !== 'none')
|
|
261
259
|
.sort((a, b) => {
|
|
262
260
|
const aRoot = owningRootOf(a.doc) ?? '';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InjectedDocs } from './injected-store.js';
|
|
2
|
-
/** The system-prompt
|
|
3
|
-
*
|
|
2
|
+
/** The system-prompt substrate splice for `nodeId` — shipped-layer protocol
|
|
3
|
+
* prose followed by the `<memory kind="preference">` block: assemble
|
|
4
|
+
* the node's subject from the canvas-db, render the pure splice, then swap the
|
|
4
5
|
* literal `$CRTR_CONTEXT_DIR` env-var token for the node's real absolute path
|
|
5
6
|
* so agents don't paste it into the non-expanding Write tool (see
|
|
6
7
|
* interpolateNodePaths). A null subject (unknown id) still renders the
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import { interpolateNodePaths } from '../canvas/paths.js';
|
|
9
9
|
import { assembleNodeSubject } from './subject.js';
|
|
10
10
|
import { renderPreferencesForSubject, renderKnowledgeForSubject } from './render.js';
|
|
11
|
-
/** The system-prompt
|
|
12
|
-
*
|
|
11
|
+
/** The system-prompt substrate splice for `nodeId` — shipped-layer protocol
|
|
12
|
+
* prose followed by the `<memory kind="preference">` block: assemble
|
|
13
|
+
* the node's subject from the canvas-db, render the pure splice, then swap the
|
|
13
14
|
* literal `$CRTR_CONTEXT_DIR` env-var token for the node's real absolute path
|
|
14
15
|
* so agents don't paste it into the non-expanding Write tool (see
|
|
15
16
|
* interpolateNodePaths). A null subject (unknown id) still renders the
|
|
@@ -57,14 +57,14 @@ import { subKindsAvailableTo } from '../config.js';
|
|
|
57
57
|
import { parseFrontmatterGeneric } from '../frontmatter.js';
|
|
58
58
|
import { pathExists, readText, realpathOrSelf, walkFiles } from '../fs-utils.js';
|
|
59
59
|
import { memoryDir } from '../runtime/memory.js';
|
|
60
|
-
import { projectScopeRoots } from '../scope.js';
|
|
60
|
+
import { NEUTRAL_PROJECT_MEMORY, projectScopeRoots } from '../scope.js';
|
|
61
61
|
import { gatePasses } from './gate.js';
|
|
62
62
|
// De-barreled to LEAF modules on purpose: importing from './index.js' would
|
|
63
63
|
// pull subject.js (canvas-db) transitively, re-tainting every CLI consumer of
|
|
64
64
|
// the pure render fns. The canvas-db wrappers (renderPreferencesSection /
|
|
65
65
|
// renderKnowledgeBlock) live in render-node.js instead.
|
|
66
66
|
import { recordDelivery } from './injected-store.js';
|
|
67
|
-
import { bootRung, normalizeDocName, parseSubstrateDoc, parseSubstrateFrontmatter, previewLine, resolveDocName, rungRank, } from './schema.js';
|
|
67
|
+
import { bootRung, minRung, normalizeDocName, parseSubstrateDoc, parseSubstrateFrontmatter, previewLine, resolveDocName, rungRank, } from './schema.js';
|
|
68
68
|
import { cachedSubstrateDocs } from './session-cache.js';
|
|
69
69
|
/** First-wins dedup by (already-normalized) name, preserving the input's
|
|
70
70
|
* precedence order. The array's ORDER is the precedence signal — callers must
|
|
@@ -89,7 +89,13 @@ function dedupeFirstWins(docs) {
|
|
|
89
89
|
* selection ONLY; display ordering is a separate, later step (see
|
|
90
90
|
* renderGrouped) so a builtin doc can never mask a project/user override by
|
|
91
91
|
* virtue of sorting first. Uses the per-session cache so the full corpus is
|
|
92
|
-
* scanned + parsed at most once per session across the boot-render calls.
|
|
92
|
+
* scanned + parsed at most once per session across the boot-render calls.
|
|
93
|
+
*
|
|
94
|
+
* The profile relationship's cap applies HERE, before dedup: a `none` project
|
|
95
|
+
* leaves the corpus entirely (it contributes nothing, not even a `[+N more]`
|
|
96
|
+
* count, and so cannot shadow a wider-scope automatic winner), and every
|
|
97
|
+
* surviving doc's authored boot rung is clamped to its cap before dedup, the
|
|
98
|
+
* session cache, and delivery seeding see it. */
|
|
93
99
|
function selectWinners(subject, kind) {
|
|
94
100
|
let docs;
|
|
95
101
|
try {
|
|
@@ -100,8 +106,9 @@ function selectWinners(subject, kind) {
|
|
|
100
106
|
}
|
|
101
107
|
const eligible = docs
|
|
102
108
|
.filter((d) => d.kind === kind)
|
|
109
|
+
.filter((d) => d.projectMemory !== 'none')
|
|
103
110
|
.filter((d) => gatePasses(d, subject))
|
|
104
|
-
.map((d) => ({ ...d, bootRung: bootRung(d) }));
|
|
111
|
+
.map((d) => ({ ...d, bootRung: minRung(bootRung(d), d.projectMemory) }));
|
|
105
112
|
return dedupeFirstWins(eligible);
|
|
106
113
|
}
|
|
107
114
|
// ---------------------------------------------------------------------------
|
|
@@ -176,9 +183,16 @@ function compareTreePosition(a, b) {
|
|
|
176
183
|
}
|
|
177
184
|
return as.length - bs.length;
|
|
178
185
|
}
|
|
186
|
+
/** A doc the running agent can revise through `crtr memory edit`: any native
|
|
187
|
+
* scope-store doc (user/profile/project/node). Shipped docs — builtin and
|
|
188
|
+
* plugin-mounted — are not editable from a node; the preference render treats
|
|
189
|
+
* them as operating protocol, not memory (see buildPreferencesBlock). */
|
|
190
|
+
function isAgentEditable(doc) {
|
|
191
|
+
return doc.scope !== 'builtin' && doc.plugin === undefined;
|
|
192
|
+
}
|
|
179
193
|
/** STEP 2 — split deduped `winners` by rung and render each group in its
|
|
180
194
|
* display order: `content` docs first, as clean prose (general→specific,
|
|
181
|
-
* then tree position, then filename — no tree chrome
|
|
195
|
+
* then tree position, then filename — no tree chrome); every
|
|
182
196
|
* other winner (preview/name/hidden-bootless) folds into ONE catalog tree
|
|
183
197
|
* exactly as before. `nodeLocalSet` marks which winners came from the
|
|
184
198
|
* node-local store (ranked most-specific in content ordering); omit it for a
|
|
@@ -238,7 +252,9 @@ function nodeLocalDocs(nodeId, subject) {
|
|
|
238
252
|
// node-local is NOT a resolver scope; `scope` is a placeholder never read
|
|
239
253
|
// by gate eval (keyed off the NODE subject, not the doc) nor by the
|
|
240
254
|
// renderers (keyed off name / body / rung).
|
|
241
|
-
|
|
255
|
+
// Node-local is not a project store: no profile relationship names it,
|
|
256
|
+
// so it carries the neutral ceiling.
|
|
257
|
+
out.push({ ...schema, name, scope: 'user', path: file, body, projectMemory: NEUTRAL_PROJECT_MEMORY });
|
|
242
258
|
}
|
|
243
259
|
catch {
|
|
244
260
|
// A single malformed file is skipped, never fatal to the render.
|
|
@@ -480,37 +496,62 @@ function buildSubPersonaMenu(kind) {
|
|
|
480
496
|
lines.join('\n'));
|
|
481
497
|
}
|
|
482
498
|
// ---------------------------------------------------------------------------
|
|
483
|
-
// 1. Preferences — `<memory kind="preference">` (system prompt).
|
|
499
|
+
// 1. Preferences — protocol prose + `<memory kind="preference">` (system prompt).
|
|
484
500
|
// ---------------------------------------------------------------------------
|
|
485
|
-
/** The system-prompt
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
501
|
+
/** The system-prompt substrate splice, TWO parts in one string.
|
|
502
|
+
*
|
|
503
|
+
* 1. The operating protocol: shipped (builtin/plugin) content-rung bodies as
|
|
504
|
+
* bare prose, plus the sub-persona menu. No memory envelope — the protocol
|
|
505
|
+
* is the rules of the node's world, and wrapping it as recalled "memory:
|
|
506
|
+
* preference" content gave it softer epistemic status than the
|
|
507
|
+
* instructions it is; the intro/outro sentences ("how the user wants you
|
|
508
|
+
* to behave", "update the preference") were also false of it.
|
|
509
|
+
* 2. The `<memory kind="preference">` block: the always-present memory-usage
|
|
510
|
+
* guidance, then (when any are eligible) each agent-editable doc wrapped
|
|
511
|
+
* `<preference name="…">…</preference>` — the name is the edit handle the
|
|
512
|
+
* outro's update directive needs — then the preview/name catalog tree.
|
|
513
|
+
* Every frame sentence is true of everything inside it.
|
|
514
|
+
*
|
|
515
|
+
* Ordering across the two parts is unchanged from the single-block render
|
|
516
|
+
* (shipped→editable was already the scope sort), so the shared cache prefix
|
|
517
|
+
* across nodes is preserved. ALWAYS returns a non-empty splice — the guidance
|
|
518
|
+
* frame is unconditional, so it is never empty even when no preference is
|
|
519
|
+
* eligible. */
|
|
491
520
|
function buildPreferencesBlock(subject, seen) {
|
|
492
|
-
let body = MEMORY_USAGE_GUIDANCE;
|
|
493
521
|
let contentDocs = [];
|
|
494
522
|
let tree = '';
|
|
523
|
+
let protocol = '';
|
|
524
|
+
let memBody = MEMORY_USAGE_GUIDANCE;
|
|
495
525
|
if (subject !== null) {
|
|
496
526
|
const winners = selectWinners(subject, 'preference');
|
|
497
527
|
seedBootDelivery(seen, winners);
|
|
498
528
|
const grouped = renderGrouped(winners, 'preferences');
|
|
499
529
|
contentDocs = grouped.contentDocs;
|
|
500
530
|
tree = grouped.tree;
|
|
531
|
+
const shipped = contentDocs
|
|
532
|
+
.filter((d) => !isAgentEditable(d))
|
|
533
|
+
.map((d) => d.body.trim())
|
|
534
|
+
.filter((b) => b !== '');
|
|
535
|
+
const editable = contentDocs
|
|
536
|
+
.filter((d) => isAgentEditable(d))
|
|
537
|
+
.map((d) => {
|
|
538
|
+
const b = d.body.trim();
|
|
539
|
+
return b === '' ? '' : `<preference name="${d.name}">\n${b}\n</preference>`;
|
|
540
|
+
})
|
|
541
|
+
.filter((b) => b !== '');
|
|
501
542
|
const subPersonaMenu = buildSubPersonaMenu(subject.kind);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
body += `\n\n${PREFERENCES_OUTRO}`;
|
|
543
|
+
protocol = [...shipped, ...(subPersonaMenu === '' ? [] : [subPersonaMenu])].join('\n\n');
|
|
544
|
+
if (editable.length > 0 || tree !== '') {
|
|
545
|
+
memBody += `\n\n${PREFERENCES_INTRO}`;
|
|
546
|
+
if (editable.length > 0)
|
|
547
|
+
memBody += `\n\n${editable.join('\n\n')}`;
|
|
548
|
+
if (tree !== '')
|
|
549
|
+
memBody += `\n\n${tree}`;
|
|
550
|
+
memBody += `\n\n${PREFERENCES_OUTRO}`;
|
|
511
551
|
}
|
|
512
552
|
}
|
|
513
|
-
|
|
553
|
+
const memoryBlock = `<memory kind="preference">\n${memBody}\n</memory>`;
|
|
554
|
+
return { block: protocol === '' ? memoryBlock : `${protocol}\n\n${memoryBlock}`, contentDocs, tree };
|
|
514
555
|
}
|
|
515
556
|
export function renderPreferencesForSubject(subject, seen) {
|
|
516
557
|
return buildPreferencesBlock(subject, seen);
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
import { type ProfileProjectMemory } from '../../api/dto/profiles.js';
|
|
1
2
|
import type { MemoryDoc, MemoryScope } from '../memory-resolver.js';
|
|
2
3
|
export declare const KINDS: readonly ["knowledge", "preference"];
|
|
3
4
|
export type DocKind = (typeof KINDS)[number];
|
|
4
5
|
/** Is `v` one of the two valid document kinds? */
|
|
5
6
|
export declare function isDocKind(v: unknown): v is DocKind;
|
|
6
7
|
export declare const RUNGS: readonly ["none", "name", "preview", "content"];
|
|
7
|
-
export type Rung =
|
|
8
|
+
export type Rung = ProfileProjectMemory;
|
|
8
9
|
/** Ordinal of a rung on the ladder (none=0 … content=3). */
|
|
9
10
|
export declare function rungRank(r: Rung): number;
|
|
10
11
|
/** Does rung `r` disclose at least as much as `min`? */
|
|
11
12
|
export declare function rungAtLeast(r: Rung, min: Rung): boolean;
|
|
13
|
+
/** The lower of two rungs — the clamp automatic delivery applies to an
|
|
14
|
+
* authored rung against its project relationship's cap. */
|
|
15
|
+
export declare function minRung(a: Rung, b: Rung): Rung;
|
|
12
16
|
/** Strip an optional `NN-` ordering prefix from ONE path segment (file or
|
|
13
|
-
* directory display name). `00-runtime-base` -> `runtime-base`; `spine` (no
|
|
17
|
+
* directory display name). `00-runtime-base/00-authoring` -> `runtime-base/authoring`; `spine` (no
|
|
14
18
|
* prefix) is unchanged. */
|
|
15
19
|
export declare function normalizeNameSegment(segment: string): string;
|
|
16
20
|
/** Normalize a full slash-separated path-derived doc name by stripping the
|
|
@@ -107,10 +111,20 @@ export interface SubstrateDoc extends SubstrateSchema {
|
|
|
107
111
|
name: string;
|
|
108
112
|
/** The scope this doc resolved from. */
|
|
109
113
|
scope: MemoryScope;
|
|
114
|
+
/** Owning plugin name when the doc is mounted from an installed plugin;
|
|
115
|
+
* undefined for a native scope doc. Shipped (builtin/plugin) docs and
|
|
116
|
+
* agent-editable scope docs render differently at boot (see renderGrouped). */
|
|
117
|
+
plugin?: string;
|
|
110
118
|
/** Absolute path to the source .md. */
|
|
111
119
|
path: string;
|
|
112
120
|
/** Document body, frontmatter stripped. */
|
|
113
121
|
body: string;
|
|
122
|
+
/** The selected profile relationship's cap on the project store this doc
|
|
123
|
+
* resolved from — the maximum rung automatic boot and workspace-open
|
|
124
|
+
* delivery may disclose it at. `content` is the neutral ceiling every
|
|
125
|
+
* non-project doc and every uncapped project root carries. Targeted reads,
|
|
126
|
+
* command routing, and directory listings ignore it. */
|
|
127
|
+
projectMemory: ProfileProjectMemory;
|
|
114
128
|
}
|
|
115
129
|
/** Parse a raw frontmatter record (from `parseFrontmatterGeneric`, via the
|
|
116
130
|
* resolver) into a typed schema with defaults applied. Returns `null` when the
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// The runtime parser is tolerant by contract (it maps over many docs and must
|
|
8
8
|
// never throw): invalid `surfaces` entries are dropped rather than crashing a
|
|
9
9
|
// render, and `crtr memory lint` owns strict authoring-time enforcement.
|
|
10
|
+
import { PROFILE_PROJECT_MEMORY_VALUES } from '../../api/dto/profiles.js';
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
11
12
|
// Kinds — the two semantic kinds (design §3): `knowledge` (consult — procedural
|
|
12
13
|
// playbooks + factual references merged) vs `preference` (behave — standing
|
|
@@ -22,7 +23,10 @@ export function isDocKind(v) {
|
|
|
22
23
|
// each rung is a superset of disclosure over the one before:
|
|
23
24
|
// none < name < preview < content
|
|
24
25
|
// ---------------------------------------------------------------------------
|
|
25
|
-
|
|
26
|
+
// The ladder is ONE union, owned by the public API DTO (`ProfileProjectMemory`)
|
|
27
|
+
// so a profile relationship's cap and a doc's authored rung are the same values
|
|
28
|
+
// and clamp against each other without a conversion.
|
|
29
|
+
export const RUNGS = PROFILE_PROJECT_MEMORY_VALUES;
|
|
26
30
|
/** Ordinal of a rung on the ladder (none=0 … content=3). */
|
|
27
31
|
export function rungRank(r) {
|
|
28
32
|
return RUNGS.indexOf(r);
|
|
@@ -31,21 +35,26 @@ export function rungRank(r) {
|
|
|
31
35
|
export function rungAtLeast(r, min) {
|
|
32
36
|
return rungRank(r) >= rungRank(min);
|
|
33
37
|
}
|
|
38
|
+
/** The lower of two rungs — the clamp automatic delivery applies to an
|
|
39
|
+
* authored rung against its project relationship's cap. */
|
|
40
|
+
export function minRung(a, b) {
|
|
41
|
+
return rungRank(a) <= rungRank(b) ? a : b;
|
|
42
|
+
}
|
|
34
43
|
// ---------------------------------------------------------------------------
|
|
35
44
|
// Display-name normalization — the optional `NN-` ordering pin. A doc's
|
|
36
45
|
// physical path may carry a two-digit numeric prefix on a file or directory
|
|
37
|
-
// segment (`00-runtime-base
|
|
46
|
+
// segment (`00-runtime-base/`, `01-spine/`) purely to pin structural order
|
|
38
47
|
// against natural sort (design: builtin prompt corpus, used sparingly). The
|
|
39
48
|
// prefix is NEVER part of the doc's identity: every identity-facing surface —
|
|
40
49
|
// MemoryDoc.name, direct lookup, leaf fallback, `crtr memory read`/`list`,
|
|
41
50
|
// prompt render, on-read display — derives from the NORMALIZED segments, so
|
|
42
|
-
// `00-runtime-base` displays/dedups/resolves as `runtime-base`. When a doc
|
|
51
|
+
// `00-runtime-base/00-authoring` displays/dedups/resolves as `runtime-base/authoring`. When a doc
|
|
43
52
|
// sets an explicit frontmatter `name`, that normalized name wins instead of
|
|
44
53
|
// the path-derived fallback. Only the physical path keeps the prefix.
|
|
45
54
|
// ---------------------------------------------------------------------------
|
|
46
55
|
const NUMERIC_PREFIX_RE = /^\d{2}-/;
|
|
47
56
|
/** Strip an optional `NN-` ordering prefix from ONE path segment (file or
|
|
48
|
-
* directory display name). `00-runtime-base` -> `runtime-base`; `spine` (no
|
|
57
|
+
* directory display name). `00-runtime-base/00-authoring` -> `runtime-base/authoring`; `spine` (no
|
|
49
58
|
* prefix) is unchanged. */
|
|
50
59
|
export function normalizeNameSegment(segment) {
|
|
51
60
|
return segment.replace(NUMERIC_PREFIX_RE, '');
|
|
@@ -133,7 +142,7 @@ export function parseSubstrateDoc(doc) {
|
|
|
133
142
|
const schema = parseSubstrateFrontmatter(doc.frontmatter);
|
|
134
143
|
if (schema === null)
|
|
135
144
|
return null;
|
|
136
|
-
return { ...schema, name: doc.name, scope: doc.scope, path: doc.path, body: doc.body };
|
|
145
|
+
return { ...schema, name: doc.name, scope: doc.scope, plugin: doc.plugin, path: doc.path, body: doc.body, projectMemory: doc.projectMemory };
|
|
137
146
|
}
|
|
138
147
|
/** The kind a doc resolves to for `--kind` filtering/matching: the substrate
|
|
139
148
|
* kind when the frontmatter parses as a valid substrate doc, else the raw
|
|
@@ -326,6 +326,10 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
|
|
|
326
326
|
surface: "specialized";
|
|
327
327
|
owner: string;
|
|
328
328
|
};
|
|
329
|
+
humanActions: {
|
|
330
|
+
surface: "specialized";
|
|
331
|
+
owner: string;
|
|
332
|
+
};
|
|
329
333
|
};
|
|
330
334
|
/** The exhaustive top-level key list used by config persistence and help. */
|
|
331
335
|
export declare const SCOPE_CONFIG_KEYS: (keyof ScopeConfig)[];
|
|
@@ -389,6 +389,7 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
389
389
|
remoteCanvas: { surface: 'specialized', owner: 'canvas config commands' },
|
|
390
390
|
spawnEnv: { surface: 'specialized', owner: 'spawn environment allow-list' },
|
|
391
391
|
bin: { surface: 'specialized', owner: 'bare-binary contributions on every node PATH' },
|
|
392
|
+
humanActions: { surface: 'specialized', owner: 'scope-configured human completion actions' },
|
|
392
393
|
};
|
|
393
394
|
/** The exhaustive top-level key list used by config persistence and help. */
|
|
394
395
|
export const SCOPE_CONFIG_KEYS = Object.keys(CONFIG_SETTINGS_COVERAGE);
|