0xray 4.0.18 → 4.0.20

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 (75) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.xray/features.json +1 -1
  3. package/dist/CHANGELOG.md +25 -0
  4. package/dist/integrations/cursor/hooks/after-file-edit.js +6 -3
  5. package/dist/integrations/cursor/hooks/cursor-hook-utils.js +40 -20
  6. package/dist/integrations/cursor/hooks/pre-compact.js +30 -22
  7. package/dist/integrations/cursor/hooks/pre-tool-use.js +5 -4
  8. package/dist/integrations/grok/hooks/grok-hook-utils.js +3 -1
  9. package/dist/integrations/hermes-agent/bridge.mjs +14 -0
  10. package/dist/integrations/hooks/station-hook-runtime.cjs +243 -13
  11. package/dist/integrations/hooks/station-hook-runtime.mjs +6 -0
  12. package/dist/integrations/hooks/station-memory-ingest.mjs +153 -4
  13. package/dist/integrations/hooks/station-memory-match.mjs +8 -8
  14. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  15. package/dist/nucleus/delegation-gate.js +10 -11
  16. package/dist/nucleus/suit-temperament.js +5 -1
  17. package/package.json +1 -1
  18. package/scripts/node/consumer-install-smoke.mjs +3 -3
  19. package/scripts/node/wear-vendored-repertoire.cjs +39 -1
  20. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  21. package/vendor/@0xray/repertoire/AGENTS.md +8 -2
  22. package/vendor/@0xray/repertoire/README.md +35 -8
  23. package/vendor/@0xray/repertoire/data/stack-overlay.json +750 -0
  24. package/vendor/@0xray/repertoire/data/subject-overlay.json +297 -0
  25. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +36 -1
  26. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -1
  27. package/vendor/@0xray/repertoire/dist/RepertoireService.js +108 -18
  28. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -1
  29. package/vendor/@0xray/repertoire/dist/index.d.ts +3 -1
  30. package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -1
  31. package/vendor/@0xray/repertoire/dist/index.js +3 -1
  32. package/vendor/@0xray/repertoire/dist/index.js.map +1 -1
  33. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +4 -0
  34. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -1
  35. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +15 -1
  36. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -1
  37. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +22 -8
  38. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -1
  39. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +56 -5
  40. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -1
  41. package/vendor/@0xray/repertoire/dist/mcp/server.js +8 -13
  42. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -1
  43. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -1
  44. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +24 -7
  45. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -1
  46. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -1
  47. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +2 -1
  48. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -1
  49. package/vendor/@0xray/repertoire/dist/paths.d.ts +65 -2
  50. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -1
  51. package/vendor/@0xray/repertoire/dist/paths.js +377 -6
  52. package/vendor/@0xray/repertoire/dist/paths.js.map +1 -1
  53. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -1
  54. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +6 -8
  55. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -1
  56. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +20 -2
  57. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -1
  58. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +121 -8
  59. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -1
  60. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +2 -1
  61. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -1
  62. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +21 -3
  63. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -1
  64. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts +40 -0
  65. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts.map +1 -0
  66. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js +89 -0
  67. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js.map +1 -0
  68. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -1
  69. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +1 -0
  70. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -1
  71. package/vendor/@0xray/repertoire/dist/types.d.ts +5 -0
  72. package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -1
  73. package/vendor/@0xray/repertoire/package.json +4 -2
  74. package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +2 -2
  75. package/xray/features.json +1 -1
@@ -1,12 +1,161 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Compact ingest — persist matched signals back into the organ (project-local copy).
3
+ * Station organ write — compact ingest + wake grow.
4
+ * Grow uses the worn RepertoireService. Groover field stays off.
4
5
  */
5
- import { existsSync, readFileSync } from 'node:fs';
6
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
6
7
  import { join } from 'node:path';
8
+ import { pathToFileURL } from 'node:url';
7
9
 
8
10
  const root = process.argv[2];
