0xray 3.5.5 → 4.0.1
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/.mcp.json +18 -14
- package/.opencode/skills/api-design/SKILL.md +1 -1
- package/.opencode/skills/architect-tools/SKILL.md +1 -1
- package/.opencode/skills/architecture-patterns/SKILL.md +1 -1
- package/.opencode/skills/auto-format/SKILL.md +1 -1
- package/.opencode/skills/boot-orchestrator/SKILL.md +2 -6
- package/.opencode/skills/bug-triage/SKILL.md +1 -1
- package/.opencode/skills/code-analyzer/SKILL.md +1 -1
- package/.opencode/skills/code-review/SKILL.md +1 -1
- package/.opencode/skills/enforcer/SKILL.md +1 -1
- package/.opencode/skills/framework-compliance-audit/SKILL.md +1 -1
- package/.opencode/skills/git-workflow/SKILL.md +1 -1
- package/.opencode/skills/hermes-agent/SKILL.md +36 -36
- package/.opencode/skills/inference-improve/SKILL.md +1 -1
- package/.opencode/skills/lint/SKILL.md +1 -1
- package/.opencode/skills/log-monitor/SKILL.md +1 -1
- package/.opencode/skills/model-health-check/SKILL.md +1 -1
- package/.opencode/skills/multimodal-looker/SKILL.md +1 -1
- package/.opencode/skills/orchestrator/SKILL.md +38 -14
- package/.opencode/skills/performance-analysis/SKILL.md +1 -1
- package/.opencode/skills/performance-optimization/SKILL.md +1 -1
- package/.opencode/skills/processor-pipeline/SKILL.md +1 -1
- package/.opencode/skills/project-analysis/SKILL.md +1 -1
- package/.opencode/skills/refactoring-strategies/SKILL.md +1 -1
- package/.opencode/skills/registry.json +65 -0
- package/.opencode/skills/researcher/SKILL.md +18 -5
- package/.opencode/skills/security-audit/SKILL.md +1 -1
- package/.opencode/skills/security-scan/SKILL.md +1 -1
- package/.opencode/skills/session-management/SKILL.md +1 -1
- package/.opencode/skills/state-manager/SKILL.md +1 -1
- package/.opencode/skills/storyteller/SKILL.md +1 -1
- package/.opencode/skills/strategist/SKILL.md +12 -0
- package/.opencode/skills/testing-best-practices/SKILL.md +37 -0
- package/.opencode/skills/testing-strategy/SKILL.md +14 -3
- package/.opencode/skills/ui-ux-design/SKILL.md +1 -1
- package/.opencode/skills/xray-orchestrator/index.ts +267 -0
- package/.xray/codex.json +12 -3
- package/.xray/features.json +28 -6
- package/.xray/features.schema.json +31 -0
- package/AGENTS-consumer.md +17 -7
- package/AGENTS.md +18 -10
- package/README.md +30 -27
- package/SKILLS.md +2 -2
- package/dist/AGENTS.md +18 -10
- package/dist/CHANGELOG.md +81 -11
- package/dist/README.md +30 -27
- package/dist/SKILLS.md +2 -2
- package/dist/cli/commands/hermes-install.js +3 -0
- package/dist/cli/commands/openclaw-install.js +14 -0
- package/dist/cli/index.js +10 -1
- package/dist/core/features-config.d.ts +15 -2
- package/dist/infrastructure/schemas/cloud-schemas.d.ts +1 -1
- package/dist/integrations/grok/grok-cli.d.ts +3 -0
- package/dist/integrations/grok/grok-cli.js +92 -4
- package/dist/integrations/grok/hooks/grok-hook-utils.js +53 -7
- package/dist/integrations/grok/hooks/post-tool-use.js +68 -46
- package/dist/integrations/grok/hooks/pre-tool-use.js +14 -31
- package/dist/integrations/grok/hooks/session-start.js +86 -4
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
- package/dist/integrations/hermes-agent/bridge.mjs +26 -1
- package/dist/integrations/hooks/delegation-gate-runtime.mjs +32 -3
- package/dist/integrations/hooks/pipeline-hook-runtime.mjs +1 -1
- package/dist/integrations/hooks/station-hook-runtime.cjs +421 -0
- package/dist/integrations/hooks/station-hook-runtime.mjs +24 -0
- package/dist/integrations/hooks/station-memory-ingest.mjs +45 -0
- package/dist/integrations/hooks/station-memory-match.mjs +47 -0
- package/dist/integrations/openclaw/client.d.ts +5 -1
- package/dist/integrations/openclaw/client.js +17 -9
- package/dist/integrations/openclaw/config.js +0 -1
- package/dist/integrations/openclaw/hooks/pre-tool-gate-runtime.mjs +102 -0
- package/dist/integrations/openclaw/index.js +17 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +12 -0
- package/dist/integrations/openclaw/pre-tool-gate.d.ts +19 -0
- package/dist/integrations/openclaw/pre-tool-gate.js +39 -0
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
- package/dist/memory-routing/index.d.ts +1 -1
- package/dist/memory-routing/index.js +1 -1
- package/dist/memory-routing/provider-loader.d.ts +4 -0
- package/dist/memory-routing/provider-loader.js +44 -2
- package/dist/memory-routing/provider-registry.js +3 -2
- package/dist/nucleus/autonomy-kernel.d.ts +2 -2
- package/dist/nucleus/autonomy-kernel.js +17 -6
- package/dist/nucleus/confer.js +17 -3
- package/dist/nucleus/delegation-gate.d.ts +14 -8
- package/dist/nucleus/delegation-gate.js +151 -16
- package/dist/nucleus/suit-temperament.d.ts +40 -0
- package/dist/nucleus/suit-temperament.js +157 -0
- package/dist/nucleus/user-aside.js +1 -1
- package/dist/plugin/xray-codex-injection.js +14 -3
- package/dist/postprocessor/triggers/GitHookTrigger.js +11 -5
- package/opencode.json +80 -0
- package/package.json +15 -5
- package/scripts/hooks/install-hooks.cjs +18 -3
- package/scripts/hooks/run-hook.js +67 -3
- package/scripts/mjs/run-repertoire-mcp.mjs +39 -0
- package/scripts/mjs/verify-confer-core.mjs +1 -1
- package/scripts/mjs/verify-delegation-gate-core.mjs +29 -2
- package/scripts/mjs/verify-four-floor-compact.mjs +524 -0
- package/scripts/mjs/verify-pipeline-facets.mjs +215 -0
- package/scripts/mjs/verify-temperament-live.mjs +261 -0
- package/scripts/node/bridge-mcp-wiring.cjs +277 -29
- package/scripts/node/consumer-install-smoke.mjs +55 -2
- package/scripts/node/install-bridges.cjs +195 -33
- package/scripts/node/postinstall.cjs +50 -27
- package/scripts/node/reconcile-version.mjs +0 -4
- package/scripts/node/release-gate.mjs +1 -1
- package/scripts/node/release.mjs +2 -2
- package/scripts/node/universal-version-manager.js +1 -1
- package/scripts/node/validate-release-docs.mjs +20 -33
- package/scripts/node/version-manager.mjs +63 -18
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
- package/src/integrations/openclaw/README.md +134 -0
- package/src/integrations/openclaw/plugin/xray-pre-tool/index.js +75 -0
- package/src/integrations/openclaw/plugin/xray-pre-tool/openclaw.plugin.json +10 -0
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +12 -0
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
- package/vendor/@0xray/repertoire/AGENTS.md +163 -0
- package/vendor/@0xray/repertoire/LICENSE +21 -0
- package/vendor/@0xray/repertoire/README.md +120 -0
- package/vendor/@0xray/repertoire/data/curated_signals.json +208 -0
- package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts +78 -0
- package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/RepertoireService.js +153 -0
- package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts +39 -0
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js +60 -0
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/index.d.ts +14 -0
- package/vendor/@0xray/repertoire/dist/index.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/index.js +14 -0
- package/vendor/@0xray/repertoire/dist/index.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts +26 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js +109 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts +18 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js +94 -0
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts +7 -0
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js +18 -0
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts +31 -0
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +83 -0
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/mcp/server.d.ts +6 -0
- package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/mcp/server.js +173 -0
- package/vendor/@0xray/repertoire/dist/mcp/server.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts +27 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js +107 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts +11 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js +32 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts +9 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js +72 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts +5 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js +18 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts +31 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js +218 -0
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/paths.d.ts +24 -0
- package/vendor/@0xray/repertoire/dist/paths.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/paths.js +74 -0
- package/vendor/@0xray/repertoire/dist/paths.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts +141 -0
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js +210 -0
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts +48 -0
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +221 -0
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts +11 -0
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js +43 -0
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts +15 -0
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.js +35 -0
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts +3 -0
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js +24 -0
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts +24 -0
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js +148 -0
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts +4 -0
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js +44 -0
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts +22 -0
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js +66 -0
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +1 -0
- package/vendor/@0xray/repertoire/dist/types.d.ts +210 -0
- package/vendor/@0xray/repertoire/dist/types.d.ts.map +1 -0
- package/vendor/@0xray/repertoire/dist/types.js +2 -0
- package/vendor/@0xray/repertoire/dist/types.js.map +1 -0
- package/vendor/@0xray/repertoire/docs/MEMORY-ROUTING-PROVIDER.md +54 -0
- package/vendor/@0xray/repertoire/hermes-mcp.example.json +20 -0
- package/vendor/@0xray/repertoire/mcp-config.example.json +11 -0
- package/vendor/@0xray/repertoire/package.json +124 -0
- package/vendor/@0xray/repertoire/schemas/curated-signal.schema.json +68 -0
- package/vendor/@0xray/repertoire/schemas/inference-log.schema.json +82 -0
- package/vendor/@0xray/repertoire/scripts/confirm-suit-all.mjs +253 -0
- package/vendor/@0xray/repertoire/scripts/confirm-suit-harness.mjs +220 -0
- package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +215 -0
- package/vendor/@0xray/repertoire/scripts/suit-bridge-shared.mjs +139 -0
- package/vendor/@0xray/repertoire/scripts/verify-grok-suit.mjs +304 -0
- package/vendor/@0xray/repertoire/scripts/verify-hermes-suit.mjs +163 -0
- package/vendor/@0xray/repertoire/scripts/verify-openclaw-suit.mjs +125 -0
- package/vendor/@0xray/repertoire/scripts/verify-opencode-suit.mjs +127 -0
- package/vendor/@0xray/repertoire/scripts/verify-synthesis-dogfood.mjs +207 -0
- package/vendor/@0xray/repertoire/skills/repertoire-trap-handling/SKILL.md +206 -0
- package/xray/codex.json +12 -3
- package/xray/features.json +28 -6
- package/xray/features.schema.json +31 -0
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
"hooks": {
|
|
3
3
|
"PreToolUse": [
|
|
4
4
|
{
|
|
5
|
-
"matcher": ".*",
|
|
6
5
|
"hooks": [
|
|
7
6
|
{
|
|
8
7
|
"type": "command",
|
|
9
|
-
"command": "node",
|
|
10
|
-
"
|
|
11
|
-
"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/pre-tool-use.js"
|
|
12
|
-
],
|
|
13
|
-
"timeout": 30000
|
|
8
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/pre-tool-use.js\"",
|
|
9
|
+
"timeout": 30
|
|
14
10
|
}
|
|
15
11
|
]
|
|
16
12
|
}
|
|
@@ -20,11 +16,8 @@
|
|
|
20
16
|
"hooks": [
|
|
21
17
|
{
|
|
22
18
|
"type": "command",
|
|
23
|
-
"command": "node",
|
|
24
|
-
"
|
|
25
|
-
"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js"
|
|
26
|
-
],
|
|
27
|
-
"timeout": 15000
|
|
19
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\"",
|
|
20
|
+
"timeout": 30
|
|
28
21
|
}
|
|
29
22
|
]
|
|
30
23
|
}
|
|
@@ -34,30 +27,44 @@
|
|
|
34
27
|
"hooks": [
|
|
35
28
|
{
|
|
36
29
|
"type": "command",
|
|
37
|
-
"command": "node",
|
|
38
|
-
"
|
|
39
|
-
"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js",
|
|
40
|
-
"--hook-event=user_prompt_submit"
|
|
41
|
-
],
|
|
42
|
-
"timeout": 15000
|
|
30
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=user_prompt_submit",
|
|
31
|
+
"timeout": 30
|
|
43
32
|
}
|
|
44
33
|
]
|
|
45
34
|
}
|
|
46
35
|
],
|
|
47
36
|
"PostToolUse": [
|
|
48
37
|
{
|
|
49
|
-
"matcher": ".*",
|
|
50
38
|
"hooks": [
|
|
51
39
|
{
|
|
52
40
|
"type": "command",
|
|
53
|
-
"command": "node",
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
41
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/post-tool-use.js\"",
|
|
42
|
+
"timeout": 30
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"PreCompact": [
|
|
48
|
+
{
|
|
49
|
+
"hooks": [
|
|
50
|
+
{
|
|
51
|
+
"type": "command",
|
|
52
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=pre_compact",
|
|
53
|
+
"timeout": 30
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"PostCompact": [
|
|
59
|
+
{
|
|
60
|
+
"hooks": [
|
|
61
|
+
{
|
|
62
|
+
"type": "command",
|
|
63
|
+
"command": "XRAY_AI_PATH=\"${XRAY_AI_PATH:-node_modules/0xray}\" node \"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/session-start.js\" --hook-event=post_compact",
|
|
64
|
+
"timeout": 30
|
|
58
65
|
}
|
|
59
66
|
]
|
|
60
67
|
}
|
|
61
68
|
]
|
|
62
69
|
}
|
|
63
|
-
}
|
|
70
|
+
}
|
|
@@ -332,6 +332,12 @@ async function runProcessors(tool, args, phase, projectRoot, logDir) {
|
|
|
332
332
|
priority: 30,
|
|
333
333
|
enabled: true,
|
|
334
334
|
});
|
|
335
|
+
processorManager.registerProcessor({
|
|
336
|
+
name: "nudge",
|
|
337
|
+
type: "post",
|
|
338
|
+
priority: 78,
|
|
339
|
+
enabled: true,
|
|
340
|
+
});
|
|
335
341
|
}
|
|
336
342
|
|
|
337
343
|
let results;
|
|
@@ -436,6 +442,24 @@ async function handleSessionStart(input, projectRoot, logDir) {
|
|
|
436
442
|
/* non-blocking — dist may be absent during dev */
|
|
437
443
|
}
|
|
438
444
|
|
|
445
|
+
try {
|
|
446
|
+
const gate = await import('../hooks/delegation-gate-runtime.mjs');
|
|
447
|
+
if (typeof gate.writeSuitSessionBoot === 'function') {
|
|
448
|
+
const compact =
|
|
449
|
+
input.compact === true ||
|
|
450
|
+
input.hookEvent === 'pre_compact' ||
|
|
451
|
+
input.hookEvent === 'post_compact';
|
|
452
|
+
gate.writeSuitSessionBoot(projectRoot, 'hermes', {
|
|
453
|
+
source: compact ? '0xray/hermes-compact' : '0xray/hermes-session-start',
|
|
454
|
+
sessionId,
|
|
455
|
+
hookEvent: compact ? 'post_compact' : 'session_start',
|
|
456
|
+
...(input.intent ? { intent: input.intent } : {}),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
} catch {
|
|
460
|
+
/* dist may be absent during dev */
|
|
461
|
+
}
|
|
462
|
+
|
|
439
463
|
logToActivity(logDir, `session-start: session=${sessionId} source=bridge`);
|
|
440
464
|
return { ok: true, sessionId, planArchive };
|
|
441
465
|
}
|
|
@@ -494,6 +518,7 @@ async function handlePostProcess(input, projectRoot, logDir) {
|
|
|
494
518
|
});
|
|
495
519
|
|
|
496
520
|
logToActivity(logDir, `post-process: complete duration=${duration}ms processors=${processorResult.success}`);
|
|
521
|
+
logToActivity(logDir, `[nudge] post-process tool=${tool}`);
|
|
497
522
|
|
|
498
523
|
// Log routing outcome for test verification
|
|
499
524
|
logRoutingOutcome(logDir, {
|
|
@@ -862,7 +887,7 @@ async function handleDelegationGate(command, projectRoot, logDir) {
|
|
|
862
887
|
await recordHermesSynthesisTurn(projectRoot, sessionId);
|
|
863
888
|
}
|
|
864
889
|
|
|
865
|
-
const features = gate.loadDelegationGateFeatures(projectRoot);
|
|
890
|
+
const features = gate.loadDelegationGateFeatures(projectRoot, host);
|
|
866
891
|
const outcome = gate.evaluatePreToolGate(tool, args, {
|
|
867
892
|
projectRoot,
|
|
868
893
|
sessionId,
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Used by Grok hooks, Hermes bridge, and verify fixtures.
|
|
5
5
|
*/
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
|
-
import { existsSync } from 'node:fs';
|
|
7
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { homedir } from 'node:os';
|
|
8
9
|
import { dirname, join, resolve } from 'node:path';
|
|
9
10
|
import { fileURLToPath } from 'node:url';
|
|
10
11
|
|
|
@@ -35,17 +36,40 @@ function resolvePackageRoot() {
|
|
|
35
36
|
return resolve(__dirname, '../../..');
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
function markedRoots() {
|
|
40
|
+
const files = [
|
|
41
|
+
join(homedir(), '.hermes', 'plugins', 'xray-hermes', 'xray-consumer-root.txt'),
|
|
42
|
+
join(homedir(), '.openclaw', 'xray-consumer-root.txt'),
|
|
43
|
+
];
|
|
44
|
+
const roots = [];
|
|
45
|
+
for (const file of files) {
|
|
46
|
+
if (!existsSync(file)) continue;
|
|
47
|
+
try {
|
|
48
|
+
const marked = readFileSync(file, 'utf8').trim();
|
|
49
|
+
if (marked) {
|
|
50
|
+
roots.push(marked, join(marked, 'node_modules', '0xray'));
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
/* ignore unreadable marker */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return roots;
|
|
57
|
+
}
|
|
58
|
+
|
|
38
59
|
function loadDelegationGate() {
|
|
39
60
|
const root = resolvePackageRoot();
|
|
61
|
+
const envRoot = process.env.XRAY_AI_PATH || '';
|
|
40
62
|
const candidates = [
|
|
41
63
|
join(__dirname, '../../nucleus/delegation-gate.js'),
|
|
42
64
|
join(root, 'dist/nucleus/delegation-gate.js'),
|
|
65
|
+
envRoot ? join(envRoot, 'dist/nucleus/delegation-gate.js') : '',
|
|
66
|
+
...markedRoots().map((r) => join(r, 'dist/nucleus/delegation-gate.js')),
|
|
43
67
|
join(process.cwd(), 'node_modules/0xray/dist/nucleus/delegation-gate.js'),
|
|
44
|
-
];
|
|
68
|
+
].filter(Boolean);
|
|
45
69
|
const found = candidates.find((p) => existsSync(p));
|
|
46
70
|
if (!found) {
|
|
47
71
|
throw new Error(
|
|
48
|
-
'delegation-gate.js missing — run npm run build in 0xray or npm install 0xray
|
|
72
|
+
'delegation-gate.js missing — run npm run build in 0xray or npm install 0xray',
|
|
49
73
|
);
|
|
50
74
|
}
|
|
51
75
|
return createRequire(import.meta.url)(found);
|
|
@@ -53,6 +77,9 @@ function loadDelegationGate() {
|
|
|
53
77
|
|
|
54
78
|
const gate = loadDelegationGate();
|
|
55
79
|
|
|
80
|
+
export const writeSuitSessionBoot = gate.writeSuitSessionBoot;
|
|
81
|
+
export const maybeHeatHostStation = gate.maybeHeatHostStation;
|
|
82
|
+
|
|
56
83
|
export const {
|
|
57
84
|
loadDelegationGateFeatures,
|
|
58
85
|
normalizeHostToolInput,
|
|
@@ -78,4 +105,6 @@ export const {
|
|
|
78
105
|
buildReceiptFromConsultOutput,
|
|
79
106
|
parseConsultVerdictFromText,
|
|
80
107
|
isSynthesisConsultTodoId,
|
|
108
|
+
archiveStaleLeadDevPlan,
|
|
109
|
+
findRecentStalePlanArchive,
|
|
81
110
|
} = gate;
|
|
@@ -189,7 +189,7 @@ export function runGrokPostprocessorLight(projectRoot, entry = {}) {
|
|
|
189
189
|
phase: 'post-process-light',
|
|
190
190
|
tool: entry.tool ?? 'unknown',
|
|
191
191
|
paths: entry.paths ?? [],
|
|
192
|
-
mode: 'grok-
|
|
192
|
+
mode: 'grok-post-tool-light',
|
|
193
193
|
};
|
|
194
194
|
writeFileSync(markerPath, `${JSON.stringify(payload, null, 2)}\n`);
|
|
195
195
|
appendActivity(projectRoot, 'postprocessor-light', 'info', {
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Station heat — compaction / host-swap card.
|
|
3
|
+
* SSOT remains session-boot.json. STATION.md is the projection the model Reads.
|
|
4
|
+
* Grok ignores SessionStart/UserPromptSubmit stdout; disk + AGENTS.md is the contract.
|
|
5
|
+
*/
|
|
6
|
+
const { execFileSync } = require("child_process");
|
|
7
|
+
const { existsSync, mkdirSync, readFileSync, writeFileSync } = require("fs");
|
|
8
|
+
const { join } = require("path");
|
|
9
|
+
|
|
10
|
+
const HOOKS_DIR = __dirname;
|
|
11
|
+
|
|
12
|
+
const INTENT_MAX = 240;
|
|
13
|
+
|
|
14
|
+
function stationMarkdownPath(root) {
|
|
15
|
+
return join(root, ".xray", "state", "STATION.md");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function sessionBootPath(root) {
|
|
19
|
+
return join(root, ".xray", "state", "session-boot.json");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function clipIntent(raw) {
|
|
23
|
+
if (raw == null) return null;
|
|
24
|
+
const text = String(raw)
|
|
25
|
+
.replace(/<\/?user_query>/gi, " ")
|
|
26
|
+
.replace(/\s+/g, " ")
|
|
27
|
+
.trim();
|
|
28
|
+
if (!text) return null;
|
|
29
|
+
if (text.length <= INTENT_MAX) return text;
|
|
30
|
+
return `${text.slice(0, INTENT_MAX - 1)}…`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readExistingBoot(root) {
|
|
34
|
+
const bootPath = sessionBootPath(root);
|
|
35
|
+
if (!existsSync(bootPath)) return {};
|
|
36
|
+
try {
|
|
37
|
+
const data = JSON.parse(readFileSync(bootPath, "utf8"));
|
|
38
|
+
return data && typeof data === "object" ? data : {};
|
|
39
|
+
} catch {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function readGitBrief(root) {
|
|
45
|
+
try {
|
|
46
|
+
const opts = { cwd: root, encoding: "utf8", timeout: 2000, stdio: ["ignore", "pipe", "ignore"] };
|
|
47
|
+
const head = execFileSync("git", ["rev-parse", "--short", "HEAD"], opts).trim();
|
|
48
|
+
const branch = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], opts).trim();
|
|
49
|
+
if (!head) return null;
|
|
50
|
+
return { branch: branch || "HEAD", head };
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function readGitSubject(root) {
|
|
57
|
+
try {
|
|
58
|
+
const opts = { cwd: root, encoding: "utf8", timeout: 2000, stdio: ["ignore", "pipe", "ignore"] };
|
|
59
|
+
const subject = execFileSync("git", ["log", "-1", "--format=%s"], opts).trim();
|
|
60
|
+
return clipIntent(subject);
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function readLiveTodoLine(plan) {
|
|
67
|
+
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
68
|
+
for (const phase of phases) {
|
|
69
|
+
const todos = Array.isArray(phase && phase.todos) ? phase.todos : [];
|
|
70
|
+
for (const todo of todos) {
|
|
71
|
+
const status = String((todo && todo.status) || "pending");
|
|
72
|
+
if (status === "completed" || status === "cancelled") continue;
|
|
73
|
+
const task = clipIntent((todo && (todo.task || todo.description)) || "");
|
|
74
|
+
if (task) return task;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function readPlanLine(root) {
|
|
81
|
+
const planPath = join(root, ".xray", "state", "lead-dev-plan.json");
|
|
82
|
+
if (existsSync(planPath)) {
|
|
83
|
+
try {
|
|
84
|
+
const plan = JSON.parse(readFileSync(planPath, "utf8"));
|
|
85
|
+
if (plan && plan.active !== false) {
|
|
86
|
+
const live = readLiveTodoLine(plan);
|
|
87
|
+
if (live) return live;
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
/* fall through to git subject — stale / empty plan is not the card */
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return readGitSubject(root);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function resolveRepertoireProviderModule(root) {
|
|
97
|
+
const mr = readMemoryRoutingConfig(root);
|
|
98
|
+
if (mr && typeof mr.module_path === "string" && mr.module_path) {
|
|
99
|
+
const configured = mr.module_path.startsWith("/") || /^[A-Za-z]:[\\/]/.test(mr.module_path)
|
|
100
|
+
? mr.module_path
|
|
101
|
+
: join(root, mr.module_path);
|
|
102
|
+
if (existsSync(configured)) return configured;
|
|
103
|
+
}
|
|
104
|
+
const siblingRoot = join(root, "..", "repertoire");
|
|
105
|
+
const siblingProvider = join(siblingRoot, "dist", "provider", "memory-routing-provider.js");
|
|
106
|
+
const nmProvider = join(
|
|
107
|
+
root,
|
|
108
|
+
"node_modules",
|
|
109
|
+
"@0xray",
|
|
110
|
+
"repertoire",
|
|
111
|
+
"dist",
|
|
112
|
+
"provider",
|
|
113
|
+
"memory-routing-provider.js",
|
|
114
|
+
);
|
|
115
|
+
const vendorProvider = join(
|
|
116
|
+
root,
|
|
117
|
+
"vendor",
|
|
118
|
+
"@0xray",
|
|
119
|
+
"repertoire",
|
|
120
|
+
"dist",
|
|
121
|
+
"provider",
|
|
122
|
+
"memory-routing-provider.js",
|
|
123
|
+
);
|
|
124
|
+
if (existsSync(nmProvider)) return nmProvider;
|
|
125
|
+
if (existsSync(vendorProvider)) return vendorProvider;
|
|
126
|
+
try {
|
|
127
|
+
const pkg = JSON.parse(readFileSync(join(siblingRoot, "package.json"), "utf8"));
|
|
128
|
+
if ((pkg.name === "@0xray/repertoire" || pkg.name === "repertoire") && existsSync(siblingProvider)) {
|
|
129
|
+
return siblingProvider;
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
/* sibling missing */
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function countCuratedSignals(signalsPath) {
|
|
138
|
+
try {
|
|
139
|
+
const data = JSON.parse(readFileSync(signalsPath, "utf8"));
|
|
140
|
+
if (Array.isArray(data.signals)) return data.signals.length;
|
|
141
|
+
if (Array.isArray(data)) return data.length;
|
|
142
|
+
} catch {
|
|
143
|
+
/* unreadable */
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function readMemoryRoutingConfig(root) {
|
|
149
|
+
const featuresPath = join(root, ".xray", "features.json");
|
|
150
|
+
if (!existsSync(featuresPath)) return {};
|
|
151
|
+
try {
|
|
152
|
+
return JSON.parse(readFileSync(featuresPath, "utf8")).memory_routing || {};
|
|
153
|
+
} catch {
|
|
154
|
+
return {};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isExplicitMemoryRoutingOptOut(mr) {
|
|
159
|
+
return Boolean(mr) && mr.enabled === false && mr.provider === "repertoire";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function isLeftoverMemoryRoutingOff(mr) {
|
|
163
|
+
if (!mr || typeof mr !== "object") return true;
|
|
164
|
+
if (mr.enabled === true) return false;
|
|
165
|
+
if (isExplicitMemoryRoutingOptOut(mr)) return false;
|
|
166
|
+
const provider = mr.provider == null || mr.provider === "" ? "null" : mr.provider;
|
|
167
|
+
return provider === "null";
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isMemoryRoutingResolvedOn(mr, modulePath) {
|
|
171
|
+
if (!modulePath) return false;
|
|
172
|
+
if (isExplicitMemoryRoutingOptOut(mr)) return false;
|
|
173
|
+
if (mr.enabled === true && (mr.provider === "repertoire" || mr.provider === "custom")) return true;
|
|
174
|
+
return isLeftoverMemoryRoutingOff(mr);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function repertoireWorkingPath(root) {
|
|
178
|
+
return join(root, ".xray", "state", "repertoire-working.json");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function readRepertoireWorking(root) {
|
|
182
|
+
const dest = repertoireWorkingPath(root);
|
|
183
|
+
if (!existsSync(dest)) return null;
|
|
184
|
+
try {
|
|
185
|
+
const data = JSON.parse(readFileSync(dest, "utf8"));
|
|
186
|
+
return data && typeof data === "object" ? data : null;
|
|
187
|
+
} catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function stationSafeSignals(names) {
|
|
193
|
+
if (!Array.isArray(names)) return [];
|
|
194
|
+
const out = [];
|
|
195
|
+
for (const raw of names) {
|
|
196
|
+
const name = String(raw || "").trim();
|
|
197
|
+
if (!name) continue;
|
|
198
|
+
if (name.toLowerCase().startsWith("bedrock-")) continue;
|
|
199
|
+
out.push(name);
|
|
200
|
+
if (out.length >= 4) break;
|
|
201
|
+
}
|
|
202
|
+
return out;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function persistRepertoireWorking(root, snapshot) {
|
|
206
|
+
try {
|
|
207
|
+
mkdirSync(join(root, ".xray", "state"), { recursive: true });
|
|
208
|
+
const prev = readRepertoireWorking(root) || {};
|
|
209
|
+
const next = { ...prev, ...snapshot, updatedAt: new Date().toISOString() };
|
|
210
|
+
writeFileSync(repertoireWorkingPath(root), `${JSON.stringify(next, null, 2)}\n`);
|
|
211
|
+
return next;
|
|
212
|
+
} catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function matchStationSignalsSync(root, intent) {
|
|
218
|
+
if (!intent) return [];
|
|
219
|
+
const helper = join(HOOKS_DIR, "station-memory-match.mjs");
|
|
220
|
+
if (!existsSync(helper)) return [];
|
|
221
|
+
try {
|
|
222
|
+
const out = execFileSync(process.execPath, [helper, root, intent], {
|
|
223
|
+
encoding: "utf8",
|
|
224
|
+
timeout: 20000,
|
|
225
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
226
|
+
env: process.env,
|
|
227
|
+
});
|
|
228
|
+
const line = String(out).trim().split("\n").filter(Boolean).at(-1) || "[]";
|
|
229
|
+
const parsed = JSON.parse(line);
|
|
230
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
231
|
+
} catch {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function ingestCompactFeedbackSync(root, sessionId, hookEvent, signals) {
|
|
237
|
+
if (!signals.length) return;
|
|
238
|
+
const helper = join(HOOKS_DIR, "station-memory-ingest.mjs");
|
|
239
|
+
if (!existsSync(helper)) return;
|
|
240
|
+
try {
|
|
241
|
+
execFileSync(
|
|
242
|
+
process.execPath,
|
|
243
|
+
[helper, root, sessionId || "station", hookEvent || "post_compact", JSON.stringify(signals)],
|
|
244
|
+
{
|
|
245
|
+
encoding: "utf8",
|
|
246
|
+
timeout: 20000,
|
|
247
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
248
|
+
env: process.env,
|
|
249
|
+
},
|
|
250
|
+
);
|
|
251
|
+
} catch {
|
|
252
|
+
/* working-state file is the session memory; registry ingest is best-effort */
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function isCompactHook(extra) {
|
|
257
|
+
const hook = String(extra.hookEvent || extra.source || "");
|
|
258
|
+
return /compact/i.test(hook);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function formatWorkingLine(working) {
|
|
262
|
+
if (!working || typeof working !== "object") return null;
|
|
263
|
+
const matched = stationSafeSignals(working.matchedSignals);
|
|
264
|
+
if (matched.length) return `Working: ${matched.join(", ")}`;
|
|
265
|
+
const hook = typeof working.hookEvent === "string" ? working.hookEvent : null;
|
|
266
|
+
const head = working.git && working.git.head ? String(working.git.head) : null;
|
|
267
|
+
if (hook && head) return `Working: last ${hook} @ ${head}`;
|
|
268
|
+
if (hook) return `Working: last ${hook}`;
|
|
269
|
+
return "Working: station snapshot";
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function buildRepertoireResume(root) {
|
|
273
|
+
const modulePath = resolveRepertoireProviderModule(root);
|
|
274
|
+
const mr = readMemoryRoutingConfig(root);
|
|
275
|
+
if (!modulePath) {
|
|
276
|
+
return "Repertoire: not installed (memory_routing stays off)";
|
|
277
|
+
}
|
|
278
|
+
let signalsPath = mr.config && mr.config.signalsPath;
|
|
279
|
+
if (signalsPath && !signalsPath.startsWith("/") && !/^[A-Za-z]:[\\/]/.test(signalsPath)) {
|
|
280
|
+
signalsPath = join(root, signalsPath);
|
|
281
|
+
}
|
|
282
|
+
if (!signalsPath) {
|
|
283
|
+
signalsPath = join(modulePath, "..", "..", "..", "data", "curated_signals.json");
|
|
284
|
+
}
|
|
285
|
+
const n = existsSync(signalsPath) ? countCuratedSignals(signalsPath) : null;
|
|
286
|
+
const count = n == null ? "" : ` — ${n} signals`;
|
|
287
|
+
if (isMemoryRoutingResolvedOn(mr, modulePath)) {
|
|
288
|
+
return `Repertoire: on${count}`;
|
|
289
|
+
}
|
|
290
|
+
return `Repertoire: present, memory_routing off${count}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function applyStationHeat(root, host, extra = {}, existing = {}) {
|
|
294
|
+
const prevHost = typeof existing.host === "string" ? existing.host : null;
|
|
295
|
+
const nextSwap = prevHost && host && prevHost !== host ? { from: prevHost, to: host } : null;
|
|
296
|
+
const keptSwap =
|
|
297
|
+
existing.hotSwap &&
|
|
298
|
+
typeof existing.hotSwap === "object" &&
|
|
299
|
+
existing.hotSwap.from &&
|
|
300
|
+
existing.hotSwap.to
|
|
301
|
+
? existing.hotSwap
|
|
302
|
+
: null;
|
|
303
|
+
const hotSwap = nextSwap || keptSwap;
|
|
304
|
+
const intent =
|
|
305
|
+
clipIntent(extra.intent || extra.prompt || extra.userMessage || extra.user_prompt) ||
|
|
306
|
+
(typeof existing.intent === "string" ? existing.intent : null);
|
|
307
|
+
const git = readGitBrief(root);
|
|
308
|
+
const planLine = readPlanLine(root);
|
|
309
|
+
const repertoireResume =
|
|
310
|
+
typeof extra.repertoireResume === "string" ? extra.repertoireResume : buildRepertoireResume(root);
|
|
311
|
+
const swapBit = hotSwap ? `hot-swap ${hotSwap.from} → ${hotSwap.to}` : `host ${host}`;
|
|
312
|
+
const intentBit = intent ? `intent: ${intent}` : "intent: (none yet)";
|
|
313
|
+
const gitBit = git ? `git ${git.branch}@${git.head}` : "git: n/a";
|
|
314
|
+
const planBit = planLine ? `plan: ${planLine}` : "plan: (none)";
|
|
315
|
+
let matchedSignals = stationSafeSignals(extra.matchedSignals);
|
|
316
|
+
const priorWorking = readRepertoireWorking(root);
|
|
317
|
+
if (!matchedSignals.length && intent) {
|
|
318
|
+
if (
|
|
319
|
+
priorWorking &&
|
|
320
|
+
priorWorking.intent === intent &&
|
|
321
|
+
Array.isArray(priorWorking.matchedSignals) &&
|
|
322
|
+
priorWorking.matchedSignals.length
|
|
323
|
+
) {
|
|
324
|
+
matchedSignals = stationSafeSignals(priorWorking.matchedSignals);
|
|
325
|
+
} else {
|
|
326
|
+
matchedSignals = stationSafeSignals(matchStationSignalsSync(root, intent));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (!matchedSignals.length && priorWorking) {
|
|
330
|
+
matchedSignals = stationSafeSignals(priorWorking.matchedSignals);
|
|
331
|
+
}
|
|
332
|
+
const workingSnapshot = {
|
|
333
|
+
host,
|
|
334
|
+
intent,
|
|
335
|
+
git,
|
|
336
|
+
hotSwap,
|
|
337
|
+
hookEvent: extra.hookEvent || extra.source || null,
|
|
338
|
+
memoryRouting: repertoireResume.startsWith("Repertoire: on") ? "on" : "off",
|
|
339
|
+
repertoireResume,
|
|
340
|
+
};
|
|
341
|
+
if (matchedSignals.length) workingSnapshot.matchedSignals = matchedSignals;
|
|
342
|
+
const working = persistRepertoireWorking(root, workingSnapshot);
|
|
343
|
+
if (isCompactHook(extra) && matchedSignals.length) {
|
|
344
|
+
ingestCompactFeedbackSync(
|
|
345
|
+
root,
|
|
346
|
+
typeof extra.sessionId === "string" ? extra.sessionId : "station",
|
|
347
|
+
extra.hookEvent || extra.source || "post_compact",
|
|
348
|
+
matchedSignals,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
const workingLine = formatWorkingLine(working);
|
|
352
|
+
const workingBit = workingLine ? workingLine : "working: (none)";
|
|
353
|
+
const stationLine = `${swapBit}. ${intentBit}. ${planBit}. ${gitBit}. ${repertoireResume}. ${workingBit}`;
|
|
354
|
+
return {
|
|
355
|
+
lastHost: prevHost,
|
|
356
|
+
hotSwap,
|
|
357
|
+
intent,
|
|
358
|
+
git,
|
|
359
|
+
planLine,
|
|
360
|
+
repertoireResume,
|
|
361
|
+
workingLine,
|
|
362
|
+
stationLine,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function formatStationMarkdown(fields) {
|
|
367
|
+
const host = fields.host || "unknown";
|
|
368
|
+
const profile = fields.suit_profile || "guided";
|
|
369
|
+
const lines = ["# Station", ""];
|
|
370
|
+
if (fields.hotSwap && fields.hotSwap.from && fields.hotSwap.to) {
|
|
371
|
+
lines.push(`Hot-swap: ${fields.hotSwap.from} → ${fields.hotSwap.to}`);
|
|
372
|
+
}
|
|
373
|
+
lines.push(`Host: ${host} (${profile})`);
|
|
374
|
+
lines.push(`Intent: ${fields.intent || "(none yet)"}`);
|
|
375
|
+
lines.push(`Plan: ${fields.planLine || "(none)"}`);
|
|
376
|
+
if (fields.git && fields.git.head) {
|
|
377
|
+
lines.push(`Git: ${fields.git.branch}@${fields.git.head}`);
|
|
378
|
+
} else {
|
|
379
|
+
lines.push("Git: n/a");
|
|
380
|
+
}
|
|
381
|
+
lines.push(fields.repertoireResume || "Repertoire: not installed (memory_routing stays off)");
|
|
382
|
+
if (fields.workingLine) {
|
|
383
|
+
lines.push(fields.workingLine);
|
|
384
|
+
}
|
|
385
|
+
lines.push("");
|
|
386
|
+
lines.push("Continue this card. Compaction and host change are the same cut. Do not cold-start.");
|
|
387
|
+
lines.push("Grok does not inject this file — Read it. OpenCode injects. Do not thicken the Grok exo.");
|
|
388
|
+
lines.push("");
|
|
389
|
+
return lines.join("\n");
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function writeStationMarkdown(root, fields) {
|
|
393
|
+
try {
|
|
394
|
+
const dir = join(root, ".xray", "state");
|
|
395
|
+
mkdirSync(dir, { recursive: true });
|
|
396
|
+
const dest = stationMarkdownPath(root);
|
|
397
|
+
writeFileSync(dest, formatStationMarkdown(fields));
|
|
398
|
+
return dest;
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
module.exports = {
|
|
405
|
+
stationMarkdownPath,
|
|
406
|
+
sessionBootPath,
|
|
407
|
+
clipIntent,
|
|
408
|
+
readExistingBoot,
|
|
409
|
+
readGitBrief,
|
|
410
|
+
readGitSubject,
|
|
411
|
+
readPlanLine,
|
|
412
|
+
buildRepertoireResume,
|
|
413
|
+
isExplicitMemoryRoutingOptOut,
|
|
414
|
+
isLeftoverMemoryRoutingOff,
|
|
415
|
+
persistRepertoireWorking,
|
|
416
|
+
readRepertoireWorking,
|
|
417
|
+
formatWorkingLine,
|
|
418
|
+
applyStationHeat,
|
|
419
|
+
formatStationMarkdown,
|
|
420
|
+
writeStationMarkdown,
|
|
421
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESM face for station-hook-runtime.cjs — Grok hooks import this.
|
|
3
|
+
*/
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const impl = require(join(dirname(fileURLToPath(import.meta.url)), 'station-hook-runtime.cjs'));
|
|
10
|
+
|
|
11
|
+
export const stationMarkdownPath = impl.stationMarkdownPath;
|
|
12
|
+
export const sessionBootPath = impl.sessionBootPath;
|
|
13
|
+
export const clipIntent = impl.clipIntent;
|
|
14
|
+
export const readExistingBoot = impl.readExistingBoot;
|
|
15
|
+
export const readGitBrief = impl.readGitBrief;
|
|
16
|
+
export const readGitSubject = impl.readGitSubject;
|
|
17
|
+
export const readPlanLine = impl.readPlanLine;
|
|
18
|
+
export const buildRepertoireResume = impl.buildRepertoireResume;
|
|
19
|
+
export const persistRepertoireWorking = impl.persistRepertoireWorking;
|
|
20
|
+
export const readRepertoireWorking = impl.readRepertoireWorking;
|
|
21
|
+
export const formatWorkingLine = impl.formatWorkingLine;
|
|
22
|
+
export const applyStationHeat = impl.applyStationHeat;
|
|
23
|
+
export const formatStationMarkdown = impl.formatStationMarkdown;
|
|
24
|
+
export const writeStationMarkdown = impl.writeStationMarkdown;
|