0xray 4.0.32 → 4.0.34
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/.grok-plugin/plugin.json +1 -1
- package/.opencode/agents/api-design.yml +31 -0
- package/.opencode/agents/architect.yml +15 -0
- package/.opencode/agents/architecture-patterns.yml +14 -0
- package/.opencode/agents/auto-format.yml +14 -0
- package/.opencode/agents/backend-engineer.yml +12 -0
- package/.opencode/agents/boot-orchestrator.yml +14 -0
- package/.opencode/agents/bug-triage-specialist.yml +15 -0
- package/.opencode/agents/code-analyzer.yml +12 -0
- package/.opencode/agents/code-reviewer.yml +14 -0
- package/.opencode/agents/content-creator.yml +12 -0
- package/.opencode/agents/database-engineer.yml +12 -0
- package/.opencode/agents/devops-engineer.yml +12 -0
- package/.opencode/agents/framework-compliance-audit.yml +14 -0
- package/.opencode/agents/frontend-engineer.yml +12 -0
- package/.opencode/agents/frontend-ui-ux-engineer.yml +12 -0
- package/.opencode/agents/git-workflow.yml +15 -0
- package/.opencode/agents/growth-strategist.yml +12 -0
- package/.opencode/agents/hermes-agent.yml +12 -0
- package/.opencode/agents/inference-improve.yml +12 -0
- package/.opencode/agents/lint.yml +14 -0
- package/.opencode/agents/log-monitor.yml +12 -0
- package/.opencode/agents/mobile-developer.yml +12 -0
- package/.opencode/agents/model-health-check.yml +12 -0
- package/.opencode/agents/multimodal-looker.yml +12 -0
- package/.opencode/agents/performance-analysis.yml +12 -0
- package/.opencode/agents/performance-engineer.yml +12 -0
- package/.opencode/agents/performance-optimization.yml +12 -0
- package/.opencode/agents/processor-pipeline.yml +14 -0
- package/.opencode/agents/project-analysis.yml +12 -0
- package/.opencode/agents/refactorer.yml +12 -0
- package/.opencode/agents/researcher.yml +12 -0
- package/.opencode/agents/security-auditor.yml +12 -0
- package/.opencode/agents/security-scan.yml +12 -0
- package/.opencode/agents/seo-consultant.yml +12 -0
- package/.opencode/agents/session-management.yml +12 -0
- package/.opencode/agents/state-manager.yml +12 -0
- package/.opencode/agents/storyteller.yml +12 -0
- package/.opencode/agents/strategist.yml +12 -0
- package/.opencode/agents/tech-writer.yml +12 -0
- package/.opencode/agents/testing-best-practices.yml +12 -0
- package/.opencode/agents/testing-lead.yml +12 -0
- package/.opencode/agents/ui-ux-design.yml +12 -0
- package/.opencode/codex.codex +8 -0
- package/.opencode/commands/auto-format.md +99 -0
- package/.opencode/commands/auto-summary-capture.md +90 -0
- package/.opencode/commands/dependency-audit.md +184 -0
- package/.opencode/commands/enforcer-daily-scan.md +137 -0
- package/.opencode/commands/framework-compliance-audit.md +205 -0
- package/.opencode/commands/interactive-validator.md +75 -0
- package/.opencode/commands/job-summary-logger.md +68 -0
- package/.opencode/commands/lint.md +11 -0
- package/.opencode/commands/mode-switch.md +95 -0
- package/.opencode/commands/model-health-check.md +186 -0
- package/.opencode/commands/performance-analysis.md +144 -0
- package/.opencode/commands/pre-commit-introspection.md +185 -0
- package/.opencode/commands/pre-commit-introspection.sh +133 -0
- package/.opencode/commands/security-scan.md +157 -0
- package/.opencode/commands/sisyphus-validation.md +128 -0
- package/.opencode/commands/summary-logger.md +83 -0
- package/.opencode/enforcer-config.json +282 -0
- package/.opencode/skills/orchestrator/SKILL.md +3 -3
- package/.opencode/workflows/post-deployment-audit.yml +123 -0
- package/.xray/features.json +1 -1
- package/dist/CHANGELOG.md +17 -0
- package/dist/cli/goggles-status.js +1 -1
- package/dist/governance/governance-service.js +11 -1
- package/dist/integrations/grok/hooks/grok-hook-utils.js +7 -4
- package/dist/integrations/grok/hooks/pre-tool-use.js +7 -1
- package/dist/integrations/grok/hooks/session-start.js +5 -2
- package/dist/integrations/hooks/goggles-mcp.mjs +3 -36
- package/dist/integrations/hooks/goggles-pipeline.d.mts +2 -0
- package/dist/integrations/hooks/goggles-pipeline.mjs +438 -82
- package/dist/integrations/hooks/goggles-planes.json +23 -0
- package/dist/integrations/hooks/plates.cjs +15 -1
- package/dist/integrations/hooks/station-hook-runtime.cjs +53 -5
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/dist/mcps/orchestrator/config/agent-capabilities.js +5 -0
- package/dist/nucleus/thin-dispatch.d.ts +4 -0
- package/dist/nucleus/thin-dispatch.js +9 -1
- package/dist/skills/orchestrator/SKILL.md +3 -3
- package/package.json +1 -1
- package/scripts/foundry/mint-suit.cjs +6 -1
- package/scripts/node/install-bridges.cjs +24 -7
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/orchestrator/config/agent-capabilities.ts +4 -0
- package/src/skills/orchestrator/SKILL.md +3 -3
- package/xray/features.json +1 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Goggles. Kind 0 name-checks the six outer names.
|
|
3
|
-
*
|
|
3
|
+
* A named plane returns its view. Field pipes fill what they can see.
|
|
4
|
+
* The view keeps every field for the next look.
|
|
4
5
|
* A held plane stays quiet. A leave is denied.
|
|
5
6
|
*/
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
7
9
|
import { dirname, join, resolve } from 'node:path';
|
|
8
10
|
import { fileURLToPath } from 'node:url';
|
|
9
11
|
|
|
@@ -204,10 +206,20 @@ function gogglesAnswer(argv) {
|
|
|
204
206
|
return { text: cards.map((card) => formatCardText(card)).join('\n\n'), cards };
|
|
205
207
|
}
|
|
206
208
|
const planes = acceptedPlanes().filter((name) => lower.includes(name));
|
|
207
|
-
if (planes.length !== 1)
|
|
209
|
+
if (planes.length !== 1) {
|
|
210
|
+
if (!planes.length && cardPlanesNamed(lower).length) {
|
|
211
|
+
const cards = collectCards('digest', lower);
|
|
212
|
+
if (cards && cards.length) {
|
|
213
|
+
return { text: cards.map((card) => formatCardText(card)).join('\n\n'), cards };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return none('');
|
|
217
|
+
}
|
|
208
218
|
const scopes = findScopes(words.filter((word) => word.toLowerCase() !== planes[0]));
|
|
209
219
|
if (scopes.length > 1) return none('');
|
|
210
|
-
|
|
220
|
+
const line = readingLine(planes[0], scopes[0] || '');
|
|
221
|
+
const file = moduleFile(planes[0]);
|
|
222
|
+
return none(file ? `${line} File: ${file}` : line);
|
|
211
223
|
}
|
|
212
224
|
|
|
213
225
|
export function readGoggles(argv) {
|
|
@@ -222,23 +234,17 @@ function cardPlanesNamed(lower) {
|
|
|
222
234
|
return CARD_PLANES.filter((name) => lower.includes(name));
|
|
223
235
|
}
|
|
224
236
|
|
|
225
|
-
function listedFiles(plane
|
|
226
|
-
|
|
227
|
-
if (scope === 'one artifact') return files.length === 1 ? [files[0]] : null;
|
|
228
|
-
const unpathed = Array.isArray(plane.unpathed) ? plane.unpathed : [];
|
|
229
|
-
const parts = files.slice();
|
|
230
|
-
for (const name of unpathed) parts.push(name === 'mill' ? 'mill has no path' : String(name));
|
|
231
|
-
return parts;
|
|
237
|
+
function listedFiles(plane) {
|
|
238
|
+
return Array.isArray(plane.files) ? plane.files.map(String) : [];
|
|
232
239
|
}
|
|
233
240
|
|
|
234
241
|
function cardView(plane, scope, flavor, root) {
|
|
235
|
-
const listed = listedFiles(plane
|
|
236
|
-
if (!listed) return null;
|
|
242
|
+
const listed = listedFiles(plane);
|
|
237
243
|
const view = {
|
|
238
244
|
plane: plane.id,
|
|
239
245
|
flavor,
|
|
240
246
|
scope: scope || '',
|
|
241
|
-
from: plane.id === 'ground' ? '' : 'ground',
|
|
247
|
+
from: plane.id === 'ground' ? '' : (plane.from || 'ground'),
|
|
242
248
|
digest: plane.digest || '',
|
|
243
249
|
plate: plane.plate || '',
|
|
244
250
|
entry: plane.entry || '',
|
|
@@ -248,7 +254,6 @@ function cardView(plane, scope, flavor, root) {
|
|
|
248
254
|
setup: plane.setup || '',
|
|
249
255
|
teardown: plane.teardown || '',
|
|
250
256
|
worn: plane.worn || '',
|
|
251
|
-
narrow: scope === 'one flow' || scope === 'one artifact',
|
|
252
257
|
};
|
|
253
258
|
if (flavor === 'triage') {
|
|
254
259
|
const filled = new Set(filledOf(plane));
|
|
@@ -272,10 +277,7 @@ function formatCardText(view) {
|
|
|
272
277
|
['Teardown', view.teardown],
|
|
273
278
|
['Worn', view.worn],
|
|
274
279
|
];
|
|
275
|
-
|
|
276
|
-
? rows.filter(([key]) => key === 'Plane' || key === 'Digest' || key === 'Files')
|
|
277
|
-
: rows;
|
|
278
|
-
let text = shown.map(([key, value]) => `${key}: ${value}`.trimEnd()).join('\n');
|
|
280
|
+
let text = rows.map(([key, value]) => `${key}: ${value}`.trimEnd()).join('\n');
|
|
279
281
|
if (view.flavor === 'triage') {
|
|
280
282
|
const lines = [];
|
|
281
283
|
if (view.empty.length) lines.push(`Empty: ${view.empty.join(', ')}`);
|
|
@@ -286,23 +288,19 @@ function formatCardText(view) {
|
|
|
286
288
|
}
|
|
287
289
|
|
|
288
290
|
export function formatCardPane(view) {
|
|
289
|
-
const rows = [
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
303
|
-
} else {
|
|
304
|
-
rows.push(['Files', view.files.join(', ')]);
|
|
305
|
-
}
|
|
291
|
+
const rows = [
|
|
292
|
+
['Plane', view.plane],
|
|
293
|
+
['From', view.from],
|
|
294
|
+
['Digest', view.digest],
|
|
295
|
+
['Plate', view.plate],
|
|
296
|
+
['Entry', view.entry],
|
|
297
|
+
['Exit', view.exit],
|
|
298
|
+
['Files', view.files.join(', ')],
|
|
299
|
+
['Skills', view.skills],
|
|
300
|
+
['Setup', view.setup],
|
|
301
|
+
['Teardown', view.teardown],
|
|
302
|
+
['Worn', view.worn],
|
|
303
|
+
];
|
|
306
304
|
if (view.flavor === 'triage') {
|
|
307
305
|
if (Array.isArray(view.empty) && view.empty.length) rows.push(['Empty', view.empty.join(', ')]);
|
|
308
306
|
if (view.exam) rows.push(['', view.exam]);
|
|
@@ -319,20 +317,15 @@ export function formatCardPane(view) {
|
|
|
319
317
|
function collectCards(flavor, lower) {
|
|
320
318
|
const named = cardPlanesNamed(lower);
|
|
321
319
|
const scopes = findScopes(lower.filter((word) => word !== flavor && !named.includes(word)));
|
|
322
|
-
if (
|
|
320
|
+
if (scopes.length > 1) return null;
|
|
323
321
|
const scope = scopes[0] || '';
|
|
324
|
-
if (!named.length && (scope === 'part' || scope === 'one flow' || scope === 'one artifact')) return null;
|
|
325
322
|
const platesDir = findPlatesDir(HERE);
|
|
326
|
-
if (!platesDir) return null;
|
|
327
323
|
const ids = named.length ? named : CARD_PLANES;
|
|
328
|
-
const root =
|
|
324
|
+
const root = sourceRoot(platesDir);
|
|
329
325
|
const cards = [];
|
|
330
326
|
for (const id of ids) {
|
|
331
|
-
const plane =
|
|
332
|
-
|
|
333
|
-
const view = cardView(plane, scope, flavor, root);
|
|
334
|
-
if (!view) return null;
|
|
335
|
-
cards.push(view);
|
|
327
|
+
const plane = growPlane(id, platesDir, stateRoot());
|
|
328
|
+
cards.push(cardView(plane, scope, flavor, root));
|
|
336
329
|
}
|
|
337
330
|
return cards;
|
|
338
331
|
}
|
|
@@ -366,6 +359,45 @@ function boxTitles(line) {
|
|
|
366
359
|
return titles;
|
|
367
360
|
}
|
|
368
361
|
|
|
362
|
+
function flowEnds(body) {
|
|
363
|
+
if (!body || body.includes('INPUT LAYER')) return null;
|
|
364
|
+
const stages = [];
|
|
365
|
+
let title = '';
|
|
366
|
+
let notes = [];
|
|
367
|
+
let open = false;
|
|
368
|
+
for (const line of String(body).split(/\r?\n/)) {
|
|
369
|
+
if (line.includes('┌')) {
|
|
370
|
+
open = true;
|
|
371
|
+
title = '';
|
|
372
|
+
notes = [];
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (!open) continue;
|
|
376
|
+
if (line.includes('└')) {
|
|
377
|
+
if (title) stages.push({ title, notes: notes.slice() });
|
|
378
|
+
open = false;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (!/[A-Za-z]/.test(line)) continue;
|
|
382
|
+
const titles = boxTitles(line);
|
|
383
|
+
if (titles.length && !title) {
|
|
384
|
+
title = titles.join(' ');
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const note = line.replace(/[│|]/g, ' ').replace(/^[\s·.-]+/, '').trim();
|
|
388
|
+
if (note) notes.push(note);
|
|
389
|
+
}
|
|
390
|
+
if (stages.length < 2) return null;
|
|
391
|
+
const first = stages[0];
|
|
392
|
+
const last = stages[stages.length - 1];
|
|
393
|
+
return {
|
|
394
|
+
entry: first.title,
|
|
395
|
+
exit: last.title,
|
|
396
|
+
setup: first.notes.join(' '),
|
|
397
|
+
teardown: last.notes.join(' '),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
369
401
|
function doorsOf(body) {
|
|
370
402
|
let layer = '';
|
|
371
403
|
let want = false;
|
|
@@ -433,40 +465,336 @@ export function filledOf(plane) {
|
|
|
433
465
|
return FIELD_ORDER.filter((name) => flags[name]);
|
|
434
466
|
}
|
|
435
467
|
|
|
468
|
+
function plateSource(id, platesDir) {
|
|
469
|
+
if (!platesDir || id === 'ground') return { body: '', path: '' };
|
|
470
|
+
const abs = join(platesDir, `${id}.md`);
|
|
471
|
+
if (!existsSync(abs)) return { body: '', path: '' };
|
|
472
|
+
return {
|
|
473
|
+
body: readFileSync(abs, 'utf8'),
|
|
474
|
+
path: join('docs-site', 'docs', 'plates', `${id}.md`),
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function sectionOf(body, title) {
|
|
479
|
+
if (!body) return '';
|
|
480
|
+
const lines = stripFrontmatter(body).split(/\r?\n/);
|
|
481
|
+
const heading = new RegExp(`^#{1,3}\\s+${title}\\s*$`, 'i');
|
|
482
|
+
let on = false;
|
|
483
|
+
const prose = [];
|
|
484
|
+
for (const line of lines) {
|
|
485
|
+
if (heading.test(line)) {
|
|
486
|
+
on = true;
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (!on) continue;
|
|
490
|
+
if (/^#{1,3}\s+/.test(line) || line.startsWith('```')) break;
|
|
491
|
+
if (!line.trim()) {
|
|
492
|
+
if (prose.length) break;
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
prose.push(line.trim());
|
|
496
|
+
}
|
|
497
|
+
return prose.join(' ');
|
|
498
|
+
}
|
|
499
|
+
|
|
436
500
|
export function assemblePlane(id, platesDir) {
|
|
437
501
|
const extra = overlayTable()[id] || {};
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
if (!existsSync(abs)) return null;
|
|
444
|
-
const raw = readFileSync(abs, 'utf8');
|
|
445
|
-
plate = join('docs-site', 'docs', 'plates', `${id}.md`);
|
|
446
|
-
if (!digest) digest = takeOf(stripFrontmatter(raw));
|
|
447
|
-
doors = doorsOf(raw);
|
|
448
|
-
}
|
|
449
|
-
if (!digest) return null;
|
|
502
|
+
const src = plateSource(id, platesDir);
|
|
503
|
+
const doors = src.body ? doorsOf(src.body) : { entry: null, exit: null };
|
|
504
|
+
const flow = src.body ? flowEnds(src.body) : null;
|
|
505
|
+
const digest = extra.digest || (src.body ? takeOf(stripFrontmatter(src.body)) : '');
|
|
506
|
+
const files = Array.isArray(extra.files) ? extra.files.map(String) : [];
|
|
450
507
|
return {
|
|
451
508
|
id,
|
|
452
509
|
digest,
|
|
453
|
-
plate,
|
|
454
|
-
entry: extra.entry || doors.entry ||
|
|
455
|
-
exit: extra.exit || doors.exit ||
|
|
510
|
+
plate: src.path,
|
|
511
|
+
entry: extra.entry || doors.entry || (flow && flow.entry) || '',
|
|
512
|
+
exit: extra.exit || doors.exit || (flow && flow.exit) || '',
|
|
456
513
|
entryIsMark: Boolean(extra.entry),
|
|
457
514
|
exitIsMark: Boolean(extra.exit),
|
|
458
|
-
files
|
|
515
|
+
files,
|
|
459
516
|
unpathed: extra.unpathed || null,
|
|
460
|
-
skills: extra.skills ||
|
|
461
|
-
setup: extra.setup ||
|
|
462
|
-
teardown: extra.teardown ||
|
|
463
|
-
worn: extra.worn ||
|
|
517
|
+
skills: extra.skills || '',
|
|
518
|
+
setup: extra.setup || sectionOf(src.body, 'Setup') || (flow && flow.setup) || '',
|
|
519
|
+
teardown: extra.teardown || sectionOf(src.body, 'Teardown') || (flow && flow.teardown) || '',
|
|
520
|
+
worn: extra.worn || '',
|
|
521
|
+
clues: cluesOf(src.body),
|
|
464
522
|
mark: extra.mark || null,
|
|
465
523
|
wornMark: extra.wornMark || null,
|
|
466
524
|
pick: extra.pick || null,
|
|
467
525
|
};
|
|
468
526
|
}
|
|
469
527
|
|
|
528
|
+
const VIEW_KEYS = ['from', 'digest', 'plate', 'entry', 'exit', 'files', 'skills', 'setup', 'teardown', 'worn'];
|
|
529
|
+
|
|
530
|
+
function stateRoot() {
|
|
531
|
+
const env = process.env.GOGGLES_ROOT;
|
|
532
|
+
if (typeof env === 'string' && env.trim() && env.trim() !== '.') return resolve(env.trim());
|
|
533
|
+
return process.cwd();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function sourceRoot(platesDir) {
|
|
537
|
+
return platesDir ? repoRootFrom(platesDir) : stateRoot();
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function viewsPath(root) {
|
|
541
|
+
return join(root, '.xray', 'state', 'goggles-views.json');
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function loadViews(root) {
|
|
545
|
+
try {
|
|
546
|
+
const data = JSON.parse(readFileSync(viewsPath(root), 'utf8'));
|
|
547
|
+
return data && typeof data === 'object' && !Array.isArray(data) ? data : {};
|
|
548
|
+
} catch {
|
|
549
|
+
return {};
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function saveViews(root, views) {
|
|
554
|
+
const file = viewsPath(root);
|
|
555
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
556
|
+
writeFileSync(file, `${JSON.stringify(views, null, 2)}\n`);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function cluesOf(body) {
|
|
560
|
+
if (!body) return [];
|
|
561
|
+
const clues = [];
|
|
562
|
+
for (const match of String(body).matchAll(/`([^`]{4,80})`/g)) clues.push(match[1]);
|
|
563
|
+
for (const line of String(body).split(/\r?\n/)) {
|
|
564
|
+
if (!line.includes('│')) continue;
|
|
565
|
+
for (const title of boxTitles(line)) {
|
|
566
|
+
if (title.length >= 8 && title.length <= 60) clues.push(title);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return clues;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const sourceCache = new Map();
|
|
573
|
+
|
|
574
|
+
function sourceTexts(root) {
|
|
575
|
+
if (sourceCache.has(root)) return sourceCache.get(root);
|
|
576
|
+
const out = [];
|
|
577
|
+
const walk = (dir, depth) => {
|
|
578
|
+
if (depth > 8) return;
|
|
579
|
+
let entries = [];
|
|
580
|
+
try {
|
|
581
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
582
|
+
} catch {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
for (const entry of entries) {
|
|
586
|
+
if (entry.name === 'node_modules' || entry.name === '__tests__' || entry.name === 'dist') continue;
|
|
587
|
+
const abs = join(dir, entry.name);
|
|
588
|
+
if (entry.isDirectory()) {
|
|
589
|
+
walk(abs, depth + 1);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
if (!/\.(ts|mjs|cjs)$/.test(entry.name) || entry.name.endsWith('.test.ts')) continue;
|
|
593
|
+
try {
|
|
594
|
+
out.push({ rel: abs.slice(root.length + 1), text: readFileSync(abs, 'utf8') });
|
|
595
|
+
} catch {
|
|
596
|
+
/* unreadable source is not a plane file */
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
walk(join(root, 'src'), 0);
|
|
601
|
+
sourceCache.set(root, out);
|
|
602
|
+
return out;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function fileFromClues(clues, root, planeId) {
|
|
606
|
+
const texts = sourceTexts(root);
|
|
607
|
+
const votes = new Map();
|
|
608
|
+
for (const clue of clues) {
|
|
609
|
+
const hits = [];
|
|
610
|
+
for (const file of texts) {
|
|
611
|
+
if (!file.text.includes(clue)) continue;
|
|
612
|
+
hits.push(file.rel);
|
|
613
|
+
if (hits.length > 8) break;
|
|
614
|
+
}
|
|
615
|
+
if (!hits.length || hits.length > 8) continue;
|
|
616
|
+
const weight = 9 - hits.length;
|
|
617
|
+
for (const rel of hits) votes.set(rel, (votes.get(rel) || 0) + weight);
|
|
618
|
+
}
|
|
619
|
+
const token = String(planeId || '').split('-')[0].toLowerCase();
|
|
620
|
+
const named = token ? [...votes.keys()].filter((rel) => rel.toLowerCase().includes(token)) : [];
|
|
621
|
+
const pool = new Set(named.length ? named : [...votes.keys()]);
|
|
622
|
+
let best = '';
|
|
623
|
+
let bestRank = -1;
|
|
624
|
+
for (const [rel, score] of votes) {
|
|
625
|
+
if (!pool.has(rel)) continue;
|
|
626
|
+
let rank = score * 10;
|
|
627
|
+
if (token && rel.toLowerCase().includes(token)) rank += 20;
|
|
628
|
+
if (rel.startsWith('src/cli/')) rank -= 3;
|
|
629
|
+
if (rank > bestRank || (rank === bestRank && rel.length < best.length)) {
|
|
630
|
+
best = rel;
|
|
631
|
+
bestRank = rank;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return best;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function skillFor(id, root) {
|
|
638
|
+
const dir = join(root, 'src', 'skills');
|
|
639
|
+
if (!existsSync(dir)) return '';
|
|
640
|
+
let names = [];
|
|
641
|
+
try {
|
|
642
|
+
names = readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
643
|
+
} catch {
|
|
644
|
+
return '';
|
|
645
|
+
}
|
|
646
|
+
const hit = names.filter((name) => name === id || name.startsWith(`${id}-`));
|
|
647
|
+
if (hit.length !== 1) return '';
|
|
648
|
+
const rel = join('src', 'skills', hit[0], 'SKILL.md');
|
|
649
|
+
return existsSync(join(root, rel)) ? rel : '';
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function mappedFile(name) {
|
|
653
|
+
try {
|
|
654
|
+
const data = JSON.parse(readFileSync(planesFile(), 'utf8'));
|
|
655
|
+
const entry = data[name];
|
|
656
|
+
if (!entry || typeof entry !== 'object') return '';
|
|
657
|
+
if (typeof entry.file === 'string' && entry.file) return entry.file;
|
|
658
|
+
} catch {
|
|
659
|
+
return '';
|
|
660
|
+
}
|
|
661
|
+
return '';
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function moduleFile(name) {
|
|
665
|
+
const mapped = mappedFile(name);
|
|
666
|
+
if (mapped) return mapped;
|
|
667
|
+
const platesDir = findPlatesDir(HERE);
|
|
668
|
+
const root = sourceRoot(platesDir);
|
|
669
|
+
const hit = sourceTexts(root).find((file) => file.rel.endsWith(`/${name}.ts`) || file.rel.endsWith(`/${name}.mjs`));
|
|
670
|
+
return hit ? hit.rel : '';
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function hintLine(name) {
|
|
674
|
+
const cards = lookCards(['digest', name]);
|
|
675
|
+
const files = cards && cards[0] && Array.isArray(cards[0].files) ? cards[0].files : [];
|
|
676
|
+
return files.length ? `${name}: ${files.join(', ')}` : '';
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export function suitHint(text) {
|
|
680
|
+
const words = intentWords(text);
|
|
681
|
+
const named = CARD_PLANES.filter((name) => words.includes(name));
|
|
682
|
+
if (!named.length) return lookVerb(words) ? 'Name one plane.' : '';
|
|
683
|
+
return named.map(hintLine).filter(Boolean).join('\n');
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const DEEP_SEARCH = /search_codebase|find_implementation|get_documentation/i;
|
|
687
|
+
|
|
688
|
+
function researchCall(toolName, text) {
|
|
689
|
+
const tool = String(toolName || '');
|
|
690
|
+
const spoken = String(text || '');
|
|
691
|
+
if (/researcher|explorer|deep[- ]?research/i.test(tool) || DEEP_SEARCH.test(tool)) return true;
|
|
692
|
+
return /bash|shell/i.test(tool) && (/researcher|explorer|deep[- ]?research/i.test(spoken) || DEEP_SEARCH.test(spoken));
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/** One plane: the files the suit continues with. A look with no plane stops. Two planes stay quiet. */
|
|
696
|
+
export function lensPlane(text) {
|
|
697
|
+
const hint = suitHint(String(text || ''));
|
|
698
|
+
if (hint === 'Name one plane.') return { stop: true, files: [] };
|
|
699
|
+
if (!hint || hint.includes('\n')) return { stop: false, files: [] };
|
|
700
|
+
const mark = hint.indexOf(': ');
|
|
701
|
+
if (mark < 0) return { stop: false, files: [] };
|
|
702
|
+
const files = hint.slice(mark + 2).split(',').map((part) => part.trim()).filter(Boolean);
|
|
703
|
+
return { stop: false, files };
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function lensPage(root, names) {
|
|
707
|
+
if (!names.length) return 'Name one plane.';
|
|
708
|
+
const platesDir = findPlatesDir(HERE);
|
|
709
|
+
const parts = [];
|
|
710
|
+
for (const id of names) {
|
|
711
|
+
const plane = growPlane(id, platesDir, root);
|
|
712
|
+
parts.push(formatCardText(cardView(plane, '', 'digest', sourceRoot(platesDir))));
|
|
713
|
+
}
|
|
714
|
+
return parts.join('\n\n');
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
function stampPlane(root, id) {
|
|
718
|
+
try {
|
|
719
|
+
const plates = createRequire(import.meta.url)('./plates.cjs');
|
|
720
|
+
if (!plates.PLATE_IDS.includes(id)) return;
|
|
721
|
+
plates.stampPlateIfMissing(root, id);
|
|
722
|
+
} catch {
|
|
723
|
+
/* a missed stamp must not fail the stop */
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/** A search stays stopped. The next move is the file on the lens, not the same search again. */
|
|
728
|
+
export function lensBeforeResearch(root, toolName, text) {
|
|
729
|
+
const spoken = String(text || '');
|
|
730
|
+
if (!researchCall(toolName, spoken)) return null;
|
|
731
|
+
const names = CARD_PLANES.filter((name) => intentWords(spoken).includes(name));
|
|
732
|
+
if (names.length === 1) stampPlane(root, names[0]);
|
|
733
|
+
return { gate: 'lens', decision: 'deny', reason: lensPage(root, names) };
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function seenFields(plane, root) {
|
|
737
|
+
const files = Array.isArray(plane.files) ? plane.files.slice() : [];
|
|
738
|
+
let worn = plane.worn || '';
|
|
739
|
+
if (!files.length && Array.isArray(plane.unpathed) && plane.unpathed.includes('mill')) {
|
|
740
|
+
if (existsSync(join(root, 'scripts', 'foundry'))) files.push('scripts/foundry');
|
|
741
|
+
}
|
|
742
|
+
if (!files.length && Array.isArray(plane.clues) && plane.clues.length) {
|
|
743
|
+
const found = fileFromClues(plane.clues, root, plane.id);
|
|
744
|
+
if (found) files.push(found);
|
|
745
|
+
}
|
|
746
|
+
let skills = plane.skills || '';
|
|
747
|
+
if (!skills) skills = skillFor(plane.id, root);
|
|
748
|
+
if (!worn) {
|
|
749
|
+
for (const file of files) {
|
|
750
|
+
if (!file.startsWith('src/')) continue;
|
|
751
|
+
let rel = file.slice(4);
|
|
752
|
+
if (rel.endsWith('.ts')) rel = rel.replace(/\.ts$/, '.js');
|
|
753
|
+
else if (!/\.(cjs|mjs|js)$/.test(rel)) continue;
|
|
754
|
+
const next = `dist/${rel}`;
|
|
755
|
+
if (existsSync(join(root, next))) {
|
|
756
|
+
worn = next;
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return {
|
|
762
|
+
from: plane.id === 'ground' ? '' : 'ground',
|
|
763
|
+
digest: plane.digest || '',
|
|
764
|
+
plate: plane.plate || '',
|
|
765
|
+
entry: plane.entry || '',
|
|
766
|
+
exit: plane.exit || '',
|
|
767
|
+
files,
|
|
768
|
+
skills,
|
|
769
|
+
setup: plane.setup || '',
|
|
770
|
+
teardown: plane.teardown || '',
|
|
771
|
+
worn,
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
function kept(stored, seen, key) {
|
|
776
|
+
if (key === 'files') {
|
|
777
|
+
if (Array.isArray(seen.files) && seen.files.length) return seen.files.map(String);
|
|
778
|
+
return Array.isArray(stored.files) ? stored.files.map(String) : [];
|
|
779
|
+
}
|
|
780
|
+
if (seen[key]) return seen[key];
|
|
781
|
+
return stored[key] || '';
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
export function growPlane(id, platesDir, root) {
|
|
785
|
+
const seen = seenFields(assemblePlane(id, platesDir), sourceRoot(platesDir));
|
|
786
|
+
const views = loadViews(root);
|
|
787
|
+
const stored = views[id] && typeof views[id] === 'object' ? views[id] : {};
|
|
788
|
+
const grown = { id };
|
|
789
|
+
for (const key of VIEW_KEYS) grown[key] = kept(stored, seen, key);
|
|
790
|
+
if (id === 'ground') grown.from = stored.from || '';
|
|
791
|
+
views[id] = {};
|
|
792
|
+
for (const key of VIEW_KEYS) views[id][key] = grown[key];
|
|
793
|
+
saveViews(root, views);
|
|
794
|
+
const base = assemblePlane(id, platesDir);
|
|
795
|
+
return { ...base, ...grown };
|
|
796
|
+
}
|
|
797
|
+
|
|
470
798
|
function repoRootFrom(platesDir) {
|
|
471
799
|
return dirname(dirname(dirname(platesDir)));
|
|
472
800
|
}
|
|
@@ -498,26 +826,39 @@ function fileHas(root, rel, mark) {
|
|
|
498
826
|
}
|
|
499
827
|
|
|
500
828
|
|
|
501
|
-
function
|
|
829
|
+
function factoryName(rel) {
|
|
830
|
+
return rel.startsWith('src/') || rel.startsWith('grok-bot/');
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function wornHolds(plane, root) {
|
|
834
|
+
if (!plane.worn || !existsSync(join(root, plane.worn))) return false;
|
|
835
|
+
if (!plane.wornMark) return true;
|
|
836
|
+
return fileHas(root, plane.worn, plane.wornMark);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
export function examinePlane(plane, root) {
|
|
502
840
|
const files = Array.isArray(plane.files) ? plane.files : [];
|
|
503
841
|
const checkable = files.length > 0 || plane.skills || plane.worn;
|
|
504
842
|
if (!checkable) return drawing();
|
|
843
|
+
const held = wornHolds(plane, root);
|
|
844
|
+
if (plane.worn && !held) {
|
|
845
|
+
return drift(`the worn build is not ${files[0] || plane.worn}`);
|
|
846
|
+
}
|
|
505
847
|
for (const rel of files) {
|
|
506
|
-
if (
|
|
848
|
+
if (existsSync(join(root, rel))) continue;
|
|
849
|
+
if (held && factoryName(rel)) continue;
|
|
850
|
+
return drift(`${rel} is not there`);
|
|
507
851
|
}
|
|
508
|
-
if (plane.mark && !fileHas(root, files[0], plane.mark)) {
|
|
852
|
+
if (plane.mark && files[0] && existsSync(join(root, files[0])) && !fileHas(root, files[0], plane.mark)) {
|
|
509
853
|
return drift(`${plane.mark} is not in ${files[0]}`);
|
|
510
854
|
}
|
|
511
|
-
if (plane.
|
|
512
|
-
return drift(`the worn build is not ${files[0] || plane.worn}`);
|
|
513
|
-
}
|
|
514
|
-
if (plane.skills && !existsSync(join(root, plane.skills))) {
|
|
855
|
+
if (plane.skills && !existsSync(join(root, plane.skills)) && !(held && factoryName(plane.skills))) {
|
|
515
856
|
return drift(`${plane.skills} is not there`);
|
|
516
857
|
}
|
|
517
|
-
if (plane.entryIsMark && plane.entry && files[0] && !fileHas(root, files[0], plane.entry)) {
|
|
858
|
+
if (plane.entryIsMark && plane.entry && files[0] && existsSync(join(root, files[0])) && !fileHas(root, files[0], plane.entry)) {
|
|
518
859
|
return drift(`${plane.entry} is not in ${files[0]}`);
|
|
519
860
|
}
|
|
520
|
-
if (plane.exitIsMark && plane.exit && files[0] && !fileHas(root, files[0], plane.exit)) {
|
|
861
|
+
if (plane.exitIsMark && plane.exit && files[0] && existsSync(join(root, files[0])) && !fileHas(root, files[0], plane.exit)) {
|
|
521
862
|
return drift(`${plane.exit} is not in ${files[0]}`);
|
|
522
863
|
}
|
|
523
864
|
return holds();
|
|
@@ -535,8 +876,8 @@ function isGogglesWork(text) {
|
|
|
535
876
|
|
|
536
877
|
|
|
537
878
|
export function cardStop(root, toolName, text, paths = []) {
|
|
538
|
-
const
|
|
539
|
-
if (isGogglesWork(
|
|
879
|
+
const spoken = String(text || '');
|
|
880
|
+
if (spoken.length <= 200 && isGogglesWork(spoken) && !(paths || []).some((item) => /goggles/i.test(String(item)))) {
|
|
540
881
|
clearReading(root);
|
|
541
882
|
clearCardLine(root);
|
|
542
883
|
return null;
|
|
@@ -574,15 +915,21 @@ function intentWords(text) {
|
|
|
574
915
|
return String(text || '').toLowerCase().split(/[^a-z0-9-]+/).filter(Boolean);
|
|
575
916
|
}
|
|
576
917
|
|
|
918
|
+
function lookVerb(words) {
|
|
919
|
+
return words.includes('look') || words.includes('name');
|
|
920
|
+
}
|
|
921
|
+
|
|
577
922
|
export function handCard(root, intent) {
|
|
578
923
|
try {
|
|
579
|
-
clearCardLine(root);
|
|
580
924
|
const text = String(intent || '');
|
|
581
|
-
|
|
925
|
+
const words = intentWords(text);
|
|
926
|
+
if (isGogglesWork(text) && text.length <= 200) {
|
|
582
927
|
clearReading(root);
|
|
928
|
+
clearCardLine(root);
|
|
583
929
|
return null;
|
|
584
930
|
}
|
|
585
|
-
|
|
931
|
+
if (!lookVerb(words)) return null;
|
|
932
|
+
clearCardLine(root);
|
|
586
933
|
const looked = readGoggles(words);
|
|
587
934
|
if (looked.text.startsWith('Actuality. Drift')) {
|
|
588
935
|
saveReading(root, { drift: looked.text });
|
|
@@ -615,14 +962,23 @@ export function lensPath(root) {
|
|
|
615
962
|
|
|
616
963
|
|
|
617
964
|
export function maintainLens(root) {
|
|
618
|
-
const
|
|
965
|
+
const drift = actualityLine();
|
|
966
|
+
const text = drift || 'quiet (match)';
|
|
619
967
|
mkdirSync(dirname(lensPath(root)), { recursive: true });
|
|
620
968
|
writeFileSync(lensPath(root), `${text}\n`);
|
|
621
|
-
return ok(
|
|
969
|
+
return ok(drift);
|
|
622
970
|
}
|
|
623
971
|
|
|
624
972
|
|
|
625
|
-
|
|
973
|
+
function sameInvoked(argvPath, modulePath) {
|
|
974
|
+
try {
|
|
975
|
+
return realpathSync(argvPath) === realpathSync(modulePath);
|
|
976
|
+
} catch {
|
|
977
|
+
return resolve(argvPath) === resolve(modulePath);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const isMain = Boolean(process.argv[1]) && sameInvoked(process.argv[1], fileURLToPath(import.meta.url));
|
|
626
982
|
if (isMain) {
|
|
627
983
|
const answered = gogglesAnswer(process.argv.slice(2));
|
|
628
984
|
const pane = process.stdout.isTTY && Array.isArray(answered.cards) && answered.cards.length > 0;
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
],
|
|
16
16
|
"skills": "SKILLS.md"
|
|
17
17
|
},
|
|
18
|
+
"synthesis": {
|
|
19
|
+
"file": "src/nucleus/synthesis.ts"
|
|
20
|
+
},
|
|
18
21
|
"routing": {
|
|
19
22
|
"files": ["src/nucleus/thin-dispatch.ts"],
|
|
20
23
|
"worn": "dist/nucleus/thin-dispatch.js",
|
|
@@ -24,5 +27,25 @@
|
|
|
24
27
|
},
|
|
25
28
|
"house": {
|
|
26
29
|
"files": ["grok-bot/lib/seat-doctor.cjs"]
|
|
30
|
+
},
|
|
31
|
+
"boot": {
|
|
32
|
+
"files": ["src/core/boot-orchestrator.ts"],
|
|
33
|
+
"skills": "src/skills/boot-orchestrator/SKILL.md"
|
|
34
|
+
},
|
|
35
|
+
"governance": {
|
|
36
|
+
"files": ["src/governance/governance-service.ts"]
|
|
37
|
+
},
|
|
38
|
+
"memory-recall": {
|
|
39
|
+
"files": ["src/integrations/hooks/plates.cjs"]
|
|
40
|
+
},
|
|
41
|
+
"orchestration": {
|
|
42
|
+
"files": ["src/mcps/orchestrator/server.ts"]
|
|
43
|
+
},
|
|
44
|
+
"processor": {
|
|
45
|
+
"files": ["src/processors/processor-manager.ts"],
|
|
46
|
+
"skills": "src/skills/processor-pipeline/SKILL.md"
|
|
47
|
+
},
|
|
48
|
+
"reporting": {
|
|
49
|
+
"files": ["src/reporting/framework-reporting-system.ts"]
|
|
27
50
|
}
|
|
28
51
|
}
|