0xray 4.0.18 → 4.0.19

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 (65) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.xray/features.json +1 -1
  3. package/dist/CHANGELOG.md +12 -0
  4. package/dist/integrations/hooks/station-hook-runtime.cjs +6 -3
  5. package/dist/integrations/hooks/station-memory-match.mjs +8 -8
  6. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  7. package/package.json +1 -1
  8. package/scripts/node/consumer-install-smoke.mjs +3 -3
  9. package/scripts/node/wear-vendored-repertoire.cjs +39 -1
  10. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  11. package/vendor/@0xray/repertoire/AGENTS.md +8 -2
  12. package/vendor/@0xray/repertoire/README.md +35 -8
  13. package/vendor/@0xray/repertoire/data/stack-overlay.json +750 -0
  14. package/vendor/@0xray/repertoire/data/subject-overlay.json +297 -0
  15. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +36 -1
  16. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -1
  17. package/vendor/@0xray/repertoire/dist/RepertoireService.js +108 -18
  18. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -1
  19. package/vendor/@0xray/repertoire/dist/index.d.ts +3 -1
  20. package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -1
  21. package/vendor/@0xray/repertoire/dist/index.js +3 -1
  22. package/vendor/@0xray/repertoire/dist/index.js.map +1 -1
  23. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +4 -0
  24. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -1
  25. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +15 -1
  26. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -1
  27. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +22 -8
  28. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -1
  29. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +56 -5
  30. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -1
  31. package/vendor/@0xray/repertoire/dist/mcp/server.js +8 -13
  32. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -1
  33. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -1
  34. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +24 -7
  35. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -1
  36. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -1
  37. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +2 -1
  38. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -1
  39. package/vendor/@0xray/repertoire/dist/paths.d.ts +65 -2
  40. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -1
  41. package/vendor/@0xray/repertoire/dist/paths.js +377 -6
  42. package/vendor/@0xray/repertoire/dist/paths.js.map +1 -1
  43. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -1
  44. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +6 -8
  45. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -1
  46. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +20 -2
  47. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -1
  48. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +121 -8
  49. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -1
  50. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +2 -1
  51. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -1
  52. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +21 -3
  53. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -1
  54. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts +40 -0
  55. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts.map +1 -0
  56. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js +89 -0
  57. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js.map +1 -0
  58. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -1
  59. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +1 -0
  60. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -1
  61. package/vendor/@0xray/repertoire/dist/types.d.ts +5 -0
  62. package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -1
  63. package/vendor/@0xray/repertoire/package.json +4 -2
  64. package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +2 -2
  65. package/xray/features.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.18",
3
+ "version": "4.0.19",
4
4
  "description": "0xRay suit for Grok, Hermes, OpenClaw, OpenCode: mill+inspect, Codex, 7 MCP servers. Costume 45/42 is opt-in foundry, not the default wear.",