9
- const sessionId = process.argv[3] || 'station';
11
+ const mode = process.argv[3] || 'station';
12
+
13
+ function readRouting(projectRoot) {
14
+ let routing = { enabled: false, provider: 'null' };
15
+ const featuresPath = join(projectRoot, '.xray', 'features.json');
16
+ if (existsSync(featuresPath)) {
17
+ try {
18
+ routing = JSON.parse(readFileSync(featuresPath, 'utf8')).memory_routing || routing;
19
+ } catch {
20
+ /* leftover */
21
+ }
22
+ }
23
+ return routing;
24
+ }
25
+
26
+ function isExplicitOptOut(routing) {
27
+ return routing && routing.enabled === false && routing.provider === 'repertoire';
28
+ }
29
+
30
+ function organServiceCandidates(projectRoot, routing) {
31
+ const configured = routing.module_path
32
+ ? routing.module_path.startsWith('/') || /^[A-Za-z]:[\\/]/.test(routing.module_path)
33
+ ? routing.module_path
34
+ : join(projectRoot, routing.module_path)
35
+ : null;
36
+ const fromProvider = configured
37
+ ? configured.replace(/provider\/memory-routing-provider\.js$/, 'RepertoireService.js')
38
+ : null;
39
+ const raw = [
40
+ fromProvider,
41
+ join(projectRoot, 'node_modules', '@0xray', 'repertoire', 'dist', 'RepertoireService.js'),
42
+ join(projectRoot, 'vendor', '@0xray', 'repertoire', 'dist', 'RepertoireService.js'),
43
+ join(projectRoot, '..', 'repertoire', 'dist', 'RepertoireService.js'),
44
+ ].filter(Boolean);
45
+ const seen = new Set();
46
+ const out = [];
47
+ for (const dest of raw) {
48
+ if (seen.has(dest) || !existsSync(dest)) continue;
49
+ seen.add(dest);
50
+ out.push(dest);
51
+ }
52
+ return out;
53
+ }
54
+
55
+ function ensureDestShape(destSignals) {
56
+ if (!existsSync(destSignals)) return;
57
+ try {
58
+ const data = JSON.parse(readFileSync(destSignals, 'utf8'));
59
+ if (!Array.isArray(data.signals)) return;
60
+ let dirty = false;
61
+ for (const signal of data.signals) {
62
+ if (!signal) continue;
63
+ if (!Array.isArray(signal.tags)) {
64
+ signal.tags = [];
65
+ dirty = true;
66
+ }
67
+ if (typeof signal.definition !== 'string') {
68
+ signal.definition = String(signal.name || '');
69
+ dirty = true;
70
+ }
71
+ }
72
+ if (dirty) writeFileSync(destSignals, `${JSON.stringify(data, null, 2)}\n`);
73
+ } catch {
74
+ /* leftover */
75
+ }
76
+ }
77
+
78
+ function readCleanupDiary(projectRoot) {
79
+ const files = [
80
+ join(projectRoot, '.xray', 'state', 'NOTES.md'),
81
+ join(projectRoot, '.xray', 'state', 'CLEANSE-LIST.md'),
82
+ join(projectRoot, 'docs', 'archive', 'README.md'),
83
+ ];
84
+ const parts = [];
85
+ const sources = [];
86
+ for (const dest of files) {
87
+ if (!existsSync(dest)) continue;
88
+ try {
89
+ parts.push(readFileSync(dest, 'utf8'));
90
+ sources.push(dest);
91
+ } catch {
92
+ /* leftover */
93
+ }
94
+ }
95
+ return { text: parts.join('\n'), sources };
96
+ }
97
+
98
+ async function growDest(projectRoot) {
99
+ const routing = readRouting(projectRoot);
100
+ if (isExplicitOptOut(routing)) {
101
+ process.stdout.write(`${JSON.stringify({ skipped: 'opt-out' })}\n`);
102
+ return;
103
+ }
104
+ for (const dest of organServiceCandidates(projectRoot, routing)) {
105
+ try {
106
+ const mod = await import(pathToFileURL(dest).href);
107
+ const RepertoireService = mod.RepertoireService;
108
+ if (typeof RepertoireService !== 'function') continue;
109
+ const pathsMod = await import(pathToFileURL(dest.replace(/RepertoireService\.js$/, 'paths.js')).href);
110
+ const destSignals = join(projectRoot, '.xray', 'state', 'repertoire', 'curated_signals.json');
111
+ ensureDestShape(destSignals);
112
+ const service = new RepertoireService({
113
+ projectRoot,
114
+ signalsPath: destSignals,
115
+ syncXray: false,
116
+ syncField: false,
117
+ });
118
+ ensureDestShape(destSignals);
119
+ const before = service.signalsManager.load().signals.length;
120
+ const sessions = service.syncXrayMemory();
121
+ const siblings = service.syncWorkspaceRepos();
122
+ const kernel =
123
+ typeof pathsMod.collectKernelDiaryText === 'function'
124
+ ? pathsMod.collectKernelDiaryText(projectRoot)
125
+ : { text: '', sources: [] };
126
+ const cleanup = readCleanupDiary(projectRoot);
127
+ const diary = service.heatKernelDiary({
128
+ text: [kernel.text, cleanup.text].filter(Boolean).join('\n'),
129
+ sources: [...(kernel.sources || []), ...cleanup.sources],
130
+ });
131
+ const after = service.signalsManager.load().signals.length;
132
+ process.stdout.write(
133
+ `${JSON.stringify({
134
+ before,
135
+ after,
136
+ imported: sessions.imported,
137
+ observed: siblings.observed,
138
+ heated: diary.heated,
139
+ })}\n`,
140
+ );
141
+ return;
142
+ } catch {
143
+ /* try next organ */
144
+ }
145
+ }
146
+ process.stdout.write(`${JSON.stringify({ skipped: 'no-organ' })}\n`);
147
+ }
148
+
149
+ if (!root) {
150
+ process.exit(0);
151
+ }
152
+
153
+ if (mode === '--grow') {
154
+ await growDest(root);
155
+ process.exit(0);
156
+ }
157
+
158
+ const sessionId = mode;
10
159
  const hookEvent = process.argv[4] || 'post_compact';
