0xray 3.5.4 → 4.0.0
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 +51 -7
- 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 +32 -6
- package/.xray/features.schema.json +87 -0
- package/AGENTS-consumer.md +16 -6
- package/AGENTS.md +21 -3
- package/README.md +13 -10
- package/SKILLS.md +1 -1
- package/dist/AGENTS.md +21 -3
- package/dist/CHANGELOG.md +98 -0
- package/dist/README.md +13 -10
- package/dist/SKILLS.md +1 -1
- package/dist/cli/commands/hermes-install.js +6 -1
- package/dist/cli/commands/openclaw-install.js +14 -0
- package/dist/cli/index.js +0 -0
- package/dist/core/features-config.d.ts +30 -2
- package/dist/governance/governance-service.d.ts +1 -0
- package/dist/governance/governance-service.js +81 -6
- package/dist/infrastructure/schemas/cloud-schemas.d.ts +1 -1
- package/dist/integrations/enforcement-gate.js +15 -5
- package/dist/integrations/grok/grok-cli.d.ts +3 -0
- package/dist/integrations/grok/grok-cli.js +92 -13
- package/dist/integrations/grok/hooks/grok-hook-utils.js +99 -9
- package/dist/integrations/grok/hooks/post-tool-use.js +68 -25
- package/dist/integrations/grok/hooks/pre-tool-use.js +17 -14
- package/dist/integrations/grok/hooks/session-start.js +114 -4
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +31 -24
- package/dist/integrations/hermes-agent/__init__.py +11 -1
- package/dist/integrations/hermes-agent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/schemas.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/tools.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/bridge.mjs +92 -11
- package/dist/integrations/hooks/confer-hook-runtime.mjs +49 -0
- package/dist/integrations/hooks/delegation-gate-runtime.mjs +32 -3
- package/dist/integrations/hooks/pipeline-hook-runtime.mjs +211 -0
- package/dist/integrations/hooks/plan-hook-runtime.mjs +68 -0
- 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/hooks/user-aside-hook-runtime.mjs +49 -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 +10 -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/architect-tools.server.js +6 -1
- package/dist/mcps/orchestrator/handlers/complexity-handler.d.ts +7 -0
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +107 -8
- package/dist/mcps/orchestrator/handlers/task-handler.d.ts +6 -0
- package/dist/mcps/orchestrator/handlers/task-handler.js +75 -0
- package/dist/mcps/orchestrator/server.js +54 -5
- 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 +74 -4
- package/dist/memory-routing/provider-registry.js +3 -2
- package/dist/nucleus/aside-worktree.d.ts +41 -0
- package/dist/nucleus/aside-worktree.js +164 -0
- package/dist/nucleus/autonomy-kernel.d.ts +2 -2
- package/dist/nucleus/autonomy-kernel.js +17 -6
- package/dist/nucleus/confer.d.ts +57 -0
- package/dist/nucleus/confer.js +322 -0
- package/dist/nucleus/delegation-gate.d.ts +18 -8
- package/dist/nucleus/delegation-gate.js +234 -20
- package/dist/nucleus/lead-dev-plan-persistence.d.ts +27 -3
- package/dist/nucleus/lead-dev-plan-persistence.js +201 -19
- package/dist/nucleus/spawn-plan-resolution.d.ts +20 -0
- package/dist/nucleus/spawn-plan-resolution.js +42 -0
- package/dist/nucleus/suit-temperament.d.ts +40 -0
- package/dist/nucleus/suit-temperament.js +157 -0
- package/dist/nucleus/synthesis-consult-receipt.js +18 -2
- package/dist/nucleus/synthesis-context.js +1 -1
- package/dist/nucleus/user-aside.d.ts +70 -0
- package/dist/nucleus/user-aside.js +393 -0
- package/dist/plugin/xray-codex-injection.js +14 -3
- package/dist/postprocessor/PostProcessor.d.ts +1 -0
- package/dist/postprocessor/PostProcessor.js +11 -0
- package/dist/postprocessor/triggers/GitHookTrigger.js +11 -5
- package/dist/processors/implementations/session-summary-processor.d.ts +1 -1
- package/dist/processors/implementations/session-summary-processor.js +9 -6
- package/opencode.json +88 -0
- package/package.json +25 -6
- package/scripts/hooks/install-hooks.cjs +21 -6
- package/scripts/hooks/run-hook.js +237 -88
- package/scripts/mjs/run-repertoire-mcp.mjs +39 -0
- package/scripts/mjs/verify-confer-core.mjs +103 -0
- package/scripts/mjs/verify-delegation-gate-core.mjs +76 -3
- package/scripts/mjs/verify-four-floor-compact.mjs +524 -0
- package/scripts/mjs/verify-hermes-session-start.mjs +137 -0
- package/scripts/mjs/verify-pipeline-facets.mjs +215 -0
- package/scripts/mjs/verify-pre-push-diff-core.mjs +87 -0
- package/scripts/mjs/verify-temperament-live.mjs +261 -0
- package/scripts/mjs/verify-user-aside-core.mjs +137 -0
- package/scripts/node/bridge-mcp-wiring.cjs +287 -29
- package/scripts/node/install-bridges.cjs +198 -44
- package/scripts/node/load-reflection-config.mjs +2 -2
- package/scripts/node/postinstall.cjs +50 -27
- package/scripts/node/release-gate.mjs +8 -4
- package/scripts/node/release.mjs +2 -2
- package/scripts/node/validate-release-docs.mjs +20 -33
- package/scripts/node/version-manager.mjs +25 -10
- 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 +10 -0
- package/src/mcps/architect-tools.server.ts +6 -1
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +180 -21
- package/src/mcps/orchestrator/handlers/task-handler.ts +99 -0
- package/src/mcps/orchestrator/server.ts +56 -5
- 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 +32 -6
- package/xray/features.schema.json +87 -0
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
import { mcpClientManager } from '../mcps/mcp-client.js';
|
|
19
19
|
import { callInProcessSkill } from '../mcps/in-process-skill-registry.js';
|
|
20
20
|
import { getGovernanceIntegration, } from '../integrations/governance/index.js';
|
|
21
|
-
import { mergeVotes } from './governance-core.js';
|
|
21
|
+
import { applyDecisionMatrix, calculateMetamorphosisScore, mergeVotes, } from './governance-core.js';
|
|
22
22
|
import { frameworkLogger } from '../core/framework-logger.js';
|
|
23
|
+
import { featuresConfigLoader } from '../core/features-config.js';
|
|
23
24
|
export class GovernanceService {
|
|
24
25
|
constructor() {
|
|
25
26
|
// We deliberately do *not* cache the integration here.
|
|
@@ -39,7 +40,7 @@ export class GovernanceService {
|
|
|
39
40
|
*/
|
|
40
41
|
async govern(request) {
|
|
41
42
|
const { proposals, context, options } = request;
|
|
42
|
-
const requireExternal = options?.requireExternalDynamo
|
|
43
|
+
const requireExternal = this.resolveRequireExternalDynamo(options?.requireExternalDynamo);
|
|
43
44
|
const timeoutMs = options?.timeoutMs ?? 90000;
|
|
44
45
|
const maxAbstentionThreshold = options?.maxAbstentionThreshold ?? 1.0;
|
|
45
46
|
frameworkLogger.log('governance-service', 'govern-start', 'info', {
|
|
@@ -59,7 +60,7 @@ export class GovernanceService {
|
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
// Run governance with end-to-end timeout
|
|
62
|
-
const result = await this.runGovernanceWithTimeout(proposals, context, requireExternal, timeoutMs);
|
|
63
|
+
const result = await this.runGovernanceWithTimeout(proposals, context, requireExternal, timeoutMs, options?.metamorphosisThreshold);
|
|
63
64
|
// Check abstention threshold
|
|
64
65
|
if (result.results.length > 0 && maxAbstentionThreshold < 1.0) {
|
|
65
66
|
const totalVotes = result.results.reduce((sum, r) => sum + r.votes.length, 0);
|
|
@@ -91,7 +92,26 @@ export class GovernanceService {
|
|
|
91
92
|
},
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
+
resolveRequireExternalDynamo(explicit) {
|
|
96
|
+
if (explicit !== undefined)
|
|
97
|
+
return explicit;
|
|
98
|
+
if (process.env.XRAY_LOCAL_MODE === '1' || process.env.XRAY_LOCAL_MODE === 'true') {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const config = featuresConfigLoader.loadConfig();
|
|
103
|
+
const ig = config.inference_governance;
|
|
104
|
+
if (ig?.require_external_dynamo === false)
|
|
105
|
+
return false;
|
|
106
|
+
if (ig?.local_mode === true)
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
/* default strict */
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
async runGovernanceWithTimeout(proposals, context, requireExternal, timeoutMs, metamorphosisThreshold = 0.7) {
|
|
95
115
|
const controller = new AbortController();
|
|
96
116
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
97
117
|
try {
|
|
@@ -112,12 +132,67 @@ export class GovernanceService {
|
|
|
112
132
|
...(externalVotes[index] || []),
|
|
113
133
|
];
|
|
114
134
|
const merged = mergeVotes(votes);
|
|
135
|
+
const externalVote = votes.find((v) => v.server === 'external-dynamo');
|
|
136
|
+
let finalDecision = merged.finalDecision;
|
|
137
|
+
let averageConfidence = merged.averageConfidence;
|
|
138
|
+
let moralOverride = 'none';
|
|
139
|
+
if (externalVote?.moralTension ||
|
|
140
|
+
externalVote?.moralScore != null ||
|
|
141
|
+
externalVote?.moralFusion != null) {
|
|
142
|
+
const matrixInput = {
|
|
143
|
+
resonance: averageConfidence,
|
|
144
|
+
isotopicRatio: externalVote.moralFusion ?? 0.5,
|
|
145
|
+
};
|
|
146
|
+
if (externalVote.moralTension != null) {
|
|
147
|
+
matrixInput.moralTension = externalVote.moralTension;
|
|
148
|
+
}
|
|
149
|
+
if (externalVote.moralScore != null) {
|
|
150
|
+
matrixInput.moralScore = externalVote.moralScore;
|
|
151
|
+
}
|
|
152
|
+
if (externalVote.moralFusion != null) {
|
|
153
|
+
matrixInput.moralFusion = externalVote.moralFusion;
|
|
154
|
+
}
|
|
155
|
+
const matrix = applyDecisionMatrix(matrixInput);
|
|
156
|
+
moralOverride = matrix.moralOverride ?? 'none';
|
|
157
|
+
if (matrix.recommendation === 'REJECT') {
|
|
158
|
+
finalDecision = 'reject';
|
|
159
|
+
}
|
|
160
|
+
else if (matrix.recommendation === 'NEEDS_REVISION' && finalDecision === 'approve') {
|
|
161
|
+
finalDecision = 'needs_revision';
|
|
162
|
+
}
|
|
163
|
+
else if (matrix.recommendation === 'PASS' && finalDecision !== 'reject') {
|
|
164
|
+
finalDecision = 'approve';
|
|
165
|
+
}
|
|
166
|
+
averageConfidence = matrix.confidence;
|
|
167
|
+
}
|
|
168
|
+
let metamorphosisScore;
|
|
169
|
+
if (proposal.type === 'metamorphosis' || proposal.source === 'metamorphosis') {
|
|
170
|
+
const proposalType = proposal.type === 'compliance'
|
|
171
|
+
? 'compliance'
|
|
172
|
+
: proposal.type === 'automate' || proposal.type === 'codify'
|
|
173
|
+
? proposal.type
|
|
174
|
+
: 'fix';
|
|
175
|
+
const metamorphosisInput = {
|
|
176
|
+
averageConfidence,
|
|
177
|
+
proposalType,
|
|
178
|
+
resonanceScore: averageConfidence,
|
|
179
|
+
};
|
|
180
|
+
if (externalVote?.moralFusion != null) {
|
|
181
|
+
metamorphosisInput.historicalCoherence = externalVote.moralFusion;
|
|
182
|
+
}
|
|
183
|
+
metamorphosisScore = calculateMetamorphosisScore(metamorphosisInput);
|
|
184
|
+
if (metamorphosisScore < metamorphosisThreshold) {
|
|
185
|
+
finalDecision = 'needs_revision';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
115
188
|
return {
|
|
116
189
|
proposalId: proposal.id,
|
|
117
|
-
finalDecision
|
|
118
|
-
averageConfidence
|
|
190
|
+
finalDecision,
|
|
191
|
+
averageConfidence,
|
|
119
192
|
votes,
|
|
120
193
|
reasoningSummary: merged.reasoningSummary,
|
|
194
|
+
moralOverride,
|
|
195
|
+
...(metamorphosisScore != null ? { metamorphosisScore } : {}),
|
|
121
196
|
};
|
|
122
197
|
});
|
|
123
198
|
return { results };
|
|
@@ -252,12 +252,22 @@ export async function afterToolHook(tool, args, _result, _error, _context) {
|
|
|
252
252
|
const result = _result;
|
|
253
253
|
if (result && typeof result === "object" && "title" in result && "description" in result) {
|
|
254
254
|
const { handleGovernRequest } = await import("../nucleus/index.js");
|
|
255
|
+
const localMode = process.env.XRAY_LOCAL_MODE === "1" || process.env.XRAY_LOCAL_MODE === "true";
|
|
255
256
|
const governanceResult = await handleGovernRequest({
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
257
|
+
proposals: [
|
|
258
|
+
{
|
|
259
|
+
id: `gate-${Date.now()}`,
|
|
260
|
+
type: String(result.type || "fix"),
|
|
261
|
+
title: String(result.title || ""),
|
|
262
|
+
description: String(result.description || ""),
|
|
263
|
+
evidence: [],
|
|
264
|
+
source: "manual",
|
|
265
|
+
metadata: result,
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
options: {
|
|
269
|
+
requireExternalDynamo: localMode ? false : undefined,
|
|
270
|
+
},
|
|
261
271
|
});
|
|
262
272
|
governanceTriggered = governanceResult?.overallDecision === 'approve';
|
|
263
273
|
if (governanceTriggered) {
|
|
@@ -19,7 +19,10 @@ export interface GrokInstallOptions {
|
|
|
19
19
|
dryRun?: boolean;
|
|
20
20
|
}
|
|
21
21
|
export declare function installForGrokCLI(options?: GrokInstallOptions): Promise<void>;
|
|
22
|
+
/** Grok TUI reads <project>/.grok/config.toml, not the package copy. */
|
|
23
|
+
export declare function writeProjectRepertoireMcp(projectRoot: string): string | null;
|
|
22
24
|
declare const _default: {
|
|
23
25
|
installForGrokCLI: typeof installForGrokCLI;
|
|
26
|
+
writeProjectRepertoireMcp: typeof writeProjectRepertoireMcp;
|
|
24
27
|
};
|
|
25
28
|
export default _default;
|
|
@@ -24,17 +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
|
-
|
|
29
|
-
const XRAY_MCP_SERVERS = [
|
|
30
|
-
{ name: 'xray-governance', mcpCmd: 'governance', env: { XRAY_FORCE_MCP_GOVERNANCE: 'true' } },
|
|
31
|
-
{ name: 'xray-skills', mcpCmd: 'skills', env: {} },
|
|
32
|
-
{ name: 'xray-orchestrator', mcpCmd: 'orchestrator', env: {} },
|
|
33
|
-
{ name: 'xray-enforcer', mcpCmd: 'enforcer', env: {} },
|
|
34
|
-
{ name: 'xray-researcher', mcpCmd: 'researcher', env: {} },
|
|
35
|
-
{ name: 'xray-code-review', mcpCmd: 'code-review', env: {} },
|
|
36
|
-
{ name: 'xray-architect-tools', mcpCmd: 'architect-tools', env: {} },
|
|
37
|
-
];
|
|
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'));
|
|
38
29
|
function registerGrokMcpServers(targetDir) {
|
|
39
30
|
try {
|
|
40
31
|
execSync('which grok', { stdio: 'ignore' });
|
|
@@ -99,6 +90,17 @@ export async function installForGrokCLI(options = {}) {
|
|
|
99
90
|
if (globalCopied > 0) {
|
|
100
91
|
console.log(`\x1b[32m✓ Synced ${globalCopied} builtin skills to ~/.grok/skills/\x1b[0m`);
|
|
101
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);
|
|
102
104
|
// Attempt auto-trust (best effort)
|
|
103
105
|
try {
|
|
104
106
|
execSync(`grok plugins trust "${targetPluginDir}"`, { stdio: 'ignore' });
|
|
@@ -115,11 +117,88 @@ export async function installForGrokCLI(options = {}) {
|
|
|
115
117
|
console.log('Restart Grok or run `grok` to load the new hooks and MCP servers.');
|
|
116
118
|
}
|
|
117
119
|
catch (err) {
|
|
118
|
-
|
|
119
|
-
|
|
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);
|
|
120
123
|
}
|
|
121
124
|
frameworkLogger.log('grok-integration', 'install-complete', 'info', {});
|
|
122
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
|
+
}
|
|
123
201
|
export default {
|
|
124
202
|
installForGrokCLI,
|
|
203
|
+
writeProjectRepertoireMcp,
|
|
125
204
|
};
|
|
@@ -17,7 +17,16 @@ import {
|
|
|
17
17
|
getActivePendingDelegations,
|
|
18
18
|
validateSpawnMatchesTodo,
|
|
19
19
|
updatePlanTodoStatusInPlace,
|
|
20
|
+
loadDelegationGateFeatures,
|
|
20
21
|
} from '../../hooks/delegation-gate-runtime.mjs';
|
|
22
|
+
import { isConferPendingForSession } from '../../hooks/confer-hook-runtime.mjs';
|
|
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';
|
|
21
30
|
|
|
22
31
|
export {
|
|
23
32
|
checkPendingDelegationGate,
|
|
@@ -105,9 +114,44 @@ export function resolveCodexPath(root = workspaceRoot()) {
|
|
|
105
114
|
return null;
|
|
106
115
|
}
|
|
107
116
|
|
|
117
|
+
export function resolveSiblingWorkspaceRoots(root = workspaceRoot()) {
|
|
118
|
+
const featuresPath = resolveFeaturesPath(root);
|
|
119
|
+
if (!featuresPath) return [];
|
|
120
|
+
try {
|
|
121
|
+
const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
|
|
122
|
+
const siblings = data.multi_agent_orchestration?.sibling_repos ?? [];
|
|
123
|
+
if (!Array.isArray(siblings)) return [];
|
|
124
|
+
const resolved = [];
|
|
125
|
+
for (const entry of siblings) {
|
|
126
|
+
const rel = typeof entry === 'string' ? entry : entry?.path;
|
|
127
|
+
if (!rel || typeof rel !== 'string') continue;
|
|
128
|
+
const abs = path.isAbsolute(rel) ? rel : path.resolve(root, rel);
|
|
129
|
+
if (!fs.existsSync(abs)) continue;
|
|
130
|
+
resolved.push({
|
|
131
|
+
path: abs,
|
|
132
|
+
label: typeof entry === 'object' && entry.label ? entry.label : path.basename(abs),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return resolved;
|
|
136
|
+
} catch {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function buildRepertoireResume(root = workspaceRoot()) {
|
|
142
|
+
return stationRepertoireResume(root);
|
|
143
|
+
}
|
|
144
|
+
|
|
108
145
|
export function loadFeatures(root = workspaceRoot()) {
|
|
109
146
|
const featuresPath = resolveFeaturesPath(root);
|
|
110
|
-
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
|
+
}
|
|
111
155
|
try {
|
|
112
156
|
const data = JSON.parse(fs.readFileSync(featuresPath, 'utf8'));
|
|
113
157
|
const orch = data.multi_agent_orchestration ?? {};
|
|
@@ -116,6 +160,8 @@ export function loadFeatures(root = workspaceRoot()) {
|
|
|
116
160
|
no_new_surface: orch.no_new_surface !== false,
|
|
117
161
|
per_suite_test_triage: orch.per_suite_test_triage !== false,
|
|
118
162
|
auto_chain_delegations: orch.auto_chain_delegations !== false,
|
|
163
|
+
grok_postprocessor_light: data.grok_postprocessor_light === true,
|
|
164
|
+
sibling_repos: resolveSiblingWorkspaceRoots(root),
|
|
119
165
|
};
|
|
120
166
|
} catch {
|
|
121
167
|
return {
|
|
@@ -123,6 +169,8 @@ export function loadFeatures(root = workspaceRoot()) {
|
|
|
123
169
|
no_new_surface: true,
|
|
124
170
|
per_suite_triage: true,
|
|
125
171
|
auto_chain_delegations: true,
|
|
172
|
+
grok_postprocessor_light: false,
|
|
173
|
+
sibling_repos: [],
|
|
126
174
|
};
|
|
127
175
|
}
|
|
128
176
|
}
|
|
@@ -160,9 +208,11 @@ export function extractToolContext(event) {
|
|
|
160
208
|
return { toolName, toolInput, paths, content, cmd: String(toolInput.command || '') };
|
|
161
209
|
}
|
|
162
210
|
|
|
163
|
-
export function checkCodexPatterns(content) {
|
|
211
|
+
export function checkCodexPatterns(content, options = {}) {
|
|
164
212
|
if (!content) return null;
|
|
165
|
-
|
|
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;
|
|
166
216
|
if (pattern.test(content)) return message;
|
|
167
217
|
pattern.lastIndex = 0;
|
|
168
218
|
}
|
|
@@ -215,23 +265,51 @@ export function sessionBootPath(root = workspaceRoot()) {
|
|
|
215
265
|
return path.join(root, '.xray', 'state', 'session-boot.json');
|
|
216
266
|
}
|
|
217
267
|
|
|
268
|
+
export function loadConferPending(root = workspaceRoot(), sessionId = null) {
|
|
269
|
+
try {
|
|
270
|
+
return isConferPendingForSession(root, sessionId);
|
|
271
|
+
} catch {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
218
276
|
export function buildSessionBootPayload(root, source = '0xray/grok-session-start', extra = {}) {
|
|
219
|
-
const features = loadFeatures();
|
|
277
|
+
const features = loadFeatures(root);
|
|
220
278
|
const blockingTerms = loadBlockingCodexTerms();
|
|
279
|
+
const siblingRoots = features.sibling_repos ?? resolveSiblingWorkspaceRoots(root);
|
|
280
|
+
const sessionId =
|
|
281
|
+
extra.sessionId || process.env.GROK_SESSION_ID || process.env.GROK_SESSION || null;
|
|
282
|
+
const conferPending = loadConferPending(root, sessionId);
|
|
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);
|
|
221
288
|
return {
|
|
222
289
|
hook: source,
|
|
223
290
|
lead_dev_mode: features.lead_dev_mode,
|
|
224
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',
|
|
225
296
|
codexBlockingTermCount: blockingTerms.length,
|
|
226
297
|
codexTerms: [59, 67, 68, 69],
|
|
227
298
|
rules: features.lead_dev_mode ? LEAD_DEV_RULES : [],
|
|
228
|
-
mcpIntake:
|
|
229
|
-
|
|
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',
|
|
230
303
|
workspaceRoot: root,
|
|
231
|
-
|
|
304
|
+
...heat,
|
|
305
|
+
...(siblingRoots.length > 0 ? { siblingWorkspaceRoots: siblingRoots } : {}),
|
|
306
|
+
...(conferPending ? { conferPending: true, conferTrigger: 'analyze-complexity at synthesis checkpoint' } : {}),
|
|
307
|
+
...(userAsideBoot ?? {}),
|
|
308
|
+
sessionId,
|
|
232
309
|
timestamp: new Date().toISOString(),
|
|
233
310
|
source,
|
|
234
311
|
...extra,
|
|
312
|
+
...heat,
|
|
235
313
|
};
|
|
236
314
|
}
|
|
237
315
|
|
|
@@ -240,19 +318,31 @@ export function writeSessionBoot(root, payload) {
|
|
|
240
318
|
const stateDir = path.join(root, '.xray', 'state');
|
|
241
319
|
fs.mkdirSync(stateDir, { recursive: true });
|
|
242
320
|
fs.writeFileSync(sessionBootPath(root), JSON.stringify(payload, null, 2));
|
|
321
|
+
writeStationMarkdown(root, payload);
|
|
243
322
|
return sessionBootPath(root);
|
|
244
323
|
} catch {
|
|
245
324
|
return null;
|
|
246
325
|
}
|
|
247
326
|
}
|
|
248
327
|
|
|
249
|
-
|
|
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. */
|
|
250
340
|
export function ensureSessionBoot(root = workspaceRoot(), source = '0xray/grok-boot') {
|
|
251
341
|
const bootPath = sessionBootPath(root);
|
|
252
342
|
if (fs.existsSync(bootPath)) {
|
|
253
343
|
try {
|
|
254
344
|
const existing = JSON.parse(fs.readFileSync(bootPath, 'utf8'));
|
|
255
|
-
if (existing
|
|
345
|
+
if (!sessionBootNeedsRefresh(existing, root)) return bootPath;
|
|
256
346
|
} catch {
|
|
257
347
|
/* rewrite corrupt boot */
|
|
258
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,6 +19,7 @@ import {
|
|
|
17
19
|
evaluatePostToolSpawn,
|
|
18
20
|
isOrchestrateToolEvent as gateIsOrchestrateToolEvent,
|
|
19
21
|
} from '../../hooks/delegation-gate-runtime.mjs';
|
|
22
|
+
import { recordRoutingOutcome, runGrokPostprocessorLight } from '../../hooks/pipeline-hook-runtime.mjs';
|
|
20
23
|
|
|
21
24
|
function extractToolOutput(event) {
|
|
22
25
|
return (
|
|
@@ -29,40 +32,77 @@ function extractToolOutput(event) {
|
|
|
29
32
|
);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const eventRoot = event.workspaceRoot || event.cwd || root;
|
|
37
|
-
const sessionId = resolveSessionId(event);
|
|
38
|
-
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);
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
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, {
|
|
42
48
|
tool: toolName,
|
|
49
|
+
agent: toolInput?.subagent_type ?? toolInput?.agent ?? 'orchestrate-task',
|
|
50
|
+
planTodoId: toolInput?.planTodoId ?? null,
|
|
43
51
|
sessionId,
|
|
44
|
-
note: 'orchestrate-task completed — pending-delegations.json written by task-handler',
|
|
45
52
|
});
|
|
53
|
+
} catch {
|
|
54
|
+
/* non-blocking */
|
|
46
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
|
+
});
|
|
47
77
|
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
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,
|
|
51
93
|
sessionId,
|
|
52
94
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
appendHookActivity(eventRoot, 'grok-post-tool-use', 'auto-chain-cleared', 'success', {
|
|
56
|
-
tool: toolName,
|
|
57
|
-
satisfied: spawnResult.satisfied.map((d) => d.id),
|
|
58
|
-
clearedAll: spawnResult.clearedAll,
|
|
59
|
-
planTodoId: spawnResult.expectedTodoId ?? null,
|
|
60
|
-
receiptRecorded: spawnResult.receiptRecorded ?? false,
|
|
61
|
-
todoCompleted: spawnResult.todoCompleted ?? false,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
95
|
+
} catch {
|
|
96
|
+
/* non-blocking */
|
|
64
97
|
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
65
100
|
|
|
101
|
+
async function main() {
|
|
102
|
+
const root = workspaceRoot();
|
|
103
|
+
try {
|
|
104
|
+
const event = await readStdinJson();
|
|
105
|
+
handlePostToolUse(event, root);
|
|
66
106
|
process.exit(0);
|
|
67
107
|
} catch (err) {
|
|
68
108
|
appendHookActivity(root, 'grok-post-tool-use', 'hook-error', 'error', {
|
|
@@ -72,4 +112,7 @@ async function main() {
|
|
|
72
112
|
}
|
|
73
113
|
}
|
|
74
114
|
|
|
75
|
-
|
|
115
|
+
const launchedAsCli = Boolean(process.argv[1] && process.argv[1].endsWith('post-tool-use.js'));
|
|
116
|
+
if (launchedAsCli) {
|
|
117
|
+
main();
|
|
118
|
+
}
|