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
|
@@ -24,8 +24,8 @@ import { syncBuiltinSkills } from '../../cli/commands/skill-install.js';
|
|
|
24
24
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
25
25
|
const packageRoot = path.resolve(__dirname, '..', '..', '..');
|
|
26
26
|
const requireCjs = createRequire(import.meta.url);
|
|
27
|
-
const { resolveConsumerTargetDir } = requireCjs(path.join(packageRoot, 'scripts/node/install-bridges.cjs'));
|
|
28
|
-
const { XRAY_MCP_SERVERS } = requireCjs(path.join(packageRoot, 'scripts/node/bridge-mcp-wiring.cjs'));
|
|
27
|
+
const { resolveConsumerTargetDir, patchGrokHooks } = requireCjs(path.join(packageRoot, 'scripts/node/install-bridges.cjs'));
|
|
28
|
+
const { XRAY_MCP_SERVERS, resolveRepertoireMcp } = requireCjs(path.join(packageRoot, 'scripts/node/bridge-mcp-wiring.cjs'));
|
|
29
29
|
function registerGrokMcpServers(targetDir) {
|
|
30
30
|
try {
|
|
31
31
|
execSync('which grok', { stdio: 'ignore' });
|
|
@@ -90,6 +90,17 @@ export async function installForGrokCLI(options = {}) {
|
|
|
90
90
|
if (globalCopied > 0) {
|
|
91
91
|
console.log(`\x1b[32m✓ Synced ${globalCopied} builtin skills to ~/.grok/skills/\x1b[0m`);
|
|
92
92
|
}
|
|
93
|
+
pinGrokPluginToInstalledDist(targetPluginDir, packageRoot, targetDir);
|
|
94
|
+
wearGrokHookCommands(targetPluginDir, packageRoot, targetDir);
|
|
95
|
+
const projectPluginDir = path.join(targetDir, '.grok', 'plugins', '0xray');
|
|
96
|
+
if (projectPluginDir !== targetPluginDir) {
|
|
97
|
+
if (!fs.existsSync(projectPluginDir) || options.force) {
|
|
98
|
+
fs.cpSync(sourceDir, projectPluginDir, { recursive: true, force: true });
|
|
99
|
+
}
|
|
100
|
+
pinGrokPluginToInstalledDist(projectPluginDir, packageRoot, targetDir);
|
|
101
|
+
wearGrokHookCommands(projectPluginDir, packageRoot, targetDir);
|
|
102
|
+
}
|
|
103
|
+
writeProjectRepertoireMcp(targetDir);
|
|
93
104
|
// Attempt auto-trust (best effort)
|
|
94
105
|
try {
|
|
95
106
|
execSync(`grok plugins trust "${targetPluginDir}"`, { stdio: 'ignore' });
|
|
@@ -106,11 +117,88 @@ export async function installForGrokCLI(options = {}) {
|
|
|
106
117
|
console.log('Restart Grok or run `grok` to load the new hooks and MCP servers.');
|
|
107
118
|
}
|
|
108
119
|
catch (err) {
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
121
|
+
frameworkLogger.log('grok-integration', 'install-error', 'error', { error: message });
|
|
122
|
+
console.error('Failed to install Grok plugin:', message);
|
|
111
123
|
}
|
|
112
124
|
frameworkLogger.log('grok-integration', 'install-complete', 'info', {});
|
|
113
125
|
}
|
|
126
|
+
function wearGrokHookCommands(pluginDir, xrayRoot, targetDir) {
|
|
127
|
+
patchGrokHooks(pluginDir, xrayRoot, targetDir, (label, action, status, details) => {
|
|
128
|
+
const level = status === 'success' ||
|
|
129
|
+
status === 'error' ||
|
|
130
|
+
status === 'info' ||
|
|
131
|
+
status === 'debug' ||
|
|
132
|
+
status === 'warning'
|
|
133
|
+
? status
|
|
134
|
+
: 'info';
|
|
135
|
+
frameworkLogger.log(label, action, level, details ?? {});
|
|
136
|
+
}, 'grok-install');
|
|
137
|
+
}
|
|
138
|
+
function pinGrokPluginToInstalledDist(pluginDir, xrayRoot, targetDir) {
|
|
139
|
+
const hookJs = path.join(xrayRoot, 'dist/integrations/grok/hooks/pre-tool-use.js');
|
|
140
|
+
const cliJs = path.join(xrayRoot, 'dist/cli/index.js');
|
|
141
|
+
if (!fs.existsSync(hookJs))
|
|
142
|
+
return;
|
|
143
|
+
const hooksPath = path.join(pluginDir, 'hooks', 'hooks.json');
|
|
144
|
+
if (fs.existsSync(hooksPath)) {
|
|
145
|
+
const text = fs.readFileSync(hooksPath, 'utf8');
|
|
146
|
+
fs.writeFileSync(hooksPath, text.split('${XRAY_AI_PATH:-node_modules/0xray}').join(xrayRoot));
|
|
147
|
+
}
|
|
148
|
+
const mcpPath = path.join(pluginDir, '.mcp.json');
|
|
149
|
+
if (fs.existsSync(mcpPath) && fs.existsSync(cliJs)) {
|
|
150
|
+
const mcp = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
|
151
|
+
for (const server of Object.values(mcp.mcpServers ?? {})) {
|
|
152
|
+
if (server.command === 'npx' && Array.isArray(server.args) && server.args.includes('mcp')) {
|
|
153
|
+
const mcpIdx = server.args.indexOf('mcp');
|
|
154
|
+
const mcpCmd = server.args[mcpIdx + 1] ?? 'governance';
|
|
155
|
+
server.command = 'node';
|
|
156
|
+
server.args = [cliJs, 'mcp', mcpCmd];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const repertoireMcp = resolveRepertoireMcp(targetDir);
|
|
160
|
+
if (mcp.mcpServers) {
|
|
161
|
+
if (repertoireMcp) {
|
|
162
|
+
mcp.mcpServers.repertoire = {
|
|
163
|
+
command: 'node',
|
|
164
|
+
args: [repertoireMcp],
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
delete mcp.mcpServers.repertoire;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
fs.writeFileSync(mcpPath, `${JSON.stringify(mcp, null, 2)}\n`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Grok TUI reads <project>/.grok/config.toml, not the package copy. */
|
|
175
|
+
export function writeProjectRepertoireMcp(projectRoot) {
|
|
176
|
+
const repertoireMcp = resolveRepertoireMcp(projectRoot);
|
|
177
|
+
if (!repertoireMcp)
|
|
178
|
+
return null;
|
|
179
|
+
const grokDir = path.join(projectRoot, '.grok');
|
|
180
|
+
fs.mkdirSync(grokDir, { recursive: true });
|
|
181
|
+
const tomlPath = path.join(grokDir, 'config.toml');
|
|
182
|
+
const block = `[mcp_servers.repertoire]
|
|
183
|
+
command = "node"
|
|
184
|
+
args = [${JSON.stringify(repertoireMcp)}]
|
|
185
|
+
enabled = true
|
|
186
|
+
`;
|
|
187
|
+
let existing = '';
|
|
188
|
+
if (fs.existsSync(tomlPath)) {
|
|
189
|
+
existing = fs.readFileSync(tomlPath, 'utf8');
|
|
190
|
+
}
|
|
191
|
+
if (/\[mcp_servers\.repertoire\]/.test(existing)) {
|
|
192
|
+
existing = existing.replace(/\[mcp_servers\.repertoire\][\s\S]*?(?=\n\[|$)/, block.trim());
|
|
193
|
+
fs.writeFileSync(tomlPath, existing.endsWith('\n') ? existing : `${existing}\n`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const prefix = existing.trim() ? `${existing.trim()}\n\n` : '';
|
|
197
|
+
fs.writeFileSync(tomlPath, `${prefix}${block}`);
|
|
198
|
+
}
|
|
199
|
+
return tomlPath;
|
|
200
|
+
}
|
|
114
201
|
export default {
|
|
115
202
|
installForGrokCLI,
|
|
203
|
+
writeProjectRepertoireMcp,
|
|
116
204
|
};
|
|
@@ -17,9 +17,16 @@ import {
|
|
|
17
17
|
getActivePendingDelegations,
|
|
18
18
|
validateSpawnMatchesTodo,
|
|
19
19
|
updatePlanTodoStatusInPlace,
|
|
20
|
+
loadDelegationGateFeatures,
|
|
20
21
|
} from '../../hooks/delegation-gate-runtime.mjs';
|
|
21
22
|
import { isConferPendingForSession } from '../../hooks/confer-hook-runtime.mjs';
|
|
22
23
|
import { getActiveUserAsideBoot } from '../../hooks/user-aside-hook-runtime.mjs';
|
|
24
|
+
import {
|
|
25
|
+
applyStationHeat,
|
|
26
|
+
buildRepertoireResume as stationRepertoireResume,
|
|
27
|
+
readExistingBoot,
|
|
28
|
+
writeStationMarkdown,
|
|
29
|
+
} from '../../hooks/station-hook-runtime.mjs';
|
|
23
30
|
|
|
24
31
|
export {
|
|
25
32
|
checkPendingDelegationGate,
|
|
@@ -131,9 +138,20 @@ export function resolveSiblingWorkspaceRoots(root = workspaceRoot()) {
|
|
|
131
138
|
}
|
|
132
139
|
}
|
|
133
140
|
|
|
141
|
+
export function buildRepertoireResume(root = workspaceRoot()) {
|
|
142
|
+
return stationRepertoireResume(root);
|
|
143
|
+
}
|
|
144
|
+
|
|
134
145
|
export function loadFeatures(root = workspaceRoot()) {
|
|
135
146
|
const featuresPath = resolveFeaturesPath(root);
|
|
136
|
-
if (!featuresPath)
|
|
147
|
+
if (!featuresPath) {
|
|
148
|
+
return {
|
|
149
|
+
lead_dev_mode: true,
|
|
150
|
+
no_new_surface: true,
|
|
151
|
+
per_suite_triage: true,
|
|
152
|
+
grok_postprocessor_light: false,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
137
155
|
try {
|
|
138
156
|
const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
|
|
139
157
|
const orch = data.multi_agent_orchestration ?? {};
|
|
@@ -142,6 +160,7 @@ export function loadFeatures(root = workspaceRoot()) {
|
|
|
142
160
|
no_new_surface: orch.no_new_surface !== false,
|
|
143
161
|
per_suite_test_triage: orch.per_suite_test_triage !== false,
|
|
144
162
|
auto_chain_delegations: orch.auto_chain_delegations !== false,
|
|
163
|
+
grok_postprocessor_light: data.grok_postprocessor_light === true,
|
|
145
164
|
sibling_repos: resolveSiblingWorkspaceRoots(root),
|
|
146
165
|
};
|
|
147
166
|
} catch {
|
|
@@ -150,6 +169,7 @@ export function loadFeatures(root = workspaceRoot()) {
|
|
|
150
169
|
no_new_surface: true,
|
|
151
170
|
per_suite_triage: true,
|
|
152
171
|
auto_chain_delegations: true,
|
|
172
|
+
grok_postprocessor_light: false,
|
|
153
173
|
sibling_repos: [],
|
|
154
174
|
};
|
|
155
175
|
}
|
|
@@ -188,9 +208,11 @@ export function extractToolContext(event) {
|
|
|
188
208
|
return { toolName, toolInput, paths, content, cmd: String(toolInput.command || '') };
|
|
189
209
|
}
|
|
190
210
|
|
|
191
|
-
export function checkCodexPatterns(content) {
|
|
211
|
+
export function checkCodexPatterns(content, options = {}) {
|
|
192
212
|
if (!content) return null;
|
|
193
|
-
|
|
213
|
+
const only = Array.isArray(options.terms) ? options.terms : null;
|
|
214
|
+
for (const { message, pattern, terms } of CODEX_BLOCK_PATTERNS) {
|
|
215
|
+
if (only && !terms.some((n) => only.includes(n))) continue;
|
|
194
216
|
if (pattern.test(content)) return message;
|
|
195
217
|
pattern.lastIndex = 0;
|
|
196
218
|
}
|
|
@@ -259,16 +281,27 @@ export function buildSessionBootPayload(root, source = '0xray/grok-session-start
|
|
|
259
281
|
extra.sessionId || process.env.GROK_SESSION_ID || process.env.GROK_SESSION || null;
|
|
260
282
|
const conferPending = loadConferPending(root, sessionId);
|
|
261
283
|
const userAsideBoot = getActiveUserAsideBoot(root, sessionId);
|
|
284
|
+
const gateFeatures = loadDelegationGateFeatures(root, 'grok');
|
|
285
|
+
const frontier = gateFeatures.ceremony === 'lite';
|
|
286
|
+
const existing = readExistingBoot(root);
|
|
287
|
+
const heat = applyStationHeat(root, extra.host || 'grok', extra, existing);
|
|
262
288
|
return {
|
|
263
289
|
hook: source,
|
|
264
290
|
lead_dev_mode: features.lead_dev_mode,
|
|
265
291
|
no_new_surface: features.no_new_surface,
|
|
292
|
+
host: extra.host || 'grok',
|
|
293
|
+
suit_profile: gateFeatures.suit_profile ?? 'guided',
|
|
294
|
+
ceremony: gateFeatures.ceremony ?? 'full',
|
|
295
|
+
spawn_plan_mode: gateFeatures.spawn_plan_mode ?? 'deny',
|
|
266
296
|
codexBlockingTermCount: blockingTerms.length,
|
|
267
297
|
codexTerms: [59, 67, 68, 69],
|
|
268
298
|
rules: features.lead_dev_mode ? LEAD_DEV_RULES : [],
|
|
269
|
-
mcpIntake:
|
|
270
|
-
|
|
299
|
+
mcpIntake: frontier
|
|
300
|
+
? 'xray-orchestrator analyze-complexity optional on frontier (spawn warns, does not deny)'
|
|
301
|
+
: 'xray-orchestrator → analyze-complexity (required before spawn_subagent)',
|
|
302
|
+
enforcement: 'PreToolUse hook — Codex constitution always on; ceremony scales by suit_temperament',
|
|
271
303
|
workspaceRoot: root,
|
|
304
|
+
...heat,
|
|
272
305
|
...(siblingRoots.length > 0 ? { siblingWorkspaceRoots: siblingRoots } : {}),
|
|
273
306
|
...(conferPending ? { conferPending: true, conferTrigger: 'analyze-complexity at synthesis checkpoint' } : {}),
|
|
274
307
|
...(userAsideBoot ?? {}),
|
|
@@ -276,6 +309,7 @@ export function buildSessionBootPayload(root, source = '0xray/grok-session-start
|
|
|
276
309
|
timestamp: new Date().toISOString(),
|
|
277
310
|
source,
|
|
278
311
|
...extra,
|
|
312
|
+
...heat,
|
|
279
313
|
};
|
|
280
314
|
}
|
|
281
315
|
|
|
@@ -284,19 +318,31 @@ export function writeSessionBoot(root, payload) {
|
|
|
284
318
|
const stateDir = path.join(root, '.xray', 'state');
|
|
285
319
|
fs.mkdirSync(stateDir, { recursive: true });
|
|
286
320
|
fs.writeFileSync(sessionBootPath(root), JSON.stringify(payload, null, 2));
|
|
321
|
+
writeStationMarkdown(root, payload);
|
|
287
322
|
return sessionBootPath(root);
|
|
288
323
|
} catch {
|
|
289
324
|
return null;
|
|
290
325
|
}
|
|
291
326
|
}
|
|
292
327
|
|
|
293
|
-
|
|
328
|
+
export function sessionBootNeedsRefresh(existing, root) {
|
|
329
|
+
if (!existing || typeof existing !== 'object') return true;
|
|
330
|
+
if (existing.lead_dev_mode === undefined) return true;
|
|
331
|
+
if (existing.host !== 'grok') return true;
|
|
332
|
+
if (!existing.suit_profile) return true;
|
|
333
|
+
if (existing.workspaceRoot && existing.workspaceRoot !== root) return true;
|
|
334
|
+
if (!existing.repertoireResume) return true;
|
|
335
|
+
if (!existing.stationLine) return true;
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Boot on SessionStart, UserPromptSubmit, or first PreToolUse if missing/stale. */
|
|
294
340
|
export function ensureSessionBoot(root = workspaceRoot(), source = '0xray/grok-boot') {
|
|
295
341
|
const bootPath = sessionBootPath(root);
|
|
296
342
|
if (fs.existsSync(bootPath)) {
|
|
297
343
|
try {
|
|
298
344
|
const existing = JSON.parse(fs.readFileSync(bootPath, 'utf8'));
|
|
299
|
-
if (existing
|
|
345
|
+
if (!sessionBootNeedsRefresh(existing, root)) return bootPath;
|
|
300
346
|
} catch {
|
|
301
347
|
/* rewrite corrupt boot */
|
|
302
348
|
}
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
extractToolContext,
|
|
9
9
|
isOrchestrateToolEvent,
|
|
10
10
|
isSubagentTool,
|
|
11
|
+
isWriteTool,
|
|
12
|
+
loadFeatures,
|
|
11
13
|
readStdinJson,
|
|
12
14
|
resolveSessionId,
|
|
13
15
|
workspaceRoot,
|
|
@@ -17,7 +19,7 @@ import {
|
|
|
17
19
|
evaluatePostToolSpawn,
|
|
18
20
|
isOrchestrateToolEvent as gateIsOrchestrateToolEvent,
|
|
19
21
|
} from '../../hooks/delegation-gate-runtime.mjs';
|
|
20
|
-
import { recordRoutingOutcome } from '../../hooks/pipeline-hook-runtime.mjs';
|
|
22
|
+
import { recordRoutingOutcome, runGrokPostprocessorLight } from '../../hooks/pipeline-hook-runtime.mjs';
|
|
21
23
|
|
|
22
24
|
function extractToolOutput(event) {
|
|
23
25
|
return (
|
|
@@ -30,60 +32,77 @@ function extractToolOutput(event) {
|
|
|
30
32
|
);
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const eventRoot = event.workspaceRoot || event.cwd || root;
|
|
38
|
-
const sessionId = resolveSessionId(event);
|
|
39
|
-
const { toolName, toolInput } = extractToolContext(event);
|
|
35
|
+
export function handlePostToolUse(event, root = workspaceRoot()) {
|
|
36
|
+
const eventRoot = event.workspaceRoot || event.cwd || root;
|
|
37
|
+
const sessionId = resolveSessionId(event);
|
|
38
|
+
const { toolName, toolInput } = extractToolContext(event);
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
if (isOrchestrateToolEvent(toolName, toolInput) || gateIsOrchestrateToolEvent(toolName, toolInput)) {
|
|
41
|
+
appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-pending', 'info', {
|
|
42
|
+
tool: toolName,
|
|
43
|
+
sessionId,
|
|
44
|
+
note: 'orchestrate-task completed — pending-delegations.json written by task-handler',
|
|
45
|
+
});
|
|
46
|
+
try {
|
|
47
|
+
recordRoutingOutcome(eventRoot, {
|
|
43
48
|
tool: toolName,
|
|
49
|
+
agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'orchestrate-task',
|
|
50
|
+
planTodoId: toolInput?.planTodoId ?? null,
|
|
44
51
|
sessionId,
|
|
45
|
-
note: 'orchestrate-task completed — pending-delegations.json written by task-handler',
|
|
46
52
|
});
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
tool: toolName,
|
|
50
|
-
agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'orchestrate-task',
|
|
51
|
-
planTodoId: toolInput?.planTodoId ?? null,
|
|
52
|
-
sessionId,
|
|
53
|
-
});
|
|
54
|
-
} catch {
|
|
55
|
-
/* non-blocking */
|
|
56
|
-
}
|
|
53
|
+
} catch {
|
|
54
|
+
/* non-blocking */
|
|
57
55
|
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const features = loadFeatures(eventRoot);
|
|
59
|
+
if (features.grok_postprocessor_light === true && isWriteTool(toolName)) {
|
|
60
|
+
try {
|
|
61
|
+
const paths = [
|
|
62
|
+
toolInput?.path,
|
|
63
|
+
toolInput?.filePath,
|
|
64
|
+
toolInput?.file_path,
|
|
65
|
+
].filter(Boolean);
|
|
66
|
+
runGrokPostprocessorLight(eventRoot, { tool: toolName, paths });
|
|
67
|
+
} catch {
|
|
68
|
+
/* non-blocking */
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (isSubagentTool(toolName)) {
|
|
73
|
+
const spawnResult = evaluatePostToolSpawn(toolName, toolInput, eventRoot, {
|
|
74
|
+
toolOutput: extractToolOutput(event),
|
|
75
|
+
sessionId,
|
|
76
|
+
});
|
|
58
77
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
if (spawnResult.satisfied.length > 0 || spawnResult.expectedTodoId) {
|
|
79
|
+
appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-cleared', 'success', {
|
|
80
|
+
tool: toolName,
|
|
81
|
+
satisfied: spawnResult.satisfied.map((d) => d.id),
|
|
82
|
+
clearedAll: spawnResult.clearedAll,
|
|
83
|
+
planTodoId: spawnResult.expectedTodoId ?? null,
|
|
84
|
+
receiptRecorded: spawnResult.receiptRecorded ?? false,
|
|
85
|
+
todoCompleted: spawnResult.todoCompleted ?? false,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
recordRoutingOutcome(eventRoot, {
|
|
90
|
+
tool: toolName,
|
|
91
|
+
agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'subagent',
|
|
92
|
+
planTodoId: toolInput?.planTodoId ?? spawnResult.expectedTodoId ?? null,
|
|
62
93
|
sessionId,
|
|
63
94
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-cleared', 'success', {
|
|
67
|
-
tool: toolName,
|
|
68
|
-
satisfied: spawnResult.satisfied.map((d) => d.id),
|
|
69
|
-
clearedAll: spawnResult.clearedAll,
|
|
70
|
-
planTodoId: spawnResult.expectedTodoId ?? null,
|
|
71
|
-
receiptRecorded: spawnResult.receiptRecorded ?? false,
|
|
72
|
-
todoCompleted: spawnResult.todoCompleted ?? false,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
recordRoutingOutcome(eventRoot, {
|
|
77
|
-
tool: toolName,
|
|
78
|
-
agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'subagent',
|
|
79
|
-
planTodoId: toolInput?.planTodoId ?? spawnResult.expectedTodoId ?? null,
|
|
80
|
-
sessionId,
|
|
81
|
-
});
|
|
82
|
-
} catch {
|
|
83
|
-
/* non-blocking */
|
|
84
|
-
}
|
|
95
|
+
} catch {
|
|
96
|
+
/* non-blocking */
|
|
85
97
|
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
86
100
|
|
|
101
|
+
async function main() {
|
|
102
|
+
const root = workspaceRoot();
|
|
103
|
+
try {
|
|
104
|
+
const event = await readStdinJson();
|
|
105
|
+
handlePostToolUse(event, root);
|
|
87
106
|
process.exit(0);
|
|
88
107
|
} catch (err) {
|
|
89
108
|
appendHookActivity(root, 'grok-post-tool-use', 'hook-error', 'error', {
|
|
@@ -93,4 +112,7 @@ async function main() {
|
|
|
93
112
|
}
|
|
94
113
|
}
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
const launchedAsCli = Boolean(process.argv[1] && process.argv[1].endsWith('post-tool-use.js'));
|
|
116
|
+
if (launchedAsCli) {
|
|
117
|
+
main();
|
|
118
|
+
}
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
checkCodexPatterns,
|
|
13
13
|
checkFullTestSuite,
|
|
14
|
-
checkSurfaceArea,
|
|
15
14
|
ensureSessionBoot,
|
|
16
15
|
isShellTool,
|
|
17
16
|
isWriteTool,
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
workspaceRoot,
|
|
22
21
|
} from './grok-hook-utils.js';
|
|
23
22
|
import { appendHookActivity } from './grok-hook-activity.js';
|
|
24
|
-
import { runGrokPostprocessorLight } from '../../hooks/pipeline-hook-runtime.mjs';
|
|
25
23
|
|
|
26
24
|
function finish(root, decision, reason, hint, toolName, extra = {}) {
|
|
27
25
|
const out = { decision, ...extra };
|
|
@@ -47,10 +45,10 @@ async function main() {
|
|
|
47
45
|
ensureSessionBoot(eventRoot, '0xray/grok-pre-tool-use-boot');
|
|
48
46
|
|
|
49
47
|
const features = loadFeatures(eventRoot);
|
|
50
|
-
const gateFeatures = loadDelegationGateFeatures(eventRoot);
|
|
48
|
+
const gateFeatures = loadDelegationGateFeatures(eventRoot, 'grok');
|
|
51
49
|
const ctx = extractFromEvent(event);
|
|
52
50
|
toolName = ctx.toolName;
|
|
53
|
-
const {
|
|
51
|
+
const { content, cmd, toolInput } = ctx;
|
|
54
52
|
const sessionId = resolveSessionId(event);
|
|
55
53
|
|
|
56
54
|
const gateBlock = evaluatePreToolGate(toolName, toolInput, {
|
|
@@ -70,6 +68,18 @@ async function main() {
|
|
|
70
68
|
);
|
|
71
69
|
}
|
|
72
70
|
|
|
71
|
+
// Constitution (11/29/69 + destructive shell) is in evaluatePreToolGate.
|
|
72
|
+
// Grok extra: Codex 2/7 (TODO/FIXME/STUB, console.log).
|
|
73
|
+
if (isWriteTool(toolName) && content) {
|
|
74
|
+
const extraBlock = checkCodexPatterns(content, { terms: [2, 7] });
|
|
75
|
+
if (extraBlock) finish(eventRoot, 'deny', extraBlock, null, toolName);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isShellTool(toolName) && cmd) {
|
|
79
|
+
const testHint = checkFullTestSuite(cmd, features);
|
|
80
|
+
if (testHint) finish(eventRoot, 'allow', null, testHint, toolName);
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
if (gateBlock.reason) {
|
|
74
84
|
finish(
|
|
75
85
|
eventRoot,
|
|
@@ -81,33 +91,6 @@ async function main() {
|
|
|
81
91
|
);
|
|
82
92
|
}
|
|
83
93
|
|
|
84
|
-
if (features.no_new_surface && isWriteTool(toolName) && paths.length) {
|
|
85
|
-
const surfaceBlock = checkSurfaceArea(paths, eventRoot);
|
|
86
|
-
if (surfaceBlock) finish(eventRoot, 'deny', surfaceBlock, null, toolName);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (isWriteTool(toolName) && content) {
|
|
90
|
-
const codexBlock = checkCodexPatterns(content);
|
|
91
|
-
if (codexBlock) finish(eventRoot, 'deny', codexBlock, null, toolName);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (isShellTool(toolName) && cmd) {
|
|
95
|
-
const destructive =
|
|
96
|
-
/\brm\s+-rf\s+\/\b|\bmkfs\b|\bdd\s+if=|:()\s*\{\s*:\|&\s*\}\s*;:/i.test(cmd);
|
|
97
|
-
if (destructive) finish(eventRoot, 'deny', 'Blocked destructive shell command', null, toolName);
|
|
98
|
-
|
|
99
|
-
const testHint = checkFullTestSuite(cmd, features);
|
|
100
|
-
if (testHint) finish(eventRoot, 'allow', null, testHint, toolName);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (features.grok_postprocessor_light === true && isWriteTool(toolName)) {
|
|
104
|
-
try {
|
|
105
|
-
runGrokPostprocessorLight(eventRoot, { tool: toolName, paths });
|
|
106
|
-
} catch {
|
|
107
|
-
/* non-blocking */
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
94
|
finish(eventRoot, 'allow', null, null, toolName);
|
|
112
95
|
} catch (err) {
|
|
113
96
|
appendHookActivity(root, 'grok-pre-tool-use', 'hook-error', 'error', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Grok SessionStart / UserPromptSubmit
|
|
4
|
-
*
|
|
3
|
+
* Grok SessionStart / UserPromptSubmit / PreCompact / PostCompact.
|
|
4
|
+
* Grok ignores stdout here; station heat is session-boot.json + STATION.md.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
@@ -26,17 +26,89 @@ function resolveHookEvent(event) {
|
|
|
26
26
|
if (process.env.GROK_HOOK_EVENT) return process.env.GROK_HOOK_EVENT;
|
|
27
27
|
const flag = process.argv.find((a) => a.startsWith('--hook-event='));
|
|
28
28
|
if (flag) return flag.slice('--hook-event='.length);
|
|
29
|
+
const named = event.hookEventName || event.hook;
|
|
30
|
+
if (named === 'PreCompact' || named === 'pre_compact') return 'pre_compact';
|
|
31
|
+
if (named === 'PostCompact' || named === 'post_compact') return 'post_compact';
|
|
29
32
|
if (
|
|
30
33
|
event.prompt != null ||
|
|
31
34
|
event.userMessage != null ||
|
|
32
35
|
event.user_prompt != null ||
|
|
33
|
-
|
|
36
|
+
named === 'UserPromptSubmit' ||
|
|
37
|
+
named === 'user_prompt_submit'
|
|
34
38
|
) {
|
|
35
39
|
return 'user_prompt_submit';
|
|
36
40
|
}
|
|
37
41
|
return 'session_start';
|
|
38
42
|
}
|
|
39
43
|
|
|
44
|
+
function extractIntent(event) {
|
|
45
|
+
return event.prompt || event.userMessage || event.user_prompt || event.compactContext || null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function loadStationProvider(root) {
|
|
49
|
+
const { loadMemoryRoutingProvider } = await import('../../../memory-routing/index.js');
|
|
50
|
+
const { readFileSync, existsSync } = await import('node:fs');
|
|
51
|
+
const { join } = await import('node:path');
|
|
52
|
+
let routing = { enabled: false, provider: 'null' };
|
|
53
|
+
const featuresPath = join(root, '.xray', 'features.json');
|
|
54
|
+
if (existsSync(featuresPath)) {
|
|
55
|
+
try {
|
|
56
|
+
routing = JSON.parse(readFileSync(featuresPath, 'utf8')).memory_routing || routing;
|
|
57
|
+
} catch {
|
|
58
|
+
/* leftover default */
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return loadMemoryRoutingProvider(routing, root);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function matchStationSignals(root, intent) {
|
|
65
|
+
if (!intent) return [];
|
|
66
|
+
try {
|
|
67
|
+
const provider = await loadStationProvider(root);
|
|
68
|
+
if (!provider || provider.id === 'null' || typeof provider.getTaskConfidence !== 'function') {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const conf = provider.getTaskConfidence({
|
|
72
|
+
id: 'station',
|
|
73
|
+
description: String(intent),
|
|
74
|
+
type: 'station',
|
|
75
|
+
});
|
|
76
|
+
const names = Array.isArray(conf.matchedSignals) ? conf.matchedSignals : [];
|
|
77
|
+
const safe = [];
|
|
78
|
+
for (const signalName of names) {
|
|
79
|
+
const name = String(signalName || '').trim();
|
|
80
|
+
if (!name || name.toLowerCase().startsWith('bedrock-')) continue;
|
|
81
|
+
safe.push(name);
|
|
82
|
+
if (safe.length >= 4) break;
|
|
83
|
+
}
|
|
84
|
+
return safe;
|
|
85
|
+
} catch {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const COMPACT_EVENTS = new Set(['pre_compact', 'post_compact']);
|
|
91
|
+
|
|
92
|
+
async function ingestStationFeedback(root, sessionId, hookEvent, matchedSignals) {
|
|
93
|
+
if (!COMPACT_EVENTS.has(hookEvent) || !matchedSignals.length) return;
|
|
94
|
+
try {
|
|
95
|
+
const provider = await loadStationProvider(root);
|
|
96
|
+
if (!provider || typeof provider.ingestFeedback !== 'function') return;
|
|
97
|
+
provider.ingestFeedback({
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
sessionId: sessionId || 'station',
|
|
100
|
+
taskId: `station-${hookEvent}`,
|
|
101
|
+
assignedAgent: 'station',
|
|
102
|
+
memorySignals: matchedSignals,
|
|
103
|
+
complexity: 0,
|
|
104
|
+
success: true,
|
|
105
|
+
durationMs: 0,
|
|
106
|
+
});
|
|
107
|
+
} catch {
|
|
108
|
+
/* working-state file is the session memory; registry ingest is best-effort */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
40
112
|
async function main() {
|
|
41
113
|
const root = workspaceRoot();
|
|
42
114
|
let HOOK_EVENT = 'session_start';
|
|
@@ -68,19 +140,29 @@ async function main() {
|
|
|
68
140
|
const source =
|
|
69
141
|
HOOK_EVENT === 'user_prompt_submit'
|
|
70
142
|
? '0xray/grok-user-prompt-submit'
|
|
71
|
-
: '
|
|
143
|
+
: HOOK_EVENT === 'pre_compact' || HOOK_EVENT === 'post_compact'
|
|
144
|
+
? '0xray/grok-compact'
|
|
145
|
+
: '0xray/grok-session-start';
|
|
72
146
|
|
|
147
|
+
const intent = extractIntent(event);
|
|
148
|
+
const matchedSignals = await matchStationSignals(eventRoot, intent);
|
|
73
149
|
const payload = buildSessionBootPayload(eventRoot, source, {
|
|
74
150
|
hookEvent: HOOK_EVENT,
|
|
75
151
|
sessionId: event.sessionId || process.env.GROK_SESSION_ID || null,
|
|
152
|
+
...(intent ? { intent } : {}),
|
|
153
|
+
...(matchedSignals.length ? { matchedSignals } : {}),
|
|
76
154
|
});
|
|
77
155
|
|
|
78
156
|
const bootPath = writeSessionBoot(eventRoot, payload) || ensureSessionBoot(eventRoot, source);
|
|
157
|
+
await ingestStationFeedback(eventRoot, sessionId, HOOK_EVENT, matchedSignals);
|
|
79
158
|
|
|
80
159
|
appendHookActivity(eventRoot, 'grok-session-start', 'session-boot-written', 'success', {
|
|
81
160
|
bootPath,
|
|
82
161
|
hookEvent: HOOK_EVENT,
|
|
83
162
|
lead_dev_mode: payload.lead_dev_mode,
|
|
163
|
+
repertoireResume: payload.repertoireResume,
|
|
164
|
+
stationLine: payload.stationLine,
|
|
165
|
+
hotSwap: payload.hotSwap || null,
|
|
84
166
|
});
|
|
85
167
|
|
|
86
168
|
try {
|