@north-light/crouter 0.3.236 → 0.3.238
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 +2 -1
- package/dist/api/client.js +3 -0
- package/dist/api/dto/broker-ops.d.ts +1 -1
- package/dist/api/dto/common.d.ts +2 -0
- package/dist/api/dto/lifecycle.d.ts +9 -2
- package/dist/api/dto/messages.d.ts +5 -0
- package/dist/api/dto/nodes.d.ts +10 -2
- package/dist/api/dto/worktree.d.ts +10 -0
- package/dist/api/routes.d.ts +1 -0
- package/dist/api/routes.js +1 -0
- package/dist/builtin-memory/00-runtime-base/00-authoring.md +1 -1
- package/dist/builtin-memory/internal/agent-shaping.md +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +1 -1
- package/dist/clients/attach/render/tool-calls.js +18 -3
- package/dist/clients/attach/viewer.js +442 -442
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +6 -0
- package/dist/clients/inbox/review/roundtrip.js +1 -1
- package/dist/commands/memory/lint.js +22 -13
- package/dist/commands/memory/shared.js +1 -1
- package/dist/commands/node/create.d.ts +1 -1
- package/dist/commands/node/create.js +1 -1
- package/dist/commands/node/lifecycle.js +1 -1
- package/dist/commands/node-worktree.js +39 -8
- package/dist/commands/revive.js +11 -2
- package/dist/commands/sys/context/admin/actions.d.ts +48 -0
- package/dist/commands/sys/context/admin/actions.js +246 -0
- package/dist/commands/sys/context/admin/axes-panel.d.ts +21 -0
- package/dist/commands/sys/context/admin/axes-panel.js +117 -0
- package/dist/commands/sys/context/admin/detail-panel.d.ts +53 -0
- package/dist/commands/sys/context/admin/detail-panel.js +178 -0
- package/dist/commands/sys/context/admin/docs-panel.d.ts +45 -0
- package/dist/commands/sys/context/admin/docs-panel.js +186 -0
- package/dist/commands/sys/context/admin/model.d.ts +75 -0
- package/dist/commands/sys/context/admin/model.js +209 -0
- package/dist/commands/sys/context/admin/shell.d.ts +82 -0
- package/dist/commands/sys/context/admin/shell.js +669 -0
- package/dist/commands/sys/context/admin.d.ts +1 -0
- package/dist/commands/sys/context/admin.js +124 -0
- package/dist/commands/sys/context/doc.d.ts +1 -0
- package/dist/commands/sys/context/doc.js +196 -0
- package/dist/commands/sys/context/prompt-review.d.ts +1 -0
- package/dist/commands/sys/{prompt-review.js → context/prompt-review.js} +10 -10
- package/dist/commands/sys/context/resolve.d.ts +55 -0
- package/dist/commands/sys/context/resolve.js +428 -0
- package/dist/commands/sys/context/sysprompt.d.ts +1 -0
- package/dist/commands/sys/{sysprompt.js → context/sysprompt.js} +11 -11
- package/dist/commands/sys/context.d.ts +2 -0
- package/dist/commands/sys/context.js +20 -0
- package/dist/commands/sys.js +3 -4
- package/dist/core/__tests__/child-death-wake.test.js +38 -22
- package/dist/core/__tests__/cron-self-cancel-delivery.test.js +72 -0
- package/dist/core/__tests__/daemon-boot.test.js +40 -28
- package/dist/core/__tests__/human-deliver.test.js +1 -1
- package/dist/core/__tests__/human-node-not-supervised.test.js +10 -15
- package/dist/core/__tests__/integration/revive.test.js +12 -12
- package/dist/core/__tests__/integration/spawn-root.test.js +6 -0
- package/dist/core/__tests__/integration/worktree-reap.test.js +32 -0
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.d.ts +1 -0
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +61 -0
- package/dist/core/__tests__/migration.test.js +38 -1
- package/dist/core/__tests__/push-final-guard.test.js +1 -1
- package/dist/core/__tests__/revive-capacity.test.d.ts +1 -0
- package/dist/core/__tests__/revive-capacity.test.js +127 -0
- package/dist/core/__tests__/revive-parked-fresh.test.js +7 -7
- package/dist/core/__tests__/seam/broker-cap-freeze.test.d.ts +1 -0
- package/dist/core/__tests__/seam/broker-cap-freeze.test.js +81 -0
- package/dist/core/__tests__/seam/dormancy-release.test.js +7 -7
- package/dist/core/__tests__/seam/yield-refresh-transaction.test.js +1 -1
- package/dist/core/canvas/browse/render.js +11 -3
- package/dist/core/canvas/canvas.d.ts +15 -3
- package/dist/core/canvas/canvas.js +52 -16
- package/dist/core/canvas/migrations.js +21 -0
- package/dist/core/canvas/nav-render.js +3 -1
- package/dist/core/canvas/remote-canvas-source.js +2 -0
- package/dist/core/canvas/render-source.d.ts +3 -1
- package/dist/core/canvas/render-source.js +7 -3
- package/dist/core/canvas/status-glyph.d.ts +10 -1
- package/dist/core/canvas/status-glyph.js +19 -3
- package/dist/core/canvas/types.d.ts +20 -1
- package/dist/core/feed/feed.js +1 -1
- package/dist/core/human/feedback-companion.js +5 -2
- package/dist/core/keybindings/catalog.d.ts +1 -1
- package/dist/core/keybindings/catalog.js +6 -2
- package/dist/core/memory/lint.d.ts +19 -0
- package/dist/core/memory/lint.js +97 -0
- package/dist/core/memory-resolver.d.ts +4 -0
- package/dist/core/memory-resolver.js +7 -7
- package/dist/core/preview-registry.js +4 -4
- package/dist/core/review/realize.js +4 -2
- package/dist/core/runtime/close.js +1 -1
- package/dist/core/runtime/fleet.d.ts +29 -1
- package/dist/core/runtime/fleet.js +23 -0
- package/dist/core/runtime/host.js +32 -11
- package/dist/core/runtime/launch-prompt.d.ts +1 -1
- package/dist/core/runtime/launch-prompt.js +2 -2
- package/dist/core/runtime/lifecycle.d.ts +4 -2
- package/dist/core/runtime/lifecycle.js +12 -1
- package/dist/core/runtime/memory.js +1 -1
- package/dist/core/runtime/reopen.js +10 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive-all.d.ts +3 -0
- package/dist/core/runtime/revive-all.js +10 -4
- package/dist/core/runtime/revive.d.ts +12 -0
- package/dist/core/runtime/revive.js +62 -3
- package/dist/core/runtime/spawn.d.ts +4 -0
- package/dist/core/runtime/spawn.js +36 -7
- package/dist/core/runtime/tmux-bindings.js +4 -0
- package/dist/core/substrate/frontmatter-validation.js +1 -1
- package/dist/core/substrate/index.d.ts +6 -3
- package/dist/core/substrate/index.js +4 -3
- package/dist/core/substrate/on-read.d.ts +0 -8
- package/dist/core/substrate/on-read.js +45 -124
- package/dist/core/substrate/plan.d.ts +94 -0
- package/dist/core/substrate/plan.js +266 -0
- package/dist/core/substrate/render.d.ts +5 -6
- package/dist/core/substrate/render.js +76 -129
- package/dist/core/substrate/schema.d.ts +1 -6
- package/dist/core/substrate/schema.js +1 -15
- package/dist/core/substrate/session-cache.d.ts +2 -10
- package/dist/core/substrate/session-cache.js +9 -47
- package/dist/core/substrate/subject-fields.d.ts +1 -4
- package/dist/core/substrate/subject-fields.js +2 -5
- package/dist/core/substrate/surface-match.d.ts +37 -17
- package/dist/core/substrate/surface-match.js +44 -53
- package/dist/core/tui/page-host.d.ts +6 -0
- package/dist/core/tui/page-host.js +12 -3
- package/dist/core/worktree.d.ts +8 -0
- package/dist/core/worktree.js +65 -0
- package/dist/daemon/__tests__/reconciler-signature.test.js +3 -2
- package/dist/daemon/__tests__/thaw-order.test.d.ts +1 -0
- package/dist/daemon/__tests__/thaw-order.test.js +55 -0
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +6 -0
- package/dist/daemon/api/__tests__/node-create-description.test.js +6 -0
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +1 -1
- package/dist/daemon/api/bridge.js +5 -1
- package/dist/daemon/api/handlers/attach.js +5 -1
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/messages.js +10 -2
- package/dist/daemon/api/handlers/nodes.js +8 -1
- package/dist/daemon/api/handlers/worktree.js +10 -1
- package/dist/daemon/api/map.js +7 -0
- package/dist/daemon/companion-retire.js +1 -1
- package/dist/daemon/cron/passes.d.ts +0 -5
- package/dist/daemon/cron/passes.js +0 -20
- package/dist/daemon/cron/sinks.js +1 -1
- package/dist/daemon/cron-run.d.ts +5 -6
- package/dist/daemon/cron-run.js +7 -16
- package/dist/daemon/crtrd.d.ts +0 -10
- package/dist/daemon/crtrd.js +23 -61
- package/dist/daemon/fleet.d.ts +10 -7
- package/dist/daemon/fleet.js +71 -12
- package/dist/daemon/messaging/node-message.js +3 -1
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/reconcilers/broker-supervision.d.ts +26 -9
- package/dist/daemon/reconcilers/broker-supervision.js +39 -52
- package/dist/daemon/reconcilers/controller-death.d.ts +7 -0
- package/dist/daemon/reconcilers/controller-death.js +26 -0
- package/dist/daemon/reconcilers/cron-lane.d.ts +0 -3
- package/dist/daemon/reconcilers/cron-lane.js +0 -3
- package/dist/daemon/reconcilers/live-obligation.js +3 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +53 -0
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +170 -0
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +5 -0
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +16 -0
- package/dist/daemon/reconcilers/node-lifecycle/terminating.d.ts +4 -0
- package/dist/daemon/reconcilers/node-lifecycle/terminating.js +13 -0
- package/dist/daemon/reconcilers/node-lifecycle/tick.d.ts +26 -0
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +140 -0
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/commands/sys/prompt-review.d.ts +0 -1
- package/dist/commands/sys/sysprompt.d.ts +0 -1
- package/dist/core/__tests__/cron-broker-capacity.test.js +0 -119
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +0 -18
- package/dist/daemon/reconcilers/dormant-inbox.js +0 -157
- /package/dist/core/__tests__/{cron-broker-capacity.test.d.ts → cron-self-cancel-delivery.test.d.ts} +0 -0
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
// rung (preview → a `# read when:` routing line; name → a bare entry), a
|
|
11
11
|
// directory that carries its own document rendering that entry on the
|
|
12
12
|
// directory's own row; a doc with NO boot entry leaks only into its dir's
|
|
13
|
-
// `[+N more]` count, never a name — EXCEPT a node-store doc with no boot entry
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
13
|
+
// `[+N more]` count, never a name — EXCEPT a node-store doc with no boot entry,
|
|
14
|
+
// which the plan floors up to `name` so it still shows its bare name rather
|
|
15
|
+
// than collapsing into a hidden count. A node-store doc with boot entries
|
|
16
|
+
// remains absent when none of those entries participates.
|
|
17
17
|
//
|
|
18
18
|
// • the SYSTEM-PROMPT half — `<memory kind="preference">`
|
|
19
19
|
// (renderPreferencesSection) — the always-present memory-usage guidance plus
|
|
@@ -31,13 +31,11 @@
|
|
|
31
31
|
// context rank. It never rewrites the frozen system snapshot.
|
|
32
32
|
//
|
|
33
33
|
// The pipeline is explicitly TWO-STEP and must never run in the other order:
|
|
34
|
-
// 1.
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// knowledge-block render floors only a node-store doc with no boot entry to
|
|
40
|
-
// `name` — the one rung-floor exemption, scoped to the node store only.
|
|
34
|
+
// 1. PLAN — planDelivery (plan.ts) computes every document's boot decision:
|
|
35
|
+
// rung, gates, profile cap, the node-store floor, and first-wins DEDUP by
|
|
36
|
+
// name over the corpus's precedence order (nearest project > user >
|
|
37
|
+
// builtin), per boot partition. This module only projects the plan's
|
|
38
|
+
// winners into its BootDoc render shape.
|
|
41
39
|
// 2. RENDER IN DISPLAY ORDER — split winners into content vs. the rest;
|
|
42
40
|
// order content general→specific (builtin, user, project outermost→
|
|
43
41
|
// nearest, node store last) then by tree position then filename; place
|
|
@@ -63,82 +61,74 @@
|
|
|
63
61
|
// directory's own line, with the directory's members nested beneath it.
|
|
64
62
|
import { sep } from 'node:path';
|
|
65
63
|
import { interpolateNodePaths } from '../canvas/paths.js';
|
|
66
|
-
import { listAllMemoryDocs, loadMemoryTargetView, resolveMemoryDoc } from '../memory-resolver.js';
|
|
64
|
+
import { ambientMemoryTarget, listAllMemoryDocs, loadMemoryTargetView, resolveMemoryDoc, } from '../memory-resolver.js';
|
|
67
65
|
import { buildMemoryTree } from '../memory/tree.js';
|
|
68
66
|
import { subKindsAvailableTo } from '../config.js';
|
|
69
67
|
import { projectScopeRoots } from '../scope.js';
|
|
70
|
-
import { gatePasses } from './gate.js';
|
|
71
68
|
// De-barreled to LEAF modules on purpose: importing from './index.js' would
|
|
72
69
|
// pull subject.js (canvas-db) transitively, re-tainting every CLI consumer of
|
|
73
70
|
// the pure render fns. The canvas-db wrappers (renderPreferencesSection /
|
|
74
71
|
// renderKnowledgeBlock) live in render-node.js instead.
|
|
75
72
|
import { documentExposedAtOrAbove, registerDocumentExposure, } from './injected-store.js';
|
|
76
|
-
import {
|
|
77
|
-
import {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
const seen = new Set();
|
|
84
|
-
const out = [];
|
|
85
|
-
for (const d of docs) {
|
|
86
|
-
if (seen.has(d.name))
|
|
87
|
-
continue;
|
|
88
|
-
seen.add(d.name);
|
|
89
|
-
out.push(d);
|
|
90
|
-
}
|
|
91
|
-
return out;
|
|
92
|
-
}
|
|
93
|
-
/** STEP 1 — the resolver-provided WINNER docs of one `kind`, eligible at boot
|
|
94
|
-
* for `subject`: parsed (non-substrate docs null-filtered), gate-passed, then
|
|
95
|
-
* first-wins DEDUPED by name over the resolver's precedence order (nearest
|
|
96
|
-
* project > user > builtin) — each at its own boot rung, INCLUDING docs with
|
|
97
|
-
* NO boot entry (the tree counts them into `[+N more]`). This is winner
|
|
98
|
-
* selection ONLY; display ordering is a separate, later step (see
|
|
99
|
-
* renderGrouped) so a builtin doc can never mask a project/user override by
|
|
100
|
-
* virtue of sorting first. Uses the per-session cache so the full corpus is
|
|
101
|
-
* scanned + parsed at most once per session across the boot-render calls.
|
|
73
|
+
import { bootPartitionOf, planDelivery } from './plan.js';
|
|
74
|
+
import { parseSubstrateDoc, previewLine, rungRank, } from './schema.js';
|
|
75
|
+
import { cachedEventCorpusInclusive } from './session-cache.js';
|
|
76
|
+
/** The node's own store (`nodes/<id>/context/memory/`), loaded through the
|
|
77
|
+
* resolver's descriptor loader like every other store. Returned across ALL
|
|
78
|
+
* kinds — the node store is the catch-all this-node store and rides into the
|
|
79
|
+
* knowledge block.
|
|
102
80
|
*
|
|
103
|
-
* The
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
let
|
|
81
|
+
* The store is addressed by the EXPLICIT `nodeId` rather than the host
|
|
82
|
+
* process's, because one process renders for other nodes (crtrd claiming a
|
|
83
|
+
* warm spare, `sys context prompt-review` walking the canvas). */
|
|
84
|
+
function nodeStoreCorpus(nodeId) {
|
|
85
|
+
if (nodeId === null)
|
|
86
|
+
return [];
|
|
87
|
+
let sources;
|
|
110
88
|
try {
|
|
111
|
-
|
|
89
|
+
// Narrowed to the node scope, so cwd and profile select no store.
|
|
90
|
+
sources = loadMemoryTargetView({ cwd: process.cwd(), profileId: null, nodeId }, { scope: 'node', quiet: true }).docs;
|
|
112
91
|
}
|
|
113
92
|
catch {
|
|
114
93
|
return [];
|
|
115
94
|
}
|
|
116
|
-
const
|
|
117
|
-
for (const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (source === undefined)
|
|
122
|
-
continue;
|
|
123
|
-
eligible.push({ ...d, source, bootRung: minRung(bootRung(d, subject), d.projectMemory) });
|
|
95
|
+
const out = [];
|
|
96
|
+
for (const source of sources) {
|
|
97
|
+
const doc = parseSubstrateDoc(source);
|
|
98
|
+
if (doc !== null)
|
|
99
|
+
out.push({ doc, source });
|
|
124
100
|
}
|
|
125
|
-
return
|
|
101
|
+
return out;
|
|
126
102
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
let
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
103
|
+
/** The session's boot corpus in PRECEDENCE order: the resolver's stores first
|
|
104
|
+
* (nearest project > user > builtin), the node's own store last so a resolver
|
|
105
|
+
* document keeps its identity against a same-named node-local one. The
|
|
106
|
+
* session cache already pairs each parsed doc with its descriptor, so the full
|
|
107
|
+
* corpus is scanned and parsed at most once per session across the boot
|
|
108
|
+
* renders. Node scope is filtered out of it because `nodeStoreCorpus` is the
|
|
109
|
+
* one path that carries node docs into a boot render — they must not
|
|
110
|
+
* double-surface. */
|
|
111
|
+
function bootCorpus(nodeId) {
|
|
112
|
+
let resolver;
|
|
113
|
+
try {
|
|
114
|
+
resolver = cachedEventCorpusInclusive(listAllMemoryDocs, parseSubstrateDoc).filter((e) => e.doc.scope !== 'node');
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return nodeStoreCorpus(nodeId);
|
|
140
118
|
}
|
|
141
|
-
return
|
|
119
|
+
return [...resolver, ...nodeStoreCorpus(nodeId)];
|
|
120
|
+
}
|
|
121
|
+
function bootPlan(subject, nodeId) {
|
|
122
|
+
return planDelivery(subject, { ...ambientMemoryTarget(), nodeId }, 'boot', {}, bootCorpus(nodeId));
|
|
123
|
+
}
|
|
124
|
+
/** STEP 1 — the plan's winners for one boot partition, in corpus order, each
|
|
125
|
+
* carrying the rung the plan settled on. Display ordering is a separate, later
|
|
126
|
+
* step (see renderGrouped) so a builtin doc can never mask a project/user
|
|
127
|
+
* override by virtue of sorting first. */
|
|
128
|
+
function bootWinners(plan, partition) {
|
|
129
|
+
return plan.docs
|
|
130
|
+
.filter((record) => record.winner && bootPartitionOf(record) === partition)
|
|
131
|
+
.map((record) => ({ ...record.doc, source: record.source, bootRung: record.finalRung }));
|
|
142
132
|
}
|
|
143
133
|
// Exposure registration
|
|
144
134
|
function rendersAtBoot(doc) {
|
|
@@ -237,41 +227,6 @@ function renderGrouped(winners, rootLabel) {
|
|
|
237
227
|
.join('\n\n');
|
|
238
228
|
return { contentProse, tree: buildTree(rest, rootLabel), contentDocs: content };
|
|
239
229
|
}
|
|
240
|
-
/** The node's own store (`nodes/<id>/context/memory/`), loaded through the
|
|
241
|
-
* resolver's descriptor loader like every other store, then gate-passed.
|
|
242
|
-
* Returned across ALL kinds — the node store is the catch-all this-node store
|
|
243
|
-
* and rides into the knowledge block.
|
|
244
|
-
*
|
|
245
|
-
* The store is addressed by the EXPLICIT `nodeId` rather than the host
|
|
246
|
-
* process's, because one process renders for other nodes (crtrd claiming a
|
|
247
|
-
* warm spare, `sys prompt-review` walking the canvas). The boot resolver
|
|
248
|
-
* corpus deliberately excludes node scope (`cachedAllMemoryDocs`), so this is
|
|
249
|
-
* the one path that carries node docs into a boot render and they cannot
|
|
250
|
-
* double-surface.
|
|
251
|
-
*
|
|
252
|
-
* Node docs follow the same GATE rule as every other store. A doc with no boot
|
|
253
|
-
* entry is retained here; renderKnowledgeForSubject floors it to `name` so it
|
|
254
|
-
* shows as a bare name instead of collapsing into `[+N more]`. */
|
|
255
|
-
function nodeStoreDocs(nodeId, subject) {
|
|
256
|
-
let docs;
|
|
257
|
-
try {
|
|
258
|
-
// Narrowed to the node scope, so cwd and profile select no store.
|
|
259
|
-
docs = loadMemoryTargetView({ cwd: process.cwd(), profileId: null, nodeId }, { scope: 'node', quiet: true }).docs;
|
|
260
|
-
}
|
|
261
|
-
catch {
|
|
262
|
-
return [];
|
|
263
|
-
}
|
|
264
|
-
const out = [];
|
|
265
|
-
for (const source of docs) {
|
|
266
|
-
const parsed = parseSubstrateDoc(source);
|
|
267
|
-
if (parsed === null || !gatePasses(parsed, subject))
|
|
268
|
-
continue;
|
|
269
|
-
const rung = bootRung(parsed, subject);
|
|
270
|
-
const floored = isVisible(rung) || parsed.surfaces.some((e) => e.on === 'boot') ? rung : 'name';
|
|
271
|
-
out.push({ ...parsed, source, bootRung: floored });
|
|
272
|
-
}
|
|
273
|
-
return out;
|
|
274
|
-
}
|
|
275
230
|
function leafSegment(name) {
|
|
276
231
|
const i = name.lastIndexOf('/');
|
|
277
232
|
return i === -1 ? name : name.slice(i + 1);
|
|
@@ -391,10 +346,10 @@ function renderChildren(dir, childPrefix, lines) {
|
|
|
391
346
|
* headed by `rootLabel`. Returns '' when there are no docs at all (the
|
|
392
347
|
* empty-tree contract).
|
|
393
348
|
*
|
|
394
|
-
* Callers (renderGrouped) pass docs already first-wins deduped by
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
349
|
+
* Callers (renderGrouped) pass docs already first-wins deduped by the plan;
|
|
350
|
+
* merging them into the canonical tree keeps that first-wins outcome
|
|
351
|
+
* structurally, because a node's `document` is the first candidate at its
|
|
352
|
+
* identity in source order. */
|
|
398
353
|
function buildTree(docs, rootLabel) {
|
|
399
354
|
if (docs.length === 0)
|
|
400
355
|
return '';
|
|
@@ -463,7 +418,7 @@ function subKindDocCitation(subKind) {
|
|
|
463
418
|
/** The computed "sub-personas you may spawn" menu for a subject's kind — the
|
|
464
419
|
* live restoration of the old `personas/resolve.ts` static menu, now derived
|
|
465
420
|
* at render time from the merged kind registry (`subKindsAvailableTo`) so it
|
|
466
|
-
* can never drift from `sys prompt-review --list`'s `subPersonas` metadata.
|
|
421
|
+
* can never drift from `sys context prompt-review --list`'s `subPersonas` metadata.
|
|
467
422
|
* Returns '' when the kind has zero available sub-kinds (no dangling empty
|
|
468
423
|
* header). Emitted for BOTH base and orchestrator modes per the CTO's ruling —
|
|
469
424
|
* mode is irrelevant to which sub-kinds are spawnable. */
|
|
@@ -507,7 +462,9 @@ function buildPreferencesBlock(subject, target) {
|
|
|
507
462
|
let protocol = '';
|
|
508
463
|
let memBody = MEMORY_USAGE_GUIDANCE;
|
|
509
464
|
if (subject !== null) {
|
|
510
|
-
|
|
465
|
+
// No nodeId: a node-local doc rides the knowledge partition whatever its
|
|
466
|
+
// kind, so it never reaches the preference block.
|
|
467
|
+
const winners = bootWinners(bootPlan(subject, null), 'preference');
|
|
511
468
|
recordRendered(target, winners);
|
|
512
469
|
const grouped = renderGrouped(winners, 'preferences');
|
|
513
470
|
contentDocs = grouped.contentDocs;
|
|
@@ -541,31 +498,20 @@ export function renderPreferencesForSubject(subject, target) {
|
|
|
541
498
|
return buildPreferencesBlock(subject, target);
|
|
542
499
|
}
|
|
543
500
|
// 2. Knowledge — `<memory kind="knowledge">` (the first-message bearings).
|
|
544
|
-
/** STEP 1 for the knowledge block, shared by the boot render and the
|
|
545
|
-
* config-change delta: the resolver's knowledge winners ∪ the node's own store
|
|
546
|
-
* (any kind), first-wins deduped resolver-first so a same-named node doc
|
|
547
|
-
* loses. Node docs carry the one rung floor — a node doc with NO boot entry is
|
|
548
|
-
* bumped to `name` so it surfaces as a bare name instead of collapsing into a
|
|
549
|
-
* `[+N more]` count; a node doc whose boot entries all fail their gates stays
|
|
550
|
-
* absent. */
|
|
551
|
-
function knowledgeWinners(subject, nodeId) {
|
|
552
|
-
return dedupeFirstWins([...selectWinners(subject, 'knowledge'), ...nodeStoreDocs(nodeId, subject)]);
|
|
553
|
-
}
|
|
554
501
|
/** The `<memory kind="knowledge">` block embedded in the session_start bearings
|
|
555
502
|
* message (bearings.ts pushes it as a SIBLING of `<crtr-bearings>`, or drops it
|
|
556
503
|
* when ''). The consultable catalog: every eligible `kind: knowledge` resolver
|
|
557
504
|
* doc PLUS the node-local memory docs (any kind) — resolver docs win
|
|
558
505
|
* first-wins dedup over a same-named node-local doc. GROUPED by rung exactly
|
|
559
506
|
* like the preference block: content prose first (general→specific,
|
|
560
|
-
* node-local last), then the preview/name catalog tree.
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
* docs never reach the `content` rung). Procedural guidance and factual
|
|
507
|
+
* node-local last), then the preview/name catalog tree. A bootless node-local
|
|
508
|
+
* doc arrives floored to `name`, so it surfaces as a bare-name tree entry
|
|
509
|
+
* rather than collapsing into a `[+N more]` count (its body still never
|
|
510
|
+
* renders: floored docs never reach the `content` rung). Procedural guidance and factual
|
|
565
511
|
* references both live here as `knowledge`. Returns '' when nothing is
|
|
566
512
|
* eligible. */
|
|
567
513
|
export function renderKnowledgeForSubject(subject, nodeId, target) {
|
|
568
|
-
const winners =
|
|
514
|
+
const winners = bootWinners(bootPlan(subject, nodeId), 'knowledge');
|
|
569
515
|
recordRendered(target, winners);
|
|
570
516
|
const { contentProse, tree } = renderGrouped(winners, 'knowledge');
|
|
571
517
|
if (contentProse === '' && tree === '')
|
|
@@ -601,8 +547,9 @@ function undelivered(target, docs) {
|
|
|
601
547
|
* because content already loaded into this context cannot be withdrawn.
|
|
602
548
|
* Rendered deltas register as transcript exposure through `target`. */
|
|
603
549
|
export function renderConfigChangeDelta(subject, nodeId, target) {
|
|
604
|
-
const
|
|
605
|
-
const
|
|
550
|
+
const plan = bootPlan(subject, nodeId);
|
|
551
|
+
const prefs = undelivered(target, bootWinners(plan, 'preference'));
|
|
552
|
+
const knowledgeDelta = undelivered(target, bootWinners(plan, 'knowledge'));
|
|
606
553
|
recordRendered(target, [...prefs, ...knowledgeDelta]);
|
|
607
554
|
const { contentDocs, tree } = renderGrouped(prefs, 'preferences');
|
|
608
555
|
// Same split as the boot preference render: shipped bodies are protocol prose
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ProfileProjectMemory } from '../../api/dto/profiles.js';
|
|
2
2
|
import type { MemoryDoc, MemoryScope } from '../memory-resolver.js';
|
|
3
|
-
import type { NodeConfigSubject } from './subject-fields.js';
|
|
4
3
|
export declare const KINDS: readonly ["knowledge", "preference"];
|
|
5
4
|
export type DocKind = (typeof KINDS)[number];
|
|
6
5
|
/** Is `v` one of the two valid document kinds? */
|
|
@@ -19,7 +18,7 @@ export declare const SURFACE_EVENTS: readonly ["boot", "workspace-open", "read",
|
|
|
19
18
|
export type SurfaceEvent = (typeof SURFACE_EVENTS)[number];
|
|
20
19
|
/** The rungs an entry may deliver at. There is no `none` — silence is the
|
|
21
20
|
* absence of an entry. (`Rung`'s `none` survives only as the internal
|
|
22
|
-
* ranking floor
|
|
21
|
+
* ranking floor — the planner's verdict for a doc that delivers nothing.) */
|
|
23
22
|
export declare const SURFACE_RUNGS: readonly ["name", "preview", "content"];
|
|
24
23
|
export type SurfaceRung = (typeof SURFACE_RUNGS)[number];
|
|
25
24
|
/** One routing entry: when event `on` exposes a subject that fits `match`
|
|
@@ -41,10 +40,6 @@ export interface SurfaceEntry {
|
|
|
41
40
|
gate?: GatePredicate;
|
|
42
41
|
at: SurfaceRung;
|
|
43
42
|
}
|
|
44
|
-
/** A doc's boot rung for `subject`: the highest `at` over participating
|
|
45
|
-
* `boot` entries, `none` when it carries none. The boot render's per-doc
|
|
46
|
-
* selection input. */
|
|
47
|
-
export declare function bootRung(doc: Pick<SubstrateSchema, 'surfaces'>, subject: NodeConfigSubject): Rung;
|
|
48
43
|
/** A gate predicate tree, evaluated by predicate.ts (`evalCondition`) against
|
|
49
44
|
* the node-config subject. Typed loosely on purpose — the matcher engine owns
|
|
50
45
|
* validation; structurally it is a field→matcher map with optional
|
|
@@ -8,7 +8,6 @@
|
|
|
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
10
|
import { PROFILE_PROJECT_MEMORY_VALUES } from '../../api/dto/profiles.js';
|
|
11
|
-
import { surfaceEntryGatePasses } from './gate.js';
|
|
12
11
|
// Kinds — the two semantic kinds (design §3): `knowledge` (consult — procedural
|
|
13
12
|
// playbooks + factual references merged) vs `preference` (behave — standing
|
|
14
13
|
// directives). `kind` is a load-bearing binary, not a content taxonomy.
|
|
@@ -51,21 +50,8 @@ export { normalizeNameSegment, normalizeDocName, resolveLocalName as resolveDocN
|
|
|
51
50
|
export const SURFACE_EVENTS = ['boot', 'workspace-open', 'read', 'memory-read', 'command', 'pre-command'];
|
|
52
51
|
/** The rungs an entry may deliver at. There is no `none` — silence is the
|
|
53
52
|
* absence of an entry. (`Rung`'s `none` survives only as the internal
|
|
54
|
-
* ranking floor
|
|
53
|
+
* ranking floor — the planner's verdict for a doc that delivers nothing.) */
|
|
55
54
|
export const SURFACE_RUNGS = ['name', 'preview', 'content'];
|
|
56
|
-
/** A doc's boot rung for `subject`: the highest `at` over participating
|
|
57
|
-
* `boot` entries, `none` when it carries none. The boot render's per-doc
|
|
58
|
-
* selection input. */
|
|
59
|
-
export function bootRung(doc, subject) {
|
|
60
|
-
let r = 'none';
|
|
61
|
-
for (const e of doc.surfaces) {
|
|
62
|
-
if (e.on !== 'boot' || !surfaceEntryGatePasses(e, subject))
|
|
63
|
-
continue;
|
|
64
|
-
if (rungRank(e.at) > rungRank(r))
|
|
65
|
-
r = e.at;
|
|
66
|
-
}
|
|
67
|
-
return r;
|
|
68
|
-
}
|
|
69
55
|
// Parse / validate.
|
|
70
56
|
/** Parse a raw frontmatter record (from `parseFrontmatterGeneric`, via the
|
|
71
57
|
* resolver) into a typed schema with defaults applied. Returns `null` when the
|
|
@@ -16,20 +16,12 @@ export declare function clearSessionCache(): void;
|
|
|
16
16
|
/** The FULL corpus (listAllMemoryDocs()), INCLUDING node scope, scanned at
|
|
17
17
|
* most once per session. `listFn` is injected by the caller to avoid
|
|
18
18
|
* circular imports at module init. This is the single filesystem walk the
|
|
19
|
-
* whole module performs —
|
|
20
|
-
*
|
|
21
|
-
* that need every referenceable doc (inline memory-reference inventory) call
|
|
22
|
-
* this directly instead of `cachedAllMemoryDocs`. */
|
|
19
|
+
* whole module performs — every other entry derives from this result rather
|
|
20
|
+
* than re-scanning. */
|
|
23
21
|
export declare function cachedAllMemoryDocsInclusive(listFn: ListAllMemoryDocsFn): MemoryDoc[];
|
|
24
22
|
/** allMemoryDocsInclusive parsed and paired with its descriptors, INCLUDING
|
|
25
23
|
* node scope — the event corpus, and the module's only parse pass. */
|
|
26
24
|
export declare function cachedEventCorpusInclusive(listFn: ListAllMemoryDocsFn, parseFn: ParseSubstrateDocFn): EventCorpusDoc[];
|
|
27
25
|
/** The parsed docs of the inclusive event corpus, without their descriptors. */
|
|
28
26
|
export declare function cachedSubstrateDocsInclusive(listFn: ListAllMemoryDocsFn, parseFn: ParseSubstrateDocFn): SubstrateDoc[];
|
|
29
|
-
/** All memory docs (listAllMemoryDocs()), scanned once per session.
|
|
30
|
-
* `listFn` is injected by the caller to avoid circular imports at module init. */
|
|
31
|
-
export declare function cachedAllMemoryDocs(listFn: ListAllMemoryDocsFn): MemoryDoc[];
|
|
32
|
-
/** The node-excluded parsed view — render.ts's boot corpus. Projected out of
|
|
33
|
-
* the inclusive parse rather than parsed again. */
|
|
34
|
-
export declare function cachedSubstrateDocs(listFn: ListAllMemoryDocsFn, parseFn: ParseSubstrateDocFn): SubstrateDoc[];
|
|
35
27
|
export {};
|
|
@@ -23,22 +23,17 @@
|
|
|
23
23
|
// filtering/mapping, never by calling listFn() again.
|
|
24
24
|
// • eventCorpusInclusive — allMemoryDocsInclusive parsed once, each surviving
|
|
25
25
|
// SubstrateDoc paired with the resolver descriptor it
|
|
26
|
-
// parsed from. The ONE parse pass
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
26
|
+
// parsed from. The ONE parse pass every delivery plan
|
|
27
|
+
// reads from. The pairs matter: `./` memory-read globs
|
|
28
|
+
// anchor on the descriptor's canonical routing anchor,
|
|
29
|
+
// and the boot tree orders by its physical path. Boot
|
|
30
|
+
// filters node scope out of it and loads the node's own
|
|
31
|
+
// store separately (render.ts), so a node doc never
|
|
32
|
+
// double-surfaces there.
|
|
30
33
|
// • substrateDocsInclusive — the parsed docs alone, still including node
|
|
31
34
|
// scope. Consumers that need every referenceable doc
|
|
32
35
|
// (e.g. the inline memory-reference inventory) use this
|
|
33
36
|
// pair with allMemoryDocsInclusive.
|
|
34
|
-
// • allMemoryDocs — allMemoryDocsInclusive with node-scope docs excluded
|
|
35
|
-
// (boot-only view — see the comment on
|
|
36
|
-
// cachedAllMemoryDocs). Consumed by render.ts.
|
|
37
|
-
// • substrateDocs — the same node-excluded view, parsed. Used by
|
|
38
|
-
// render.ts's resolver corpus. The event corpus
|
|
39
|
-
// (on-read.ts) uses the INCLUSIVE pairs instead: node
|
|
40
|
-
// docs' surfaces entries fire on read/memory-read/
|
|
41
|
-
// command like any other store's.
|
|
42
37
|
// Node subjects are deliberately NOT cached: lifecycle, mode, kind, and other
|
|
43
38
|
// gate inputs can change while a resident broker/session remains live. Rendering
|
|
44
39
|
// must always gate against the current persisted node metadata.
|
|
@@ -46,8 +41,6 @@ const _cache = {
|
|
|
46
41
|
allMemoryDocsInclusive: null,
|
|
47
42
|
eventCorpusInclusive: null,
|
|
48
43
|
substrateDocsInclusive: null,
|
|
49
|
-
allMemoryDocs: null,
|
|
50
|
-
substrateDocs: null,
|
|
51
44
|
};
|
|
52
45
|
/** Called by canvas-doc-substrate.ts on every `session_start`.
|
|
53
46
|
* Resets all cached values so the next access triggers a fresh scan. */
|
|
@@ -55,16 +48,12 @@ export function clearSessionCache() {
|
|
|
55
48
|
_cache.allMemoryDocsInclusive = null;
|
|
56
49
|
_cache.eventCorpusInclusive = null;
|
|
57
50
|
_cache.substrateDocsInclusive = null;
|
|
58
|
-
_cache.allMemoryDocs = null;
|
|
59
|
-
_cache.substrateDocs = null;
|
|
60
51
|
}
|
|
61
52
|
/** The FULL corpus (listAllMemoryDocs()), INCLUDING node scope, scanned at
|
|
62
53
|
* most once per session. `listFn` is injected by the caller to avoid
|
|
63
54
|
* circular imports at module init. This is the single filesystem walk the
|
|
64
|
-
* whole module performs —
|
|
65
|
-
*
|
|
66
|
-
* that need every referenceable doc (inline memory-reference inventory) call
|
|
67
|
-
* this directly instead of `cachedAllMemoryDocs`. */
|
|
55
|
+
* whole module performs — every other entry derives from this result rather
|
|
56
|
+
* than re-scanning. */
|
|
68
57
|
export function cachedAllMemoryDocsInclusive(listFn) {
|
|
69
58
|
if (_cache.allMemoryDocsInclusive === null) {
|
|
70
59
|
_cache.allMemoryDocsInclusive = listFn();
|
|
@@ -92,30 +81,3 @@ export function cachedSubstrateDocsInclusive(listFn, parseFn) {
|
|
|
92
81
|
}
|
|
93
82
|
return _cache.substrateDocsInclusive;
|
|
94
83
|
}
|
|
95
|
-
/** All memory docs (listAllMemoryDocs()), scanned once per session.
|
|
96
|
-
* `listFn` is injected by the caller to avoid circular imports at module init. */
|
|
97
|
-
export function cachedAllMemoryDocs(listFn) {
|
|
98
|
-
if (_cache.allMemoryDocs === null) {
|
|
99
|
-
// The BOOT pipeline (render.ts) EXCLUDES node-scope docs: node-local
|
|
100
|
-
// memory surfaces at boot via render.ts's nodeLocalDocs (any kind, floored
|
|
101
|
-
// into the knowledge block), NOT through the resolver corpus, so a node doc
|
|
102
|
-
// must not also enter there (it would double-surface at boot). The event
|
|
103
|
-
// corpus (on-read.ts) uses the inclusive view — node docs' surfaces
|
|
104
|
-
// entries fire on read/memory-read/command. The `node` scope reaches CLI
|
|
105
|
-
// read/list/find/delete through the uncached listAllMemoryDocs() path.
|
|
106
|
-
// Derived from the inclusive cache by filtering, so listFn() itself still
|
|
107
|
-
// runs at most once per session even though both views are consumed.
|
|
108
|
-
_cache.allMemoryDocs = cachedAllMemoryDocsInclusive(listFn).filter((d) => d.scope !== 'node');
|
|
109
|
-
}
|
|
110
|
-
return _cache.allMemoryDocs;
|
|
111
|
-
}
|
|
112
|
-
/** The node-excluded parsed view — render.ts's boot corpus. Projected out of
|
|
113
|
-
* the inclusive parse rather than parsed again. */
|
|
114
|
-
export function cachedSubstrateDocs(listFn, parseFn) {
|
|
115
|
-
if (_cache.substrateDocs === null) {
|
|
116
|
-
_cache.substrateDocs = cachedEventCorpusInclusive(listFn, parseFn)
|
|
117
|
-
.filter((e) => e.doc.scope !== 'node')
|
|
118
|
-
.map((e) => e.doc);
|
|
119
|
-
}
|
|
120
|
-
return _cache.substrateDocs;
|
|
121
|
-
}
|
|
@@ -31,10 +31,7 @@ export interface NodeConfigSubject {
|
|
|
31
31
|
}
|
|
32
32
|
/** The scope a cwd resolves into: `project` when scope.ts finds a
|
|
33
33
|
* nearest-ancestor `.crouter/` at/above it, else `user`. Reuses the existing
|
|
34
|
-
* resolver (`projectScopeRoot`).
|
|
35
|
-
* on first call, so for a node assembling its OWN subject (cwd === process.cwd)
|
|
36
|
-
* this is exact; resolving an arbitrary unrelated cwd in the same process would
|
|
37
|
-
* return the cached root — fine for per-node subject assembly. */
|
|
34
|
+
* resolver (`projectScopeRoot`). */
|
|
38
35
|
export declare function scopeForCwd(cwd: string): 'user' | 'project';
|
|
39
36
|
/** Resolve `profile_id` to the manifest's mutable `name` for the gate subject.
|
|
40
37
|
* NEVER throws: a missing/deleted profile resolves to `null` silently (the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// subject-fields.ts — the PURE half of subject assembly: the NodeConfigSubject
|
|
2
2
|
// shape plus the two derived-field resolvers (`scopeForCwd`, `profileNameFor`)
|
|
3
3
|
// that read scope/profile config but NEVER the canvas-db. Split out of
|
|
4
|
-
// subject.ts so CLI consumers (`sys prompt-review`) can build a subject from an
|
|
4
|
+
// subject.ts so CLI consumers (`sys context prompt-review`) can build a subject from an
|
|
5
5
|
// API-fetched node without pulling subject.ts's canvas-db reach (getNode/getRow).
|
|
6
6
|
// The canvas-db assembler (`assembleNodeSubject`, `spineDepth`) stays in
|
|
7
7
|
// subject.ts for broker/daemon-side callers.
|
|
@@ -10,10 +10,7 @@ import { loadProfileManifest } from '../profiles/manifest.js';
|
|
|
10
10
|
import { CrtrError } from '../errors.js';
|
|
11
11
|
/** The scope a cwd resolves into: `project` when scope.ts finds a
|
|
12
12
|
* nearest-ancestor `.crouter/` at/above it, else `user`. Reuses the existing
|
|
13
|
-
* resolver (`projectScopeRoot`).
|
|
14
|
-
* on first call, so for a node assembling its OWN subject (cwd === process.cwd)
|
|
15
|
-
* this is exact; resolving an arbitrary unrelated cwd in the same process would
|
|
16
|
-
* return the cached root — fine for per-node subject assembly. */
|
|
13
|
+
* resolver (`projectScopeRoot`). */
|
|
17
14
|
export function scopeForCwd(cwd) {
|
|
18
15
|
return projectScopeRoot(cwd) !== null ? 'project' : 'user';
|
|
19
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Rung, type SubstrateDoc, type SurfaceEntry } from './schema.js';
|
|
1
|
+
import { type Rung, type SubstrateDoc, type SurfaceEntry, type SurfaceEvent } from './schema.js';
|
|
2
2
|
import type { NodeConfigSubject } from './subject-fields.js';
|
|
3
3
|
/** The project directory owning a doc's store: the path segment stack above
|
|
4
4
|
* the doc's `.crouter` dir. `null` when the doc's path carries no `.crouter`
|
|
@@ -14,12 +14,12 @@ export declare function underOwningRoot(doc: Pick<SubstrateDoc, 'path'>, absFile
|
|
|
14
14
|
* realpathed. `readFrontmatter` is the read file's own parsed YAML (empty
|
|
15
15
|
* for non-markdown files); an empty record never satisfies
|
|
16
16
|
* `matchFrontmatter`. */
|
|
17
|
-
export declare function matchesReadEntry(entry: SurfaceEntry, doc: Pick<SubstrateDoc, 'path' | 'scope'>, subject: NodeConfigSubject, absReadFile: string, readFrontmatter: Record<string, unknown>): boolean;
|
|
17
|
+
export declare function matchesReadEntry(entry: SurfaceEntry, doc: Pick<SubstrateDoc, 'path' | 'scope'>, subject: NodeConfigSubject | null, absReadFile: string, readFrontmatter: Record<string, unknown>): boolean;
|
|
18
18
|
/** Does a `memory-read` entry on a carrier anchored at `routingAnchor` fit a
|
|
19
19
|
* resolved read of the doc known by its exact canonical `name`? */
|
|
20
20
|
export declare function matchesMemoryReadEntry(entry: SurfaceEntry, routingAnchor: string, subject: NodeConfigSubject | null, name: string): boolean;
|
|
21
21
|
/** Does a `command` entry fit the executed command string? */
|
|
22
|
-
export declare function matchesCommandEntry(entry: SurfaceEntry, subject: NodeConfigSubject, command: string): boolean;
|
|
22
|
+
export declare function matchesCommandEntry(entry: SurfaceEntry, subject: NodeConfigSubject | null, command: string): boolean;
|
|
23
23
|
/** Remove heredoc BODIES (the stdin data between `<<DELIM` and its closing
|
|
24
24
|
* `DELIM` line) from a command before it is matched. The opening line is kept
|
|
25
25
|
* — `crtr push final <<'EOF'` is still a real `push final` invocation — but the
|
|
@@ -34,21 +34,41 @@ export declare function stripHeredocs(command: string): string;
|
|
|
34
34
|
* command with its heredoc bodies stripped. Subshell parentheses, backticks,
|
|
35
35
|
* and path-prefixed binaries stay unhandled: this is a guardrail against the
|
|
36
36
|
* faithful-but-uninformed action, not an enforcement boundary. */
|
|
37
|
-
export declare function matchesPreCommandEntry(entry: SurfaceEntry, subject: NodeConfigSubject, command: string): boolean;
|
|
37
|
+
export declare function matchesPreCommandEntry(entry: SurfaceEntry, subject: NodeConfigSubject | null, command: string): boolean;
|
|
38
|
+
/** What an event occurrence exposes for matching. A field the event does not
|
|
39
|
+
* use is ignored; a field the event needs and lacks matches nothing. */
|
|
40
|
+
export interface SurfaceMatchPayload {
|
|
41
|
+
/** `read`: the read file, already realpathed. */
|
|
42
|
+
absoluteFile?: string;
|
|
43
|
+
/** `read`: the read file's own parsed YAML (empty for a non-markdown file). */
|
|
44
|
+
readFrontmatter?: Record<string, unknown>;
|
|
45
|
+
/** `memory-read`: the exact canonical name the read resolved to. */
|
|
46
|
+
resolvedCanonicalName?: string;
|
|
47
|
+
/** `memory-read`: the CARRIER's routing anchor, from its resolver descriptor
|
|
48
|
+
* — not derivable from a canonical name, which cannot say whether the doc
|
|
49
|
+
* fronts its own directory. */
|
|
50
|
+
routingAnchor?: string;
|
|
51
|
+
/** `command` / `pre-command`: the command string. */
|
|
52
|
+
command?: string;
|
|
53
|
+
}
|
|
54
|
+
/** A doc as the matchers see it. `path`/`scope` are consulted only by `read`
|
|
55
|
+
* (a `./`-anchored glob resolves against the store's owning repo dir). */
|
|
56
|
+
type MatchDoc = Pick<SubstrateDoc, 'surfaces'> & Partial<Pick<SubstrateDoc, 'path' | 'scope'>>;
|
|
57
|
+
/** Does ONE entry of `event` fit this occurrence — constraints and the entry's
|
|
58
|
+
* own gate together? */
|
|
59
|
+
export declare function surfaceEntryParticipates(entry: SurfaceEntry, doc: MatchDoc, subject: NodeConfigSubject | null, event: SurfaceEvent, payload: SurfaceMatchPayload): boolean;
|
|
60
|
+
/** The entry that decides this doc's delivery for one event occurrence: the
|
|
61
|
+
* highest-rung participating entry, or null when none participates. */
|
|
62
|
+
export declare function matchingSurfaceEntry(doc: MatchDoc, subject: NodeConfigSubject | null, event: SurfaceEvent, payload: SurfaceMatchPayload): SurfaceEntry | null;
|
|
38
63
|
/** The doc's delivery rung for a read of `absReadFile` (already realpathed). */
|
|
39
|
-
export declare function readDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces' | 'path' | 'scope'>, subject: NodeConfigSubject, absReadFile: string, readFrontmatter: Record<string, unknown>): Rung;
|
|
40
|
-
/** The doc's workspace-open rung.
|
|
41
|
-
|
|
42
|
-
export declare function workspaceOpenRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject): Rung;
|
|
64
|
+
export declare function readDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces' | 'path' | 'scope'>, subject: NodeConfigSubject | null, absReadFile: string, readFrontmatter: Record<string, unknown>): Rung;
|
|
65
|
+
/** The doc's workspace-open rung. */
|
|
66
|
+
export declare function workspaceOpenRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject | null): Rung;
|
|
43
67
|
/** The doc's delivery rung for a `crtr memory read` that resolved a doc known
|
|
44
|
-
* by its exact canonical `name` — no mount-stripped or other alias.
|
|
45
|
-
* `routingAnchor` comes from the doc's resolver descriptor — it is not
|
|
46
|
-
* derivable from the canonical name, which cannot say whether the doc fronts
|
|
47
|
-
* its own directory. */
|
|
68
|
+
* by its exact canonical `name` — no mount-stripped or other alias. */
|
|
48
69
|
export declare function memoryReadDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces'>, routingAnchor: string, subject: NodeConfigSubject | null, name: string): Rung;
|
|
49
70
|
/** The doc's delivery rung for an executed command string. */
|
|
50
|
-
export declare function commandDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject, command: string): Rung;
|
|
51
|
-
/** The doc's delivery rung for a command about to run
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export declare function preCommandDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject, command: string): Rung;
|
|
71
|
+
export declare function commandDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject | null, command: string): Rung;
|
|
72
|
+
/** The doc's delivery rung for a command about to run. */
|
|
73
|
+
export declare function preCommandDeliveryRung(doc: Pick<SubstrateDoc, 'surfaces'>, subject: NodeConfigSubject | null, command: string): Rung;
|
|
74
|
+
export {};
|