0xray 4.0.30 → 4.0.32

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.
Files changed (49) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.mcp.json +8 -0
  3. package/.opencode/skills/orchestrator/SKILL.md +12 -0
  4. package/.xray/features.json +1 -1
  5. package/dist/CHANGELOG.md +17 -0
  6. package/dist/cli/commands/status.d.ts +4 -2
  7. package/dist/cli/commands/status.js +6 -3
  8. package/dist/cli/commands/validate.js +9 -0
  9. package/dist/cli/goggles-status.d.ts +13 -0
  10. package/dist/cli/goggles-status.js +76 -0
  11. package/dist/cli/index.js +41 -2
  12. package/dist/integrations/grok/grok-cli.d.ts +3 -0
  13. package/dist/integrations/grok/grok-cli.js +41 -1
  14. package/dist/integrations/grok/hooks/grok-hook-utils.js +24 -4
  15. package/dist/integrations/grok/hooks/post-tool-use.js +2 -1
  16. package/dist/integrations/grok/hooks/pre-tool-use.js +90 -5
  17. package/dist/integrations/grok/hooks/session-start.js +7 -2
  18. package/dist/integrations/hooks/goggles-mcp.mjs +371 -0
  19. package/dist/integrations/hooks/goggles-pipeline.mjs +632 -0
  20. package/dist/integrations/hooks/goggles-planes.json +28 -0
  21. package/dist/integrations/hooks/plates.cjs +23 -0
  22. package/dist/integrations/hooks/station-hook-runtime.cjs +40 -11
  23. package/dist/integrations/hooks/station-memory-ingest.mjs +3 -0
  24. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  25. package/dist/mcps/orchestrator/config/agent-capabilities.js +7 -0
  26. package/dist/memory-routing/plates.d.ts +1 -1
  27. package/dist/memory-routing/plates.js +5 -0
  28. package/dist/memory-routing/provider-loader.js +2 -0
  29. package/dist/nucleus/thin-dispatch.d.ts +1 -0
  30. package/dist/nucleus/thin-dispatch.js +4 -2
  31. package/dist/skills/orchestrator/SKILL.md +12 -0
  32. package/docs-site/docs/plates/glossary.md +27 -0
  33. package/docs-site/docs/plates/goggles.md +18 -0
  34. package/docs-site/docs/plates/grokbot.md +41 -0
  35. package/docs-site/docs/plates/host-pack.md +32 -0
  36. package/docs-site/docs/plates/house.md +42 -39
  37. package/docs-site/docs/plates/index.md +13 -1
  38. package/docs-site/docs/plates/kits.md +28 -0
  39. package/docs-site/docs/plates/suit.md +40 -0
  40. package/package.json +2 -1
  41. package/scripts/foundry/assert-packed-dist-cli.mjs +9 -0
  42. package/scripts/mjs/run-goggles-mcp.mjs +41 -0
  43. package/scripts/node/bridge-mcp-wiring.cjs +61 -21
  44. package/scripts/node/consumer-install-smoke.mjs +5 -0
  45. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  46. package/src/mcps/orchestrator/config/agent-capabilities.ts +8 -0
  47. package/src/skills/orchestrator/SKILL.md +12 -0
  48. package/vendor/@0xray/repertoire/dist/paths.js +4 -0
  49. package/xray/features.json +1 -1
@@ -17,10 +17,10 @@ const {
17
17
  unlinkSync,
18
18
  writeFileSync,
19
19
  } = require("fs");
20
- const { join } = require("path");
20
+ const { join, resolve } = require("path");
21
21
 
22
22
  const HOOKS_DIR = __dirname;
23
- const { plateStockLine } = require("./plates.cjs");
23
+ const { plateStockLine, recallPlate, stampPlateIfMissing } = require("./plates.cjs");
24
24
 
25
25
  const INTENT_MAX = 240;
26
26
 
@@ -363,7 +363,7 @@ function destLawNameSet(root) {
363
363
  return names;
364
364
  }
365
365
 
