@north-light/crouter 0.3.175 → 0.3.177
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 +4 -4
- package/dist/api/client.js +2 -2
- package/dist/api/dto/lifecycle.d.ts +1 -1
- package/dist/api/dto/nodes.d.ts +7 -1
- package/dist/api/dto/profiles.d.ts +3 -0
- package/dist/api/dto/reports.d.ts +1 -1
- package/dist/clients/attach/__tests__/group-activity.test.js +2 -2
- package/dist/clients/attach/config.js +5 -5
- package/dist/clients/attach/input/clipboard-image.js +2 -2
- package/dist/clients/attach/input/ref-autocomplete.js +1 -1
- package/dist/clients/attach/input/titled-editor.d.ts +12 -13
- package/dist/clients/attach/input/titled-editor.js +14 -15
- package/dist/clients/attach/overlays/dialogs.d.ts +1 -1
- package/dist/clients/attach/overlays/dialogs.js +2 -2
- package/dist/clients/attach/overlays/mcp.js +5 -12
- package/dist/clients/attach/render/chat-view.d.ts +1 -1
- package/dist/clients/attach/render/chat-view.js +2 -2
- package/dist/clients/attach/render/crtr-output.d.ts +3 -3
- package/dist/clients/attach/render/crtr-output.js +25 -13
- package/dist/clients/attach/render/group-recap.js +7 -0
- package/dist/clients/attach/session/context.js +3 -3
- package/dist/clients/attach/session/editor-inventory.js +6 -6
- package/dist/clients/attach/session/input-wiring.js +1 -1
- package/dist/clients/attach/session/teardown.js +7 -9
- package/dist/clients/attach/slash/dispatch.d.ts +1 -2
- package/dist/clients/attach/slash/dispatch.js +4 -8
- package/dist/clients/attach/viewer.js +536 -566
- package/dist/clients/inbox/controller.js +3 -2
- package/dist/clients/inbox/deck-adapter.js +3 -2
- package/dist/clients/surfaces/host.d.ts +1 -1
- package/dist/commands/api-client.d.ts +12 -13
- package/dist/commands/api-client.js +15 -16
- package/dist/commands/chord.js +1 -2
- package/dist/commands/human/queue.js +6 -5
- package/dist/commands/memory/find.js +3 -3
- package/dist/commands/node/create.js +7 -3
- package/dist/commands/node/lifecycle.js +1 -1
- package/dist/commands/node-lifecycle-revive.d.ts +1 -1
- package/dist/commands/node-lifecycle-revive.js +3 -3
- package/dist/commands/profile/list.js +3 -1
- package/dist/commands/profile/new.js +4 -1
- package/dist/commands/profile/project.js +23 -9
- package/dist/commands/profile/show.js +3 -1
- package/dist/commands/profile.js +2 -2
- package/dist/commands/push.js +1 -1
- package/dist/commands/surface/node/placement.d.ts +1 -1
- package/dist/commands/surface/node/placement.js +1 -1
- package/dist/commands/surface-edit.js +1 -4
- package/dist/commands/sys/logs.js +4 -2
- package/dist/commands/sys/panels/panel.d.ts +3 -3
- package/dist/commands/sys/panels/panel.js +3 -3
- package/dist/commands/sys/setup-core.js +1 -7
- package/dist/commands/sys/sync-deps.js +1 -3
- package/dist/commands/sys/sync-project-guidance.js +2 -11
- package/dist/commands/sys/sysprompt.js +1 -3
- package/dist/core/__tests__/branded-host-concurrency.test.js +1 -1
- package/dist/core/__tests__/fixtures/fake-engine.js +1 -1
- package/dist/core/__tests__/helpers/harness.d.ts +1 -1
- package/dist/core/__tests__/helpers/harness.js +1 -1
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +1 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +1 -1
- package/dist/core/canvas/boot.js +1 -1
- package/dist/core/canvas/browse/app.js +2 -2
- package/dist/core/canvas/canvas.d.ts +3 -3
- package/dist/core/canvas/canvas.js +3 -3
- package/dist/core/canvas/daemon-owner.js +1 -2
- package/dist/core/canvas/db.js +7 -8
- package/dist/core/canvas/extensions.d.ts +1 -1
- package/dist/core/canvas/extensions.js +7 -1
- package/dist/core/canvas/index.js +2 -2
- package/dist/core/canvas/pid.d.ts +12 -14
- package/dist/core/canvas/pid.js +16 -20
- package/dist/core/canvas/remote-transport.js +2 -2
- package/dist/core/canvas/status-glyph.d.ts +1 -1
- package/dist/core/canvas/status-glyph.js +1 -1
- package/dist/core/canvas/types.d.ts +1 -1
- package/dist/core/command-manifests/manifest.js +4 -6
- package/dist/core/command-manifests/schema.js +10 -12
- package/dist/core/command-plugins/transport/exec-invoke.js +5 -7
- package/dist/core/command-plugins/transport/http-invoke.js +14 -8
- package/dist/core/command.js +3 -1
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +6 -29
- package/dist/core/events/read.js +1 -3
- package/dist/core/exclusive-lock.d.ts +14 -0
- package/dist/core/exclusive-lock.js +124 -0
- package/dist/core/fault-classifier.js +1 -3
- package/dist/core/fs-utils.d.ts +7 -0
- package/dist/core/fs-utils.js +29 -2
- package/dist/core/host-exports/export.d.ts +4 -5
- package/dist/core/host-exports/export.js +4 -5
- package/dist/core/human/claim.js +4 -2
- package/dist/core/human/convention.d.ts +0 -11
- package/dist/core/human/convention.js +1 -131
- package/dist/core/human/scan.js +5 -4
- package/dist/core/io.d.ts +23 -0
- package/dist/core/io.js +60 -0
- package/dist/core/preview-registry.d.ts +10 -5
- package/dist/core/preview-registry.js +136 -2537
- package/dist/core/profiles/manifest.d.ts +13 -2
- package/dist/core/profiles/manifest.js +58 -49
- package/dist/core/review/store.d.ts +4 -1
- package/dist/core/review/store.js +10 -0
- package/dist/core/review/types.d.ts +1 -1
- package/dist/core/review/types.js +1 -1
- package/dist/core/runtime/branded-host.js +6 -84
- package/dist/core/runtime/broker/frame-dispatch.js +4 -4
- package/dist/core/runtime/broker-cli.js +1 -1
- package/dist/core/runtime/broker-extension-render.js +1 -1
- package/dist/core/runtime/broker-protocol.d.ts +9 -10
- package/dist/core/runtime/broker-protocol.js +9 -10
- package/dist/core/runtime/broker-sdk.d.ts +1 -1
- package/dist/core/runtime/broker.js +6 -6
- package/dist/core/runtime/canvas-extensions.d.ts +1 -0
- package/dist/core/runtime/canvas-extensions.js +2 -0
- package/dist/core/runtime/host.js +14 -14
- package/dist/core/runtime/launch.d.ts +1 -1
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/lifecycle.js +16 -21
- package/dist/core/runtime/node-read.js +2 -3
- package/dist/core/runtime/package-health.js +1 -8
- package/dist/core/runtime/persona.js +2 -2
- package/dist/core/runtime/pi-vendored.d.ts +4 -2
- package/dist/core/runtime/pi-vendored.js +5 -16
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/reopen.js +2 -2
- package/dist/core/runtime/revive-all.d.ts +3 -3
- package/dist/core/runtime/revive-all.js +6 -6
- package/dist/core/runtime/revive.js +1 -1
- package/dist/core/runtime/spawn.d.ts +1 -2
- package/dist/core/runtime/spawn.js +2 -3
- package/dist/core/runtime/structured-output.js +4 -6
- package/dist/core/runtime/tmux-bindings.js +1 -1
- package/dist/core/runtime/tmux-driver.d.ts +2 -2
- package/dist/core/runtime/tmux-driver.js +3 -5
- package/dist/core/runtime/tool-group-summary.js +5 -4
- package/dist/core/runtime/warm-pool.d.ts +9 -8
- package/dist/core/runtime/warm-pool.js +58 -62
- package/dist/core/scope.js +2 -9
- package/dist/core/self-update.js +3 -3
- package/dist/core/spawn.d.ts +0 -1
- package/dist/core/spawn.js +1 -4
- package/dist/core/substrate/index.d.ts +2 -1
- package/dist/core/substrate/index.js +2 -1
- package/dist/core/substrate/on-read-node.d.ts +7 -0
- package/dist/core/substrate/on-read-node.js +37 -0
- package/dist/core/substrate/on-read.d.ts +7 -5
- package/dist/core/substrate/on-read.js +16 -32
- package/dist/core/termrender/termrender.js +16 -96
- package/dist/core/wake.js +2 -2
- package/dist/core/worktree.d.ts +3 -3
- package/dist/core/worktree.js +16 -107
- package/dist/daemon/api/bridge.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -2
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/nodes.js +33 -10
- package/dist/daemon/api/handlers/reports.js +1 -1
- package/dist/daemon/api/handlers/review-comments.js +5 -44
- package/dist/daemon/api/handlers/reviews.js +5 -53
- package/dist/daemon/api/handlers/validate.d.ts +23 -0
- package/dist/daemon/api/handlers/validate.js +58 -0
- package/dist/daemon/api/map.js +1 -0
- package/dist/daemon/cron-run.js +7 -7
- package/dist/daemon/human/finish.js +3 -2
- package/dist/daemon/manage.d.ts +6 -6
- package/dist/daemon/manage.js +15 -16
- package/dist/daemon/review/finish.js +1 -10
- package/dist/pi-extensions/canvas-context-intro.js +1 -14
- package/dist/pi-extensions/canvas-doc-substrate.js +2 -2
- package/dist/pi-extensions/canvas-preview-result.d.ts +22 -0
- package/dist/pi-extensions/canvas-preview-result.js +60 -0
- package/dist/pi-extensions/canvas-review-boundary.js +1 -14
- package/dist/pi-extensions/truncate.d.ts +5 -0
- package/dist/pi-extensions/truncate.js +14 -0
- package/dist/shared/predicates.d.ts +2 -0
- package/dist/shared/predicates.js +4 -0
- package/dist/shared/shell-quote.d.ts +3 -0
- package/dist/shared/shell-quote.js +5 -0
- package/dist/shared/tool-groups.d.ts +4 -2
- package/dist/shared/tool-groups.js +3 -3
- package/dist/types.d.ts +8 -5
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/core/substrate/on-read-pure.d.ts +0 -7
- package/dist/core/substrate/on-read-pure.js +0 -272
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
// on-read.ts — file-context delivery for the document substrate.
|
|
2
|
-
//
|
|
3
|
-
// A memory with file-read visibility participates only through an explicit
|
|
4
|
-
// `applies-to` path glob (authoring lint requires one). Two events use that one
|
|
5
|
-
// routing mechanism:
|
|
6
|
-
//
|
|
7
|
-
// • A successful `read` tool call evaluates the read file against every
|
|
8
|
-
// visible substrate doc. Project stores encountered between that file and
|
|
9
|
-
// the filesystem root join the resolved cwd/profile corpus, so a nested
|
|
10
|
-
// workspace can contribute guidance exactly when a file beneath it is read.
|
|
11
|
-
// • Opening a workspace evaluates the reserved `applies-to: "."` target for
|
|
12
|
-
// every project store mounted by the cwd and selected profile. This happens
|
|
13
|
-
// while the first-message bearings are assembled, so workspace-wide context
|
|
14
|
-
// arrives before the task rather than waiting for an arbitrary first file.
|
|
15
|
-
//
|
|
16
|
-
// `read-when` remains an additional OR trigger over a read markdown file's own
|
|
17
|
-
// frontmatter. It does not replace `applies-to`: every non-none file-read rung
|
|
18
|
-
// still declares its path boundary explicitly.
|
|
19
|
-
//
|
|
20
|
-
// Every candidate renders at its own fileReadVisibility rung. Explicit routing
|
|
21
|
-
// is the whole on-read model, so directory INDEX ceilings remain a boot-catalog
|
|
22
|
-
// concern and do not cap a deliberately matched document.
|
|
23
|
-
import { realpathSync } from 'node:fs';
|
|
24
|
-
import { homedir } from 'node:os';
|
|
25
|
-
import { basename, dirname, matchesGlob, parse, relative, sep } from 'node:path';
|
|
26
|
-
import { CRTR_DIR_NAME } from '../../types.js';
|
|
27
|
-
import { pathExists, readText, walkFiles } from '../fs-utils.js';
|
|
28
|
-
import { parseFrontmatterGeneric } from '../frontmatter.js';
|
|
29
|
-
import { evalCondition } from '../predicate.js';
|
|
30
|
-
import { listAllMemoryDocs, listProjectMemoryDocs } from '../memory-resolver.js';
|
|
31
|
-
import { userScopeRoot } from '../scope.js';
|
|
32
|
-
import { displayName } from './ceiling.js';
|
|
33
|
-
import { gatePasses } from './gate.js';
|
|
34
|
-
import { normalizeDocName, parseSubstrateDoc, parseSubstrateFrontmatter, previewLine, resolveDocName } from './schema.js';
|
|
35
|
-
import { cachedSubstrateDocs } from './session-cache.js';
|
|
36
|
-
const JUNK_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache', '.yalc']);
|
|
37
|
-
function realpathOrSelf(p) {
|
|
38
|
-
try {
|
|
39
|
-
return realpathSync(p);
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return p;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function attr(s) {
|
|
46
|
-
return s
|
|
47
|
-
.replace(/&/g, '&')
|
|
48
|
-
.replace(/"/g, '"')
|
|
49
|
-
.replace(/</g, '<')
|
|
50
|
-
.replace(/>/g, '>');
|
|
51
|
-
}
|
|
52
|
-
function gitRootOf(p) {
|
|
53
|
-
let d = p;
|
|
54
|
-
const root = parse(d).root;
|
|
55
|
-
while (true) {
|
|
56
|
-
if (pathExists(`${d}${sep}.git`))
|
|
57
|
-
return d;
|
|
58
|
-
if (d === root)
|
|
59
|
-
return null;
|
|
60
|
-
const parent = dirname(d);
|
|
61
|
-
if (parent === d)
|
|
62
|
-
return null;
|
|
63
|
-
d = parent;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function disp(p) {
|
|
67
|
-
const root = gitRootOf(p);
|
|
68
|
-
if (!root)
|
|
69
|
-
return p;
|
|
70
|
-
const rel = relative(root, p);
|
|
71
|
-
return rel === '' ? '.' : rel;
|
|
72
|
-
}
|
|
73
|
-
function isJunkAncestor(dir) {
|
|
74
|
-
return dir.split(sep).some((segment) => JUNK_DIRS.has(segment));
|
|
75
|
-
}
|
|
76
|
-
function owningRootOf(doc) {
|
|
77
|
-
const parts = doc.path.split(sep);
|
|
78
|
-
const idx = parts.lastIndexOf(CRTR_DIR_NAME);
|
|
79
|
-
if (idx <= 0)
|
|
80
|
-
return null;
|
|
81
|
-
return parts.slice(0, idx).join(sep) || sep;
|
|
82
|
-
}
|
|
83
|
-
function loadProjectDoc(file, memoryDir) {
|
|
84
|
-
try {
|
|
85
|
-
const raw = relative(memoryDir, file)
|
|
86
|
-
.replace(/\.md$/i, '')
|
|
87
|
-
.split(sep)
|
|
88
|
-
.join('/');
|
|
89
|
-
const fallbackName = normalizeDocName(raw);
|
|
90
|
-
if (fallbackName === '')
|
|
91
|
-
return null;
|
|
92
|
-
const { data, body } = parseFrontmatterGeneric(readText(file));
|
|
93
|
-
const schema = parseSubstrateFrontmatter(data);
|
|
94
|
-
if (schema === null)
|
|
95
|
-
return null;
|
|
96
|
-
return {
|
|
97
|
-
...schema,
|
|
98
|
-
name: resolveDocName(data, fallbackName),
|
|
99
|
-
scope: 'project',
|
|
100
|
-
path: file,
|
|
101
|
-
body,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function safeWalkMarkdown(dir) {
|
|
109
|
-
try {
|
|
110
|
-
return walkFiles(dir, (name) => name.toLowerCase().endsWith('.md'));
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
/** Project docs from every workspace store enclosing the read file. This is a
|
|
117
|
-
* discovery walk only: each returned doc must still match an explicit trigger. */
|
|
118
|
-
function enclosingProjectDocs(absReadFile) {
|
|
119
|
-
const docs = [];
|
|
120
|
-
const seen = new Set();
|
|
121
|
-
const home = realpathOrSelf(homedir());
|
|
122
|
-
const userRoot = realpathOrSelf(userScopeRoot());
|
|
123
|
-
const fsRoot = parse(absReadFile).root;
|
|
124
|
-
let dir = dirname(absReadFile);
|
|
125
|
-
while (true) {
|
|
126
|
-
if (dir !== home && dir !== userRoot && !isJunkAncestor(dir)) {
|
|
127
|
-
const memoryDir = `${dir}${sep}${CRTR_DIR_NAME}${sep}memory`;
|
|
128
|
-
if (pathExists(memoryDir)) {
|
|
129
|
-
for (const file of safeWalkMarkdown(memoryDir)) {
|
|
130
|
-
const real = realpathOrSelf(file);
|
|
131
|
-
if (seen.has(real))
|
|
132
|
-
continue;
|
|
133
|
-
seen.add(real);
|
|
134
|
-
const doc = loadProjectDoc(file, memoryDir);
|
|
135
|
-
if (doc !== null)
|
|
136
|
-
docs.push(doc);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (dir === home || dir === fsRoot)
|
|
141
|
-
break;
|
|
142
|
-
const parent = dirname(dir);
|
|
143
|
-
if (parent === dir)
|
|
144
|
-
break;
|
|
145
|
-
dir = parent;
|
|
146
|
-
}
|
|
147
|
-
return docs;
|
|
148
|
-
}
|
|
149
|
-
function resolvedDocs() {
|
|
150
|
-
try {
|
|
151
|
-
return cachedSubstrateDocs(listAllMemoryDocs, parseSubstrateDoc);
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
return [];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
function dedupeByPhysicalPath(docs) {
|
|
158
|
-
const seen = new Set();
|
|
159
|
-
const out = [];
|
|
160
|
-
for (const doc of docs) {
|
|
161
|
-
const real = realpathOrSelf(doc.path);
|
|
162
|
-
if (seen.has(real))
|
|
163
|
-
continue;
|
|
164
|
-
seen.add(real);
|
|
165
|
-
out.push(doc);
|
|
166
|
-
}
|
|
167
|
-
return out;
|
|
168
|
-
}
|
|
169
|
-
function globMatches(glob, absReadFile, owningRoot) {
|
|
170
|
-
const targets = [absReadFile, basename(absReadFile)];
|
|
171
|
-
if (owningRoot !== null)
|
|
172
|
-
targets.push(relative(owningRoot, absReadFile));
|
|
173
|
-
return targets.some((target) => {
|
|
174
|
-
try {
|
|
175
|
-
return matchesGlob(target, glob);
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
return false;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
function readFileFrontmatter(absReadFile) {
|
|
183
|
-
if (!/\.(md|mdx|markdown)$/i.test(absReadFile))
|
|
184
|
-
return {};
|
|
185
|
-
try {
|
|
186
|
-
return parseFrontmatterGeneric(readText(absReadFile)).data ?? {};
|
|
187
|
-
}
|
|
188
|
-
catch {
|
|
189
|
-
return {};
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
function matchesReadEvent(doc, absReadFile, readFrontmatter) {
|
|
193
|
-
const pathMatch = doc.appliesTo?.some((glob) => globMatches(glob, absReadFile, owningRootOf(doc))) === true;
|
|
194
|
-
const frontmatterMatch = doc.readWhen !== undefined &&
|
|
195
|
-
Object.keys(readFrontmatter).length > 0 &&
|
|
196
|
-
evalCondition(doc.readWhen, readFrontmatter);
|
|
197
|
-
return pathMatch || frontmatterMatch;
|
|
198
|
-
}
|
|
199
|
-
function envelopeName(doc) {
|
|
200
|
-
const displayed = displayName(doc.name);
|
|
201
|
-
if (displayed !== '')
|
|
202
|
-
return displayed;
|
|
203
|
-
const root = owningRootOf(doc);
|
|
204
|
-
return root === null ? doc.name : basename(root);
|
|
205
|
-
}
|
|
206
|
-
function renderDocEnvelope(doc) {
|
|
207
|
-
const rung = doc.fileReadVisibility;
|
|
208
|
-
if (rung === 'none')
|
|
209
|
-
return null;
|
|
210
|
-
let body = '';
|
|
211
|
-
if (rung === 'content')
|
|
212
|
-
body = doc.body.trim();
|
|
213
|
-
else if (rung === 'preview')
|
|
214
|
-
body = previewLine(doc);
|
|
215
|
-
const attrs = `kind="${attr(doc.kind)}" name="${attr(envelopeName(doc))}" src="${attr(disp(doc.path))}"`;
|
|
216
|
-
return body === '' ? `<memory ${attrs} />` : `<memory ${attrs}>\n${body}\n</memory>`;
|
|
217
|
-
}
|
|
218
|
-
function renderCandidates(subject, docs, seen) {
|
|
219
|
-
const rendered = [];
|
|
220
|
-
for (const doc of docs) {
|
|
221
|
-
const real = realpathOrSelf(doc.path);
|
|
222
|
-
if (seen.has(real))
|
|
223
|
-
continue;
|
|
224
|
-
try {
|
|
225
|
-
if (!gatePasses(doc, subject))
|
|
226
|
-
continue;
|
|
227
|
-
const block = renderDocEnvelope(doc);
|
|
228
|
-
if (block === null)
|
|
229
|
-
continue;
|
|
230
|
-
seen.add(real);
|
|
231
|
-
rendered.push(block);
|
|
232
|
-
}
|
|
233
|
-
catch {
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return rendered.length === 0
|
|
238
|
-
? ''
|
|
239
|
-
: `<auto-loaded-context>\n${rendered.join('\n')}\n</auto-loaded-context>`;
|
|
240
|
-
}
|
|
241
|
-
/** Surface docs matched by a successful read tool call using the caller-supplied
|
|
242
|
-
* daemon snapshot subject. */
|
|
243
|
-
export function renderOnReadDocsForSubject(subject, readFilePath, seen = new Set()) {
|
|
244
|
-
const absReadFile = realpathOrSelf(readFilePath);
|
|
245
|
-
const readFrontmatter = readFileFrontmatter(absReadFile);
|
|
246
|
-
const docs = dedupeByPhysicalPath([...enclosingProjectDocs(absReadFile), ...resolvedDocs()])
|
|
247
|
-
.filter((doc) => realpathOrSelf(doc.path) !== absReadFile)
|
|
248
|
-
.filter((doc) => matchesReadEvent(doc, absReadFile, readFrontmatter));
|
|
249
|
-
return renderCandidates(subject, docs, seen);
|
|
250
|
-
}
|
|
251
|
-
/** Workspace boot docs using the snapshot's cwd/profile instead of a canvas
|
|
252
|
-
* lookup. */
|
|
253
|
-
export function renderWorkspaceOpenDocsForSubject(subject, cwd, profileId) {
|
|
254
|
-
let docs;
|
|
255
|
-
try {
|
|
256
|
-
docs = listProjectMemoryDocs(cwd, profileId)
|
|
257
|
-
.map(parseSubstrateDoc)
|
|
258
|
-
.filter((doc) => doc !== null);
|
|
259
|
-
}
|
|
260
|
-
catch {
|
|
261
|
-
return '';
|
|
262
|
-
}
|
|
263
|
-
docs = dedupeByPhysicalPath(docs)
|
|
264
|
-
.filter((doc) => doc.appliesTo?.some((glob) => glob.trim() === '.') === true)
|
|
265
|
-
.sort((a, b) => {
|
|
266
|
-
const aRoot = owningRootOf(a) ?? '';
|
|
267
|
-
const bRoot = owningRootOf(b) ?? '';
|
|
268
|
-
const depth = aRoot.split(sep).filter(Boolean).length - bRoot.split(sep).filter(Boolean).length;
|
|
269
|
-
return depth || aRoot.localeCompare(bRoot) || a.path.localeCompare(b.path);
|
|
270
|
-
});
|
|
271
|
-
return renderCandidates(subject, docs, new Set());
|
|
272
|
-
}
|