5
5
  "author": {
6
6
  "name": "0xRay AI",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.18",
3
+ "version": "4.0.19",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",
package/dist/CHANGELOG.md CHANGED
@@ -7,6 +7,7 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
7
7
  ## [Unreleased]
8
8
 
9
9
  ### ✨ Features
10
+ - **Vendored Repertoire 0.2.5** — `vendor/@0xray/repertoire` is the published 0.2.5 package (overlays included). Wear replaces an older leftover in `node_modules`. A newer user-installed copy is left alone. Boot reads worn `node_modules`, then vendor, then a sibling checkout last. Repertoire stays optional (`enabled: false` + `provider: repertoire`); Station is the memory when it is off.
10
11
  - **Cursor fifth wear** — `install-bridges.cjs` fastens project `.cursor/hooks.json` (preToolUse / preCompact / afterFileEdit) so Cursor Cloud heats Station and gates tools. Leaves an existing file alone. Not a fifth chat TUI. No new MCP/skill surface. Pack gate (`REQUIRED_PACK_PATHS`) now requires `dist/integrations/cursor/hooks/{hooks.json,pre-tool-use.js,pre-compact.js,after-file-edit.js,cursor-hook-utils.js,cursor-usage-receipt.js}` so a published tarball cannot ship a dead consumer command. `preToolUse` / `afterFileEdit` rewrite the card when git HEAD or Repertoire count diverges — Ticket / Durable / Seed stay. OP-PROC stays in the hook, not on Station.
11
12
 
12
13
  ### 📚 Documentation
@@ -34,6 +35,17 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
34
35
 
35
36
  ---
36
37
 
38
+ ## [4.0.19] - 2026-09-22
39
+
40
+ ### ✨ Features
41
+ - **Vendored Repertoire 0.2.5** — published 0.2.5 lives in `vendor/@0xray/repertoire`. Wear replaces older leftovers. Optional; Station is the memory when it is off.
42
+
43
+ ### 🔎 Other Changes
44
+ - Load worn Repertoire first; sibling checkout last. (f8a90b531)
45
+ - Put published Repertoire 0.2.5 inside 0xray vendor and wear it. (a90b0a7a4)
46
+
47
+ ---
48
+
37
49
  ## [4.0.18] - 2026-09-22
38
50
 
39
51
  ### 🔄 Changes
@@ -229,8 +229,8 @@ function notesPath(root) {
229
229
  function repertoirePackageRoots(root) {
230
230
  const candidates = [
231
231
  join(root, "node_modules", "@0xray", "repertoire"),
232
- join(root, "..", "repertoire"),
233
232
  join(root, "vendor", "@0xray", "repertoire"),
233
+ join(root, "..", "repertoire"),
234
234
  ];
235
235
  const out = [];
236
236
  for (const pkgRoot of candidates) {
@@ -535,7 +535,9 @@ function buildRepertoireResume(root) {
535
535
  }
536
536
 
537
537
  function applyStationHeat(root, host, extra = {}, existing = {}) {
538
- const hydrate = hydrateDestOnWake(root);
538
+ const mr = readMemoryRoutingConfig(root);
539
+ const memoryOff = isExplicitMemoryRoutingOptOut(mr);
540
+ const hydrate = memoryOff ? { dest: null, added: 0, destCount: 0 } : hydrateDestOnWake(root);
539
541
  const captured = maybeCaptureSessionOnHeadMove(root);
540
542
  const pickup = readNotesPickup(root);
541
543
  const approaches = readLatestSessionApproaches(root);
@@ -569,7 +571,7 @@ function applyStationHeat(root, host, extra = {}, existing = {}) {
569
571
  }
570
572
  const priorWorking = readRepertoireWorking(root);
571
573
  const destCount = hydrate.destCount || (existsSync(destSignalsPath(root)) ? countCuratedSignals(destSignalsPath(root)) : 0);
572
- if (!matchedSignals.length && matchText) {
574
+ if (!memoryOff && !matchedSignals.length && matchText) {
573
575
  if (
574
576
  !rematch &&
575
577
  priorWorking &&
@@ -608,6 +610,7 @@ function applyStationHeat(root, host, extra = {}, existing = {}) {
608
610
  const working = persistRepertoireWorking(root, workingSnapshot);
609
611
  const pickupChanged = Boolean(pickup && (!priorWorking || priorWorking.pickup !== pickup));
610
612
  if (
613
+ !memoryOff &&
611
614
  matchedSignals.length &&
612
615
  (isCompactHook(extra) || hydrate.added > 0 || pickupChanged)
613
616
  ) {
@@ -32,19 +32,19 @@ function providerCandidates() {
32
32
  : join(root, routing.module_path)
33
33
  : null;
34
34
  const raw = [
35
- join(root, '..', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js'),
36
- join(root, 'node_modules', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js'),
37
35
  configured,
36
+ join(root, 'node_modules', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js'),
38
37
  join(root, 'vendor', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js'),
38
+ join(root, '..', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js'),
39
39
  ].filter(Boolean);
40
- const withSubject = [];
41
- const rest = [];
40
+ const seen = new Set();
41
+ const out = [];
42
42
  for (const dest of raw) {
43
- const overlay = dest.replace(/dist\/provider\/memory-routing-provider\.js$/, 'data/subject-overlay.json');
44
- if (existsSync(overlay)) withSubject.push(dest);
45
- else rest.push(dest);
43
+ if (seen.has(dest)) continue;
44
+ seen.add(dest);
45
+ out.push(dest);
46
46
  }
47
- return [...withSubject, ...rest];
47
+ return out;
48
48
  }
49
49
 
50
50
  async function loadProvider() {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.18",
3
+ "version": "4.0.19",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.18",
3
+ "version": "4.0.19",
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",
@@ -92,7 +92,7 @@ function assertOrganRequire(tmpRoot) {
92
92
  if (organPkg.name !== "@0xray/repertoire") {
93
93
  throw new Error(`required organ name ${organPkg.name}`);
94
94
  }
95
- if (organPkg.version !== "0.2.0") {
95
+ if (organPkg.version !== "0.2.5") {
96
96
  throw new Error(`required organ version ${organPkg.version}`);
97
97
  }
98
98
  if (fs.existsSync(path.join(tmpRoot, "vendor"))) {
@@ -165,8 +165,8 @@ function assertFreshInstallDefaults(tmpRoot, version) {
165
165
  throw new Error("vendored @0xray/repertoire missing from fresh tarball install");
166
166
  }
167
167
  const organ = JSON.parse(fs.readFileSync(organPkg, "utf-8"));
168
- if (organ.version !== "0.2.0") {
169
- throw new Error(`expected organ 0.2.0, got ${organ.version}`);
168
+ if (organ.version !== "0.2.5") {
169
+ throw new Error(`expected organ 0.2.5, got ${organ.version}`);
170
170
  }
171
171
  console.log(" ✅ .xray/features.json fresh-install defaults (opt-in off)");
172
172
  return { consumerFeaturesPath, features };
@@ -37,6 +37,41 @@ function destIsUsableRepertoire(dest) {
37
37
  return repertoirePackageName(dest) === "@0xray/repertoire";
38
38
  }
39
39
 
40
+ function packageVersion(dir) {
41
+ try {
42
+ const version = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8")).version;
43
+ return typeof version === "string" ? version : "0.0.0";
44
+ } catch {
45
+ return "0.0.0";
46
+ }
47
+ }
48
+
49
+ function versionLessThan(left, right) {
50
+ const a = String(left || "0").split(".").map((n) => Number.parseInt(n, 10) || 0);
51
+ const b = String(right || "0").split(".").map((n) => Number.parseInt(n, 10) || 0);
52
+ const n = Math.max(a.length, b.length);
53
+ for (let i = 0; i < n; i += 1) {
54
+ const av = a[i] || 0;
55
+ const bv = b[i] || 0;
56
+ if (av < bv) return true;
57
+ if (av > bv) return false;
58
+ }
59
+ return false;
60
+ }
61
+
62
+ function removeDestTree(dest) {
63
+ try {
64
+ const st = fs.lstatSync(dest);
65
+ if (st.isSymbolicLink()) {
66
+ fs.unlinkSync(dest);
67
+ return;
68
+ }
69
+ } catch {
70
+ return;
71
+ }
72
+ fs.rmSync(dest, { recursive: true, force: true });
73
+ }
74
+
40
75
  function removeBrokenDest(dest) {
41
76
  try {
42
77
  const st = fs.lstatSync(dest);
@@ -51,7 +86,10 @@ function removeBrokenDest(dest) {
51
86
  function wearOne(vendor, dest, log) {
52
87
  removeBrokenDest(dest);
53
88
  if (destAlreadyWorn(dest, vendor)) return true;
54
- if (fs.existsSync(dest) && destIsUsableRepertoire(dest)) return true;
89
+ if (fs.existsSync(dest) && destIsUsableRepertoire(dest)) {
90
+ if (!versionLessThan(packageVersion(dest), packageVersion(vendor))) return true;
91
+ removeDestTree(dest);
92
+ }
55
93
 
56
94
  fs.mkdirSync(path.dirname(dest), { recursive: true });
57
95
  const rel = path.relative(path.dirname(dest), vendor);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.18",
3
+ "version": "4.0.19",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -74,9 +74,11 @@ Configure in `.xray/features.json`:
74
74
  "memory_routing": {
75
75
  "enabled": true,
76
76
  "provider": "repertoire",
77
- "module_path": "../repertoire/dist/provider/memory-routing-provider.js",
77
+ "module_path": "./dist/provider/memory-routing-provider.js",
78
78
  "config": {
79
- "signalsPath": "../repertoire/data/curated_signals.json"
79
+ "signalsPath": ".xray/state/repertoire/curated_signals.json",
80
+ "statePath": ".xray/state/repertoire/inference-state.json",
81
+ "feedbackDir": ".xray/state/repertoire/feedback"
80
82
  }
81
83
  }
82
84
  ```
@@ -94,6 +96,10 @@ Without Repertoire: `{ "enabled": false, "provider": "null" }`.
94
96
 
95
97
  Tools: `repertoire__get_task_confidence`, `repertoire__get_high_confidence_signals`, `repertoire__search_primitives`, `repertoire__ingest_feedback`.
96
98
 
99
+ Factory seed (`data/curated_signals.json`) is read-only (8 names). `data/stack-overlay.json` merges into the project copy on hydrate so stack language survives a new clone. `data/subject-overlay.json` merges after that so dest knows what each organ/hangar is. `reloadOpProc` is factory + stack only. Live writes hydrate `.xray/state/repertoire/` even when cwd is this organ repo. Do not pin 0.1.8. Station is the survive-the-cut card — not this organ.
100
+
101
+ Lead cadence lives in worn 0xRay (`grok-bot/ops/LEAD-CADENCE.md` + `orchestrator` skill). Project-local names `lead-cadence-syncopation`, `live-loop-not-pacer`, `peer-wears-without-commands` must route on this copy. A peer continues from Station + these names — no command stream.
102
+
97
103
  ## Codex OS (always on — not optional)
98
104
 
99
105
  The Universal Development Codex (`.xray/codex.json`, **69 terms**) is enforced by **PreToolUse** (blocks) and this section (brain). MCP enforcer is audit — not the gate.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Factory memory organ for [0xRay](https://github.com/0xRayAI/xray): seed primitives, in-process memory routing, extra MCP (not an 8th `xray-*` server).
4
4
 
5
- **v0.2.0** · 0xRay **4.0** wear. Runtime does **not** depend on `0xray` (optional peer for suit-verify scripts).
5
+ **v0.2.5** · 0xRay **4.0** wear. Runtime does **not** depend on `0xray` (optional peer for suit-verify scripts).
6
6
 
7
7
  ## Install
8
8
 
@@ -43,13 +43,17 @@ Default operating model: **`autonomy-command`** — lead dev, phased todos, suba
43
43
  }
44
44
  ```
45
45
 
46
- Bundled `data/curated_signals.json` is used by default. Override with env:
46
+ Bundled `data/curated_signals.json` is **read-only** (8 factory trap names). `data/stack-overlay.json` is the committed stack-language overlay (OP-PROC). `data/subject-overlay.json` is what each workspace organ/hangar *is*. The provider hydrates a project copy under `.xray/state/repertoire/curated_signals.json` (seed + stack + subject) — including when cwd is this organ repo. Feedback never writes the tarball seed. Do not pin 0.1.8.
47
+
48
+ Override with env:
47
49
 
48
50
  | Env | Default |
49
51
  |-----|---------|
50
- | `CURATED_SIGNALS_PATH` | `<package>/data/curated_signals.json` |
51
- | `REPERTOIRE_DATA_DIR` | `<package>/data` |
52
- | `REPERTOIRE_LOG_DIR` | `<package>/logs/groover-inference` |
52
+ | `CURATED_SIGNALS_PATH` | factory seed (hydrated to `.xray/state/repertoire/curated_signals.json`) |
53
+ | `REPERTOIRE_DATA_DIR` | `.xray/state/repertoire` |
54
+ | `REPERTOIRE_STATE_PATH` | `.xray/state/repertoire/inference-state.json` |
55
+ | `REPERTOIRE_LOG_DIR` | `.xray/state/repertoire/logs` |
56
+ | `REPERTOIRE_FEEDBACK_DIR` | `.xray/state/repertoire/feedback` |
53
57
 
54
58
  ### Tools
55
59
 
@@ -60,6 +64,8 @@ Bundled `data/curated_signals.json` is used by default. Override with env:
60
64
  | `repertoire__get_high_confidence_signals` | Validated signals above threshold |
61
65
  | `repertoire__ingest_feedback` | Record orchestrator outcomes |
62
66
 
67
+ Routing confidence is **time-weighted**: excess above the 0.55 gate fades after a 14-day grace (60-day half-life). Factory seed sitting on the gate keeps routing. `npm run signals:hygiene` reports decay on the hydrated project copy under `.xray/state/repertoire/`; it dry-runs in this repo unless `--i-mean-it` (writes the project copy, never the tarball).
68
+
63
69
  ## 0xRay memory routing (in-process)
64
70
 
65
71
  In `.xray/features.json` or `xray/features.json`:
@@ -76,8 +82,10 @@ In `.xray/features.json` or `xray/features.json`:
76
82
 
77
83
  ```json
78
84
  "config": {
79
- "signalsPath": ".xray/curated_signals.json",
80
- "logDir": "logs/groover-inference"
85
+ "signalsPath": ".xray/state/repertoire/curated_signals.json",
86
+ "statePath": ".xray/state/repertoire/inference-state.json",
87
+ "feedbackDir": ".xray/state/repertoire/feedback",
88
+ "logDir": ".xray/state/repertoire/logs"
81
89
  }
82
90
  ```
83
91
 
@@ -98,7 +106,26 @@ provider.getTaskConfidence?.({
98
106
 
99
107
  ## Field actuation add-ons (optional)
100
108
 
101
- Repertoire has **no Moltbook dependency**. It ingests **enriched JSONL** from any producer (`matched_primitives` + `match_confidence`) and closes the memory loop via consult, feedback, and post-tick ingest.
109
+ Repertoire has **no Moltbook dependency**. It ingests **enriched JSONL** from an **explicit** producer (`matched_primitives` + `match_confidence`) and can grow the project dest — unknown primitives that pass the 0.55 gate are proposed as `field-observed`. **Groover is not Repertoire.** Groover was a broken experiment of how this organ was supposed to work. Do not treat Groover field (145-name `repertoire-brain`, sibling inference JSONL) as the dest becoming real. The factory seed stays 8 names. Do not pin `0.1.8`.
110
+
111
+ ```bash
112
+ REPERTOIRE_FIELD_LOGS=/path/to/this-project/enriched npm run ingest
113
+ npm run health:repertoire
114
+ ```
115
+
116
+ `ingest` without `--path` and `--source groover` reads `REPERTOIRE_FIELD_LOGS` only. It does **not** walk `../groover/`. Health reads `.xray/state/repertoire/`, not the package tarball.
117
+
118
+ ## Compact reload (the 37 overlay names are OP-PROC)
119
+
120
+ Station is the ticket. The overlay names (`station-survives-the-cut`, `repertoire-is-long-running-kb`, `compact-rekey-from-disk`, …) are the operating procedure.
121
+
122
+ After compact the suit reloads OP-PROC by hydrating `.xray/state/repertoire/curated_signals.json` and reading that dest — not by restating commands and not by dumping names onto `STATION.md`. `reloadOpProc()` is that snapshot. 0xRay heat writes the same names onto `.xray/state/repertoire-working.json`.
123
+
124
+ ```bash
125
+ npm run ingest -- --source xray
126
+ ```
127
+
128
+ Walks `docs/inference` / `.xray/inference` `session-*.json` on this project and suited siblings. Grows dest from session-capture. Heats overlay names that already live on dest. `REPERTOIRE_XRAY_LOGS` is an explicit extra colon list.
102
129
 
103
130
  Each project activates its own public field surface if it wants one:
104
131