366
- /** Drop hangar repo-* and git-slug keywords. Keep factory + stack laws. */
366
+ /** Drop diary slugs. Keep factory, stack, and subject-overlay names. */
367
367
  function pruneKeywordDest(root) {
368
368
  const dest = destSignalsPath(root);
369
369
  if (!dest || !existsSync(dest)) return { removed: 0, kept: 0 };
@@ -376,12 +376,13 @@ function pruneKeywordDest(root) {
376
376
  if (!Array.isArray(data.signals)) return { removed: 0, kept: 0 };
377
377
  const factory = signalNameSet(repertoireDataFile(root, "curated_signals.json"));
378
378
  const stack = signalNameSet(repertoireDataFile(root, "stack-overlay.json"));
379
+ const subject = signalNameSet(repertoireDataFile(root, "subject-overlay.json"));
379
380
  const kept = [];
380
381
  let removed = 0;
381
382
  for (const signal of data.signals) {
382
383
  const name = String((signal && signal.name) || "").trim();
383
384
  if (!name) continue;
384
- const protectedLaw = factory.has(name) || stack.has(name);
385
+ const protectedLaw = factory.has(name) || stack.has(name) || subject.has(name);
385
386
  if (!protectedLaw && (isKeywordDestName(name) || isGenericFieldObservedSignal(signal))) {
386
387
  removed += 1;
387
388
  continue;
@@ -780,20 +781,28 @@ function growDestOnWake(root) {
780
781
  const helper = join(HOOKS_DIR, "station-memory-ingest.mjs");
781
782
  if (!existsSync(helper)) return null;
782
783
  try {
784
+ const dest = destSignalsPath(root);
785
+ const before = countCuratedSignals(dest) || 0;
783
786
  const out = execFileSync(process.execPath, [helper, root, "--grow"], {
784
787
  encoding: "utf8",
785
788
  timeout: 45000,
786
789
  stdio: ["ignore", "pipe", "pipe"],
787
- env: { ...process.env, REPERTOIRE_FIELD_SYNC: "0", REPERTOIRE_DEST_LOCK: "held" },
790
+ env: {
791
+ ...process.env,
792
+ REPERTOIRE_FIELD_SYNC: "0",
793
+ REPERTOIRE_DEST_LOCK: "held",
794
+ REPERTOIRE_SUBJECT_OVERLAY: "0",
795
+ },
788
796
  });
789
797
  const line = String(out).trim().split("\n").filter(Boolean).at(-1) || "{}";
790
798
  const parsed = JSON.parse(line);
791
799
  const pruned = pruneKeywordDest(root);
792
- const destCount = countCuratedSignals(destSignalsPath(root)) || 0;
793
- if (!parsed || typeof parsed !== "object") return { pruned: pruned.removed, destCount };
800
+ const destCount = countCuratedSignals(dest) || 0;
801
+ if (!parsed || typeof parsed !== "object") return { before, pruned: pruned.removed, destCount, after: destCount };
794
802
  const heated = Array.isArray(parsed.heated) ? parsed.heated.length : 0;
795
803
  return {
796
804
  ...parsed,
805
+ before,
797
806
  observed: heated,
798
807
  pruned: pruned.removed,
799
808
  destCount,
@@ -947,8 +956,8 @@ function applyStationHeat(root, host, extra = {}, existing = {}) {
947
956
  const matchText = clipIntent([intent, pickup, approaches].filter(Boolean).join(" "));
948
957
  const git = readGitBrief(root);
949
958
  const planLine = resolveHeatPlan(root, extra, existing);
950
- const repertoireResume =
951
- typeof extra.repertoireResume === "string" ? extra.repertoireResume : buildRepertoireResume(root);
959
+ // A passed string is the previous card. Count the project file after this wake.
960
+ const repertoireResume = buildRepertoireResume(root);
952
961
  const swapBit = hotSwap ? `hot-swap ${hotSwap.from} → ${hotSwap.to}` : `host ${host}`;
953
962
  const intentBit = intent ? `intent: ${intent}` : "intent: (none yet)";
954
963
  const gitBit = git ? `git ${git.branch}@${git.head}` : "git: n/a";
@@ -1085,7 +1094,7 @@ function stationBootNeedsRefresh(existing, root, host) {
1085
1094
  if (!existing || typeof existing !== "object") return true;
1086
1095
  if (host && existing.host && existing.host !== host) return true;
1087
1096
  if (!existing.suit_profile) return true;
1088
- if (existing.workspaceRoot && existing.workspaceRoot !== root) return true;
1097
+ if (existing.workspaceRoot && !sameWorkspaceRoot(existing.workspaceRoot, root)) return true;
1089
1098
  if (!existing.stationLine) return true;
1090
1099
  const liveGit = readGitBrief(root);
1091
1100
  const bootHead = existing.git && existing.git.head ? String(existing.git.head) : "";
@@ -1108,13 +1117,27 @@ function stationDurableHoldsNpm(root) {
1108
1117
  .some((line) => isHoldNpmLine(line));
1109
1118
  }
1110
1119
 
1120
+ function sameWorkspaceRoot(left, right) {
1121
+ if (!left || !right) return false;
1122
+ return resolve(String(left)) === resolve(String(right));
1123
+ }
1124
+
1125
+ function isFooterFragment(line) {
1126
+ const lower = String(line || "").trim().toLowerCase();
1127
+ if (!lower || /^[.]+$/.test(lower)) return true;
1128
+ return STOCK_STATION_FOOTERS.some((footer) => {
1129
+ if (lower.length >= 12 && footer.includes(lower)) return true;
1130
+ return lower.length >= 3 && lower.length < 12 && footer.endsWith(lower);
1131
+ });
1132
+ }
1133
+
1111
1134
  function isStockStationLine(line) {
1112
1135
  const trimmed = String(line || "").trim();
1113
1136
  if (!trimmed) return true;
1114
1137
  if (/^#\s+station\s*$/i.test(trimmed)) return true;
1115
1138
  if (DESIGN_MAP_LINES.includes(trimmed)) return true;
1116
1139
  const lower = trimmed.toLowerCase();
1117
- if (STOCK_STATION_FOOTERS.includes(lower)) return true;
1140
+ if (STOCK_STATION_FOOTERS.includes(lower) || isFooterFragment(trimmed)) return true;
1118
1141
  return STOCK_STATION_PREFIXES.some((prefix) => lower.startsWith(prefix));
1119
1142
  }
1120
1143
 
@@ -1210,6 +1233,12 @@ function writeStationMarkdown(root, fields) {
1210
1233
  try {
1211
1234
  const dir = join(root, ".xray", "state");
1212
1235
  mkdirSync(dir, { recursive: true });
1236
+ try {
1237
+ const plate = recallPlate(fields && fields.intent);
1238
+ if (plate) stampPlateIfMissing(root, plate.id);
1239
+ } catch {
1240
+ /* a missing plate doc must not block the card */
1241
+ }
1213
1242
  const dest = stationMarkdownPath(root);
1214
1243
  const next = mergeStationMarkdown(formatStationMarkdown(fields), readExistingStationMarkdown(root));
1215
1244
  writeFileSync(dest, next);
@@ -24,6 +24,9 @@ const UNREAD_DIARY_FILES = [
24
24
  const root = process.argv[2];
25
25
  const mode = process.argv[3] || 'station';
26
26
 
27
+ // Project dest keeps factory and stack laws. Subject repo-* stay off it.
28
+ process.env.REPERTOIRE_SUBJECT_OVERLAY = '0';
29
+
27
30
  function readRouting(projectRoot) {
28
31
  let routing = { enabled: false, provider: 'null' };
29
32
  const featuresPath = join(projectRoot, '.xray', 'features.json');
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.30",
3
+ "version": "4.0.32",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -8,6 +8,7 @@ import { AGENT_REGISTRY } from "../../../agents/registry.js";
8
8
  import { initializeMemoryRouting } from '../../../memory-routing/index.js';
9
9
  import { getProvider, toMemoryCapabilityMap, fromMemoryCapabilityMap, } from './memory-routing-bridge.js';
10
10
  import { routeSubagent } from '../../../nucleus/autonomy-kernel.js';
11
+ import { scoreAndRoute } from '../../../nucleus/thin-dispatch.js';
11
12
  /** routeSubagent names → AGENT_REGISTRY keys */
12
13
  const ROUTE_AGENT_ALIASES = {
13
14
  'code-review': 'code-reviewer',
@@ -78,6 +79,12 @@ export class AgentCapabilitiesManager {
78
79
  * Select the best agent for a task based on complexity, capabilities, and memory routing.
79
80
  */
80
81
  selectAgentForTask(requiredCapabilities, complexity, operationDescription = '', taskType = '') {
82
+ if (operationDescription.trim()) {
83
+ const routed = scoreAndRoute(operationDescription, {});
84
+ if (routed.memoryRouting?.overridden && this.capabilities.has(routed.agent)) {
85
+ return routed.agent;
86
+ }
87
+ }
81
88
  if (taskType.trim()) {
82
89
  const routed = routeSubagent(taskType);
83
90
  const resolved = resolveRoutedAgent(routed, this.capabilities);
@@ -1,4 +1,4 @@
1
- export declare const PLATE_IDS: readonly ["routing", "governance", "boot", "orchestration", "processor", "reporting", "memory-recall", "house"];
1
+ export declare const PLATE_IDS: readonly ["routing", "governance", "boot", "orchestration", "processor", "reporting", "memory-recall", "house", "goggles", "suit", "kits", "host-pack", "glossary"];
2
2
  export type PlateId = (typeof PLATE_IDS)[number];
3
3
  export interface PlateStamp {
4
4
  id: PlateId;
@@ -14,6 +14,11 @@ export const PLATE_IDS = [
14
14
  'reporting',
15
15
  'memory-recall',
16
16
  'house',
17
+ 'goggles',
18
+ 'suit',
19
+ 'kits',
20
+ 'host-pack',
21
+ 'glossary',
17
22
  ];
18
23
  function isPlateId(value) {
19
24
  return PLATE_IDS.includes(value);
@@ -5,6 +5,8 @@ import { pathToFileURL } from 'node:url';
5
5
  import { frameworkLogger } from '../core/framework-logger.js';
6
6
  import { createMemoryRoutingProvider as createNullProvider } from './null-provider.js';
7
7
  import { validateMemoryRoutingConfig } from './validate-config.js';
8
+ // Opening the organ must not merge subject repo-* back onto the project file.
9
+ process.env.REPERTOIRE_SUBJECT_OVERLAY ??= '0';
8
10
  function sleep(ms) {
9
11
  return new Promise((resolve) => setTimeout(resolve, ms));
10
12
  }
@@ -30,6 +30,7 @@ export declare function scoreAndRoute(operation: string, context: unknown, thres
30
30
  providerId: string;
31
31
  adjustedScore: number;
32
32
  signals: string[];
33
+ overridden: boolean;
33
34
  lessons?: MemorySignalLessons[];
34
35
  };
35
36
  };
@@ -57,7 +57,8 @@ export function routeToAgent(scoreOrLevel, level) {
57
57
  */
58
58
  export function scoreAndRoute(operation, context, thresholds) {
59
59
  const score = scoreComplexity(operation, context, thresholds);
60
- let agent = routeToAgent(score);
60
+ const baseAgent = routeToAgent(score);
61
+ let agent = baseAgent;
61
62
  const provider = ensureMemoryRoutingProviderSync();
62
63
  let memoryRouting;
63
64
  if (provider.id !== "null") {
@@ -67,12 +68,13 @@ export function scoreAndRoute(operation, context, thresholds) {
67
68
  providerId: resolved.context.providerId,
68
69
  adjustedScore: resolved.adjustedScore,
69
70
  signals: resolved.context.matchedSignals,
71
+ overridden: agent !== baseAgent,
70
72
  ...(resolved.context.lessons ? { lessons: resolved.context.lessons } : {}),
71
73
  };
72
74
  const adjustedLevel = getLevelFromScore(resolved.adjustedScore, thresholds);
73
75
  frameworkLogger.log("nucleus-thin-dispatch", "memory-routing", "info", {
74
76
  providerId: resolved.context.providerId,
75
- baseAgent: routeToAgent(score),
77
+ baseAgent,
76
78
  resolvedAgent: agent,
77
79
  baseScore: score.score,
78
80
  adjustedScore: resolved.adjustedScore,
@@ -53,6 +53,18 @@ When `multi_agent_orchestration.lead_dev_mode` is true in `features.json` (defau
53
53
  | Test failures | bug-triage |
54
54
  | Review | code-review |
55
55
 
56
+ ## Goggles
57
+
58
+ The command is `0xray look`. `0xray goggles` is the same organ. A pipe keeps the line card. A terminal shows that card as a pane. Chat seats without hooks use the `goggles` MCP tools `look` and `status_lens`. Same organ.
59
+
60
+ Kind 0 is actuality. It compares the list in the file to the same six names in the code. It speaks only when those lists differ. A match is quiet. It does not read the suit that is running. It is not a plate type.
61
+
62
+ Kind 1 names one plane: dichotomy, syncopate, synthesis, or loop. The lens holds that plane. An action on that plane is quiet. An action on another plane, or on a pipeline drawing, is stopped. A pipeline drawing is not a scope stop. Ground is not a scope stop. Scope, when named, is ecosystem, part, one flow, or one artifact, and an action wider than that scope is stopped. One kind and one scope level at a time. Two planes, calling, ground, and a pipeline name do not arm the lens. `outer` without one plane is `Name one plane.` After 1 is empty. Nothing is picked.
63
+
64
+ `digest` and `triage` return the card already built by `assemblePlane`. The fields are from, digest, plate, entry, exit, files, skills, setup, teardown, and worn. Empty stays empty. The rows are ground, routing, house, boot, governance, memory-recall, orchestration, processor, and reporting. Those nine are not Kind 0. `digest` fills the card. Entry and exit are the plate's input and output box titles when that plate has them. Setup and teardown stay empty unless the row names them. The mill path is `scripts/foundry`. `triage` adds the empty fields and whether the row holds. Zoom after the card is the same ladder: ecosystem, part, one flow, one artifact. One file is one artifact. Several files are not narrowed to a guessed file.
65
+
66
+ The hold lasts for the work that named the plane. It does not stop one tool and then forget. Work that says goggles clears the hold and stays quiet. The suit does not invent the plane.
67
+
56
68
  ## Hooks (rewired, not new MCPs)
57
69
 
58
70
  - **SessionStart** → `session-start.js` boots lead_dev_mode
@@ -0,0 +1,27 @@
1
+ ---
2
+ title: Glossary
3
+ sidebar_label: Glossary
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Glossary
8
+
9
+ What the words mean.
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────────────────────┐
13
+ │ SAY WHAT PEOPLE GET │
14
+ ├────────────────────────────────────────────────────────────┤
15
+ │ suit · what the agent wears │
16
+ │ power · memory, judgment, or payments │
17
+ │ where it runs · the tool you already open │
18
+ │ goggles · it views one plane │
19
+ │ house · shared rules, one board, memory that sticks │
20
+ │ mill · the shop that builds and ships │
21
+ │ plane · one view, not the whole job │
22
+ │ plate · the drawing, not the live run │
23
+ │ grok-bot · the package you install │
24
+ └────────────────────────────────────────────────────────────┘
25
+ ```
26
+
27
+
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Goggles
3
+ sidebar_label: Goggles
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Goggles
8
+
9
+ It views one plane.
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────────────────────┐
13
+ │ GOGGLES │
14
+ ├────────────────────────────────────────────────────────────┤
15
+ │ · it views one plane │
16
+ │ · not every plane at once │
17
+ └────────────────────────────────────────────────────────────┘
18
+ ```
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Grok Bot
3
+ sidebar_label: Grok Bot
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Grok Bot
8
+
9
+ Give your bots a house: shared rules, one board for the work, and memory that sticks.
10
+
11
+ ```
12
+ ┌──────────────────────────────┐ ┌──────────────────────────────┐ ┌──────────────────────────────┐
13
+ │ SUIT · 0xray │ ─── │ HOUSE · grok-bot │ ─── │ WAVEBOARD · grok-bot │
14
+ ├──────────────────────────────┤ ├──────────────────────────────┤ ├──────────────────────────────┤
15
+ │ · rules on every step │ │ · one folder, six headings │ │ · open cards │
16
+ │ · hooks into your AI tools │ │ · who owns what │ │ · one card, one owner │
17
+ │ · wear on, unwear off │ │ · what needs asking first │ │ · done means proof │
18
+ └──────────────────────────────┘ └──────────────────────────────┘ └──────────────────────────────┘
19
+ │ │ │
20
+ │ │ │
21
+ ┌──────────────────────────────┐ ┌──────────────────────────────┐ ┌──────────────────────────────┐
22
+ │ MEMORY · 0xray (repertoire) │ │ DOCTOR · grok-bot │ │ ATTENTION · grok-bot │
23
+ ├──────────────────────────────┤ ├──────────────────────────────┤ ├──────────────────────────────┤
24
+ │ · lessons as named rules │ │ · checks the house │ │ · only what needs you │
25
+ │ · handed back on the job │ │ · fails on leftover examples │ │ · ask-first items wait here │
26
+ │ · ships in the suit │ │ · says House: PASS when set │ │ · read right after the board │
27
+ └──────────────────────────────┘ └──────────────────────────────┘ └──────────────────────────────┘
28
+ │ │ │
29
+ └────────────────────────────────────┼────────────────────────────────────┘
30
+ ┌───────────────┴──────────────┐
31
+ │ STATION · 0xray │
32
+ ├──────────────────────────────┤
33
+ │ · the pickup card │
34
+ │ · read first on every wake │
35
+ │ · then board, then memory │
36
+ └──────────────────────────────┘
37
+
38
+ code links: suit → memory, house → doctor, memory → station. Other lines show reading order only.
39
+ ```
40
+
41
+ stamped · 0xray 4.0.30 · @0xray/grok-bot 0.1.8
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Host Pack
3
+ sidebar_label: Host Pack
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Host Pack
8
+
9
+ Run it in the tool you already open. Same suit. No new app.
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────────────────────┐
13
+ │ WHERE IT RUNS │
14
+ ├────────────────────────────────────────────────────────────┤
15
+ │ · same suit │
16
+ │ · the tool you already open │
17
+ └────────────────────────────────────────────────────────────┘
18
+
19
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
20
+ │ grok-bot │ │ Hermes │ │ OpenCode │
21
+ │ · already runs │ │ · already runs │ │ · already runs │
22
+ └──────────────────┘ └──────────────────┘ └──────────────────┘
23
+
24
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
25
+ │ OpenClaw │ │ Grok CLI │ │ Cursor │
26
+ │ · already runs │ │ · already runs │ │ · already runs │
27
+ └──────────────────┘ └──────────────────┘ └──────────────────┘
28
+
29
+ same suit → the tool you open → powers snap on
30
+ ```
31
+
32
+ These six already run.
@@ -1,50 +1,53 @@
1
1
  ---
2
2
  title: House
3
3
  sidebar_label: House
4
+ plate_type: state flow
4
5
  ---
5
6
 
6
7
  # House
7
8
 
8
- One team, one folder. `grok-bot house init` copies `HOUSE.md`, `WAVEBOARD.md`, and `ATTENTION_STATE.md` into `./house`. It does not copy `EXAMPLE.md`. It refuses when a target file is already there. Doctor reads `HOUSE.md` through `GROK_BOT_HOUSE`, or by walking up when that variable is unset, and FAILs with `house/EXAMPLE.md exists — delete it` when that file is present. A wake reads the station, then the board files in `house/`.
9
+ A state flow plate: the stages a house goes through before doctor says House: PASS.
9
10
 
10
11
  ```
11
- ┌──────────────────────────────────────────────────────────────┐
12
- │ INPUT LAYER │
13
- │ │
14
- │ npx @0xray/grok-bot house init │
15
- │ copies HOUSE.md, WAVEBOARD.md, ATTENTION_STATE.md only │
16
- │ refuses if a target file is already there │
17
- └──────────────────────────────┬───────────────────────────────┘
18
- v
19
- ┌──────────────────────────────┼───────────────────────────────┐
20
- │ PROCESSING LAYER v │
21
- │ │
22
- │ ┌──────────────────────────────────────────────────────┐ │
23
- │ │ HOUSE.md — six headings │ │
24
- │ │ owner · seats · public voice · allowed · ask first │ │
25
- │ │ board: WAVEBOARD.md + ATTENTION_STATE.md │ │
26
- │ │ the owner approves Allowed before it counts │ │
27
- │ └───────────────────────────┬──────────────────────────┘ │
28
- │ v │
29
- │ ┌──────────────────────────────────────────────────────┐ │
30
- │ │ grok-bot doctor │ │
31
- │ │ GROK_BOT_HOUSE, or walk up for house/HOUSE.md │ │
32
- │ │ a set path that is missing warns and does not walk │ │
33
- │ │ a line that starts with (example) fails │ │
34
- │ │ house/EXAMPLE.md exists — delete it │ │
35
- │ └───────────────────────────┬──────────────────────────┘ │
36
- └──────────────────────────────┼───────────────────────────────┘
37
- v
38
- ┌──────────────────────────────┼───────────────────────────────┐
39
- │ OUTPUT LAYER v │
40
- │ │
41
- │ read the station, then house/WAVEBOARD.md │
42
- │ and house/ATTENTION_STATE.md │
43
- │ a missing board file uses templates/house/ │
44
- │ one card, one owner │
45
- │ change the house when the owner says a rule twice │
46
- └──────────────────────────────────────────────────────────────┘
47
-
12
+ ┌──────────────────────────────┐
13
+ │ EMPTY │
14
+ ├──────────────────────────────┤
15
+ │ · no house/ folder yet │
16
+ └──────────────────────────────┘
17
+ │ house init
18
+ v
19
+ ┌──────────────────────────────┐
20
+ │ STARTER FILES COPIED │
21
+ ├──────────────────────────────┤
22
+ │ · copy starter │
23
+ │ · HOUSE.md, WAVEBOARD.md, │
24
+ │ ATTENTION_STATE.md │
25
+ └──────────────────────────────┘
26
+ │
27
+ v
28
+ ┌──────────────────────────────┐
29
+ │ HEADINGS FILLED │ <──────────┐
30
+ ├──────────────────────────────┤ │
31
+ │ · fill six headings │ │
32
+ │ · owner, seats, public voice │ │
33
+ │ allowed, ask first, board │ │
34
+ └──────────────────────────────┘ │
35
+ │ │
36
+ v │
37
+ ┌──────────────────────────────┐ │ not yet
38
+ │ OWNER APPROVES │ │
39
+ ├──────────────────────────────┤ │
40
+ │ · owner approves Allowed │ │
41
+ │ · doctor cannot check this │ │
42
+ └──────────────────────────────┘ │
43
+ │ │
44
+ v │
45
+ ┌──────────────────────────────┐ │
46
+ │ DOCTOR · House: PASS? │ ───────────┘
47
+ ├──────────────────────────────┤
48
+ │ · doctor checks it │
49
+ │ · yes: House: PASS │
50
+ └──────────────────────────────┘
48
51
  ```
49
52
 
50
- stamped · 0xray · @0xray/grok-bot 0.1.7
53
+ stamped · 0xray 4.0.30 · @0xray/grok-bot 0.1.8
@@ -13,4 +13,16 @@ The station card stays the short subsystem table. That table is the index still
13
13
 
14
14
  The markdown file is the source of truth for that stamp. When the pipeline changes, edit the plate. A worn project may hold a copy at `.xray/state/plates/<id>.md`. The copy is written only when that file is missing, so a local edit stays.
15
15
 
16
- [Routing](./routing.md) · [Governance](./governance.md) · [Boot](./boot.md) · [Orchestration](./orchestration.md) · [Processor](./processor.md) · [Reporting](./reporting.md) · [Memory recall](./memory-recall.md) · [House](./house.md)
16
+ Plates have a type. A domain model plate shows how named parts fit. A state flow plate shows the stages one thing goes through.
17
+
18
+ ## Domain model
19
+
20
+ [Goggles](./goggles.md) · [Suit](./suit.md) · [Kits](./kits.md) · [Host Pack](./host-pack.md) · [Glossary](./glossary.md) · [Grok Bot](./grokbot.md)
21
+
22
+ ## State flow
23
+
24
+ [House](./house.md)
25
+
26
+ ## Not yet typed
27
+
28
+ [Routing](./routing.md) · [Governance](./governance.md) · [Boot](./boot.md) · [Orchestration](./orchestration.md) · [Processor](./processor.md) · [Reporting](./reporting.md) · [Memory recall](./memory-recall.md)
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Kits
3
+ sidebar_label: Kits
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Kits
8
+
9
+ Add a power. Memory, judgment, or payments.
10
+
11
+ ```
12
+ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
13
+ │ REPERTOIRE │ │ DYNAMO │ │ CLEARING │
14
+ ├──────────────────────┤ ├──────────────────────┤ ├──────────────────────┤
15
+ │ · it remembers │ │ · yes or no │ │ · you pay │
16
+ │ · the lesson stays │ │ · before it ships │ │ · you get a receipt │
17
+ └──────────────────────┘ └──────────────────────┘ └──────────────────────┘
18
+
19
+ ┌────────────────────────────────────────────────────────────┐
20
+ │ NOT POWERS │
21
+ ├────────────────────────────────────────────────────────────┤
22
+ │ · the team folder │
23
+ │ · the shop that builds │
24
+ │ · where the suit runs │
25
+ └────────────────────────────────────────────────────────────┘
26
+ ```
27
+
28
+ Three. That's the set.
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Suit
3
+ sidebar_label: Suit
4
+ plate_type: domain model
5
+ ---
6
+
7
+ # Suit
8
+
9
+ Give your agent a suit. The rules stay on, you add powers, and it runs in the tool you already open.
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────────────────────┐
13
+ │ SUIT · what it wears │
14
+ ├────────────────────────────────────────────────────────────┤
15
+ │ · the rules stay on │
16
+ │ · you put it on once │
17
+ │ · it builds the factories │
18
+ └────────────────────────────────────────────────────────────┘
19
+ │
20
+ you add powers
21
+ v
22
+ ┌────────────────────────────────────────────────────────────┐
23
+ │ WHERE IT RUNS │
24
+ ├────────────────────────────────────────────────────────────┤
25
+ │ · the tool you already open │
26
+ │ · grok-bot · Hermes · OpenCode │
27
+ │ · OpenClaw · Grok CLI · Cursor │
28
+ └────────────────────────────────────────────────────────────┘
29
+ │
30
+ they snap on
31
+ v
32
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
33
+ │ REPERTOIRE │ │ DYNAMO │ │ CLEARING │
34
+ │ · memory │ │ · judgment │ │ · payments │
35
+ └──────────────────┘ └──────────────────┘ └──────────────────┘
36
+
37
+ goggles views one plane
38
+ ```
39
+
40
+ Same rules in the repo. You are not locked into one app.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.30",
3
+ "version": "4.0.32",
4
4
  "description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
5
5
  "readme": "README.md",
6
6
  "license": "MIT",
@@ -170,6 +170,7 @@
170
170
  "scripts/mjs/verify-temperament-live.mjs",
171
171
  "scripts/mjs/verify-four-floor-compact.mjs",
172
172
  "scripts/mjs/run-repertoire-mcp.mjs",
173
+ "scripts/mjs/run-goggles-mcp.mjs",
173
174
  "scripts/mjs/verify-delegation-gate-core.mjs",
174
175
  "scripts/mjs/delegation-gate-fixture.mjs",
175
176
  "src/opencode/",
@@ -29,8 +29,17 @@ export const REQUIRED_PACK_PATHS = [
29
29
  "dist/integrations/cursor/hooks/pre-compact.sh",
30
30
  "dist/integrations/cursor/hooks/after-file-edit.sh",
31
31
  "dist/integrations/hooks/plates.cjs",
32
+ "dist/integrations/hooks/goggles-pipeline.mjs",
33
+ "dist/integrations/hooks/goggles-planes.json",
34
+ "dist/integrations/hooks/goggles-mcp.mjs",
35
+ "scripts/mjs/run-goggles-mcp.mjs",
32
36
  "docs-site/docs/plates/memory-recall.md",
33
37
  "docs-site/docs/plates/processor.md",
38
+ "docs-site/docs/plates/goggles.md",
39
+ "docs-site/docs/plates/suit.md",
40
+ "docs-site/docs/plates/kits.md",
41
+ "docs-site/docs/plates/host-pack.md",
42
+ "docs-site/docs/plates/glossary.md",
34
43
  ];
35
44
 
36
45
  export function packedFilePaths(files) {