11
160
  let signals = [];
12
161
  try {
@@ -14,7 +163,7 @@ try {
14
163
  } catch {
15
164
  signals = [];
16
165
  }
17
- if (!root || !Array.isArray(signals) || signals.length === 0) {
166
+ if (!Array.isArray(signals) || signals.length === 0) {
18
167
  process.exit(0);
19
168
  }
20
169
 
@@ -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.20",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -462,17 +462,16 @@ export function evaluateConstitutionGate(toolName, toolInput, ctx) {
462
462
  return { allow: true };
463
463
  }
464
464
  export function evaluatePreToolGate(toolName, toolInput, ctx) {
465
- if (ctx.host === 'openclaw') {
466
- try {
467
- maybeHeatHostStation(ctx.projectRoot, 'openclaw', {
468
- source: '0xray/openclaw-pre-tool',
469
- sessionId: ctx.sessionId || 'openclaw',
470
- hookEvent: ctx.hookEvent || 'session_start',
471
- });
472
- }
473
- catch {
474
- /* station heat is best-effort — constitution still runs */
475
- }
465
+ const host = ctx.host || 'generic';
466
+ try {
467
+ maybeHeatHostStation(ctx.projectRoot, host, {
468
+ source: `0xray/${host}-pre-tool`,
469
+ sessionId: ctx.sessionId || host,
470
+ hookEvent: ctx.hookEvent || 'pre_tool_use',
471
+ });
472
+ }
473
+ catch {
474
+ /* station heat is best-effort — constitution still runs */
476
475
  }
477
476
  const constitution = evaluateConstitutionGate(toolName, toolInput, ctx);
478
477
  if (!constitution.allow)
@@ -111,7 +111,11 @@ export function maybeHeatHostStation(projectRoot, host, extra = {}) {
111
111
  const existingSessionId = concreteSessionId(existing.sessionId);
112
112
  const sameHost = existing.host === host;
113
113
  const sameSession = existingSessionId !== null && sessionId !== null && existingSessionId === sessionId;
114
- if (sameHost && sameSession && fs.existsSync(cardPath)) {
114
+ if (sameHost &&
115
+ sameSession &&
116
+ fs.existsSync(cardPath) &&
117
+ !stationHeat.stationBootNeedsRefresh(existing, projectRoot, host)) {
118
+ stationHeat.heatLiveMemory(projectRoot);
115
119
  return bootPath;
116
120
  }
117
121
  return writeSuitSessionBoot(projectRoot, host, extra);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "4.0.18",
3
+ "version": "4.0.20",
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.20",
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