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
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { frameworkLogger } from '../../../core/framework-logger.js';
|
|
7
7
|
import { buildLeadDevPlan, buildSynthesisCheckpointPlan, isLeadDevModeActive, persistLeadDevPlan, } from '../../../nucleus/autonomy-kernel.js';
|
|
8
|
+
import { formatConferQuorumReport, isConferEnabled, runConferQuorum, } from '../../../nucleus/confer.js';
|
|
8
9
|
import { bindPlanToSession } from '../../../nucleus/lead-dev-plan-persistence.js';
|
|
9
10
|
import { clearPendingDelegations } from '../../../nucleus/pending-delegations.js';
|
|
11
|
+
import { isAutoProvisionWorktreeEnabled, provisionGitWorktree, } from '../../../nucleus/aside-worktree.js';
|
|
12
|
+
import { buildUserAsidePlan, formatUserAsideSummary, isUserAsidesEnabled, loadUserAside, mergeUserAsideIntake, saveUserAside, setActiveAsideId, UserAsideValidationError, } from '../../../nucleus/user-aside.js';
|
|
10
13
|
import { getExecutionPlanner } from '../execution/execution-planner.js';
|
|
11
14
|
import { addObservations, extractComplexityObservations } from '../aside-context.js';
|
|
12
15
|
function normalizeAnalyzeTasks(raw) {
|
|
@@ -61,13 +64,89 @@ export class ComplexityHandler {
|
|
|
61
64
|
.filter((t) => t.description?.trim())
|
|
62
65
|
.map((t) => ({ description: t.description, type: t.type }));
|
|
63
66
|
const synthesisCheckpoint = args.synthesisCheckpoint === true;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let
|
|
70
|
-
|
|
67
|
+
const projectRoot = process.cwd();
|
|
68
|
+
const userAsideIntake = !synthesisCheckpoint &&
|
|
69
|
+
Boolean(args.userAsideId?.trim()) &&
|
|
70
|
+
isUserAsidesEnabled(projectRoot);
|
|
71
|
+
let userAsideReport = '';
|
|
72
|
+
let leadDevPlan = synthesisCheckpoint
|
|
73
|
+
? buildSynthesisCheckpointPlan(args.synthesisDueReason ?? null, projectRoot)
|
|
74
|
+
: userAsideIntake
|
|
75
|
+
? null
|
|
76
|
+
: isLeadDevModeActive() && (primaryDescription || planTaskInputs.length > 0)
|
|
77
|
+
? buildLeadDevPlan(primaryDescription, taskTypes.length ? taskTypes : ['implement'], planTaskInputs, analysis.overallComplexity, projectRoot)
|
|
78
|
+
: null;
|
|
79
|
+
let planPersisted = synthesisCheckpoint
|
|
80
|
+
? leadDevPlan !== null
|
|
81
|
+
: userAsideIntake
|
|
82
|
+
? false
|
|
83
|
+
: !leadDevPlan;
|
|
84
|
+
if (userAsideIntake && args.userAsideId) {
|
|
85
|
+
try {
|
|
86
|
+
const asideId = args.userAsideId.trim();
|
|
87
|
+
const title = args.userAsideTitle?.trim() || asideId;
|
|
88
|
+
const existing = loadUserAside(asideId, projectRoot);
|
|
89
|
+
const userAside = existing
|
|
90
|
+
? mergeUserAsideIntake(existing, primaryDescription || existing.description, planTaskInputs, analysis.overallComplexity, projectRoot)
|
|
91
|
+
: buildUserAsidePlan(asideId, title, primaryDescription || title, planTaskInputs, analysis.overallComplexity, projectRoot);
|
|
92
|
+
if (!userAside) {
|
|
93
|
+
planPersisted = false;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
if (args.worktree)
|
|
97
|
+
userAside.worktree = args.worktree;
|
|
98
|
+
if (args.branch)
|
|
99
|
+
userAside.branch = args.branch;
|
|
100
|
+
if (args.sessionId)
|
|
101
|
+
userAside.sessionId = args.sessionId;
|
|
102
|
+
if (args.userAsideTitle)
|
|
103
|
+
userAside.title = title;
|
|
104
|
+
let worktreeProvisionNote = '';
|
|
105
|
+
if (args.worktree?.trim() &&
|
|
106
|
+
args.branch?.trim() &&
|
|
107
|
+
isAutoProvisionWorktreeEnabled(projectRoot)) {
|
|
108
|
+
const provision = provisionGitWorktree({
|
|
109
|
+
projectRoot,
|
|
110
|
+
worktree: args.worktree.trim(),
|
|
111
|
+
branch: args.branch.trim(),
|
|
112
|
+
});
|
|
113
|
+
if (!provision.ok) {
|
|
114
|
+
throw new UserAsideValidationError(`Worktree auto-provision failed: ${provision.message}`);
|
|
115
|
+
}
|
|
116
|
+
worktreeProvisionNote = provision.created
|
|
117
|
+
? `\n\n**Worktree provisioned:** \`${provision.path}\` (branch \`${args.branch.trim()}\`)`
|
|
118
|
+
: `\n\n**Worktree ready:** \`${provision.path}\``;
|
|
119
|
+
}
|
|
120
|
+
const asidePath = saveUserAside(userAside, projectRoot);
|
|
121
|
+
const activate = args.setActiveAside !== false;
|
|
122
|
+
if (activate) {
|
|
123
|
+
clearPendingDelegations(projectRoot);
|
|
124
|
+
setActiveAsideId(asideId, projectRoot, args.sessionId ?? null);
|
|
125
|
+
}
|
|
126
|
+
planPersisted = true;
|
|
127
|
+
userAsideReport = `\n\n## User aside\n\n${formatUserAsideSummary(userAside)}${worktreeProvisionNote}`;
|
|
128
|
+
if (activate) {
|
|
129
|
+
userAsideReport += `\n\n**Active aside:** \`${asideId}\` — spawns route to \`${asideId}.a.*\` todos.`;
|
|
130
|
+
}
|
|
131
|
+
await frameworkLogger.log('orchestrator.server', 'user-aside-persisted', 'info', {
|
|
132
|
+
asidePath,
|
|
133
|
+
asideId,
|
|
134
|
+
todoCount: userAside.plan.phases.reduce((n, p) => n + p.todos.length, 0),
|
|
135
|
+
activated: activate,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
planPersisted = false;
|
|
141
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
142
|
+
userAsideReport = `\n\n❌ User aside intake failed: ${message}`;
|
|
143
|
+
await frameworkLogger.log('orchestrator.server', 'user-aside-persist-failed', 'warning', {
|
|
144
|
+
error: message,
|
|
145
|
+
validation: err instanceof UserAsideValidationError,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (leadDevPlan) {
|
|
71
150
|
try {
|
|
72
151
|
const sessionId = args.sessionId ?? `analyze-${Date.now()}`;
|
|
73
152
|
if (!synthesisCheckpoint) {
|
|
@@ -90,13 +169,33 @@ export class ComplexityHandler {
|
|
|
90
169
|
await frameworkLogger.log('orchestrator.server', synthesisCheckpoint ? 'synthesis-plan-persist-failed' : 'lead-dev-plan-persist-failed', 'warning', { error: err instanceof Error ? err.message : String(err) });
|
|
91
170
|
}
|
|
92
171
|
}
|
|
172
|
+
let conferReport = '';
|
|
173
|
+
if (synthesisCheckpoint &&
|
|
174
|
+
leadDevPlan &&
|
|
175
|
+
planPersisted &&
|
|
176
|
+
isConferEnabled() &&
|
|
177
|
+
args.sessionId) {
|
|
178
|
+
const conferOpts = {
|
|
179
|
+
dueReason: args.synthesisDueReason ?? null,
|
|
180
|
+
fixture: args.conferFixture === true,
|
|
181
|
+
};
|
|
182
|
+
if (args.collocatedText)
|
|
183
|
+
conferOpts.collocatedText = args.collocatedText;
|
|
184
|
+
const conferResult = await runConferQuorum(process.cwd(), args.sessionId, conferOpts);
|
|
185
|
+
conferReport = `\n\n${formatConferQuorumReport(conferResult)}`;
|
|
186
|
+
await frameworkLogger.log('orchestrator.server', 'confer-quorum', conferResult.status === 'completed' ? 'info' : 'warning', {
|
|
187
|
+
status: conferResult.status,
|
|
188
|
+
agentCount: conferResult.agents.length,
|
|
189
|
+
sessionId: args.sessionId,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
93
192
|
const ok = planPersisted;
|
|
94
193
|
return {
|
|
95
194
|
ok,
|
|
96
195
|
content: [
|
|
97
196
|
{
|
|
98
197
|
type: 'text',
|
|
99
|
-
text: this.formatComplexityResponse(analysis, recommendations, tasks.length, leadDevPlan, synthesisCheckpoint),
|
|
198
|
+
text: this.formatComplexityResponse(analysis, recommendations, tasks.length, leadDevPlan, synthesisCheckpoint) + conferReport + userAsideReport,
|
|
100
199
|
},
|
|
101
200
|
],
|
|
102
201
|
};
|
|
@@ -31,6 +31,12 @@ export declare class TaskHandler {
|
|
|
31
31
|
sessionId?: string;
|
|
32
32
|
executionMode?: string;
|
|
33
33
|
timeout?: number;
|
|
34
|
+
confer?: boolean;
|
|
35
|
+
conferFixture?: boolean;
|
|
36
|
+
collocatedText?: string;
|
|
37
|
+
userAsideId?: string;
|
|
38
|
+
setActiveAside?: boolean;
|
|
39
|
+
clearActiveAside?: boolean;
|
|
34
40
|
}, deps: TaskHandlerDeps): Promise<{
|
|
35
41
|
content: Array<{
|
|
36
42
|
type: string;
|
|
@@ -19,6 +19,81 @@ export class TaskHandler {
|
|
|
19
19
|
* Handle orchestrate-task request
|
|
20
20
|
*/
|
|
21
21
|
async handleOrchestrateTask(args, deps) {
|
|
22
|
+
if (args.clearActiveAside === true) {
|
|
23
|
+
const projectRoot = process.cwd();
|
|
24
|
+
const { clearActiveAside, getActiveAsideId } = await import('../../../nucleus/user-aside.js');
|
|
25
|
+
const prior = getActiveAsideId(projectRoot, args.sessionId ?? null);
|
|
26
|
+
clearActiveAside(projectRoot);
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: prior
|
|
32
|
+
? `✅ Cleared active aside \`${prior}\` — spawns resume main lead-dev plan.`
|
|
33
|
+
: 'ℹ️ No active aside was set.',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (args.userAsideId?.trim()) {
|
|
39
|
+
const projectRoot = process.cwd();
|
|
40
|
+
const { setActiveAsideId, loadUserAside, formatUserAsideSummary, isUserAsidesEnabled, UserAsideValidationError, } = await import('../../../nucleus/user-aside.js');
|
|
41
|
+
const { clearPendingDelegations } = await import('../../../nucleus/pending-delegations.js');
|
|
42
|
+
if (!isUserAsidesEnabled(projectRoot)) {
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: 'text', text: '❌ User asides disabled in features.json' }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const asideId = args.userAsideId.trim();
|
|
48
|
+
const aside = loadUserAside(asideId, projectRoot);
|
|
49
|
+
if (!aside) {
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: 'text',
|
|
54
|
+
text: `❌ User aside \`${asideId}\` not found — run analyze-complexity with userAsideId first.`,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (args.setActiveAside !== false) {
|
|
60
|
+
try {
|
|
61
|
+
clearPendingDelegations(projectRoot);
|
|
62
|
+
setActiveAsideId(asideId, projectRoot, args.sessionId ?? null);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const message = err instanceof UserAsideValidationError ? err.message : String(err);
|
|
66
|
+
return { content: [{ type: 'text', text: `❌ ${message}` }] };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: 'text',
|
|
73
|
+
text: `✅ Active aside: \`${asideId}\`\n\n${formatUserAsideSummary(aside)}`,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (args.confer === true) {
|
|
79
|
+
const { runConferQuorum, formatConferQuorumReport, isConferEnabled } = await import('../../../nucleus/confer.js');
|
|
80
|
+
const sid = args.sessionId ?? `confer_${Date.now()}`;
|
|
81
|
+
if (!isConferEnabled()) {
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: 'text', text: '❌ Confer disabled in features.json' }],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const conferOpts = {
|
|
87
|
+
dueReason: args.description,
|
|
88
|
+
fixture: args.conferFixture === true,
|
|
89
|
+
};
|
|
90
|
+
if (args.collocatedText)
|
|
91
|
+
conferOpts.collocatedText = args.collocatedText;
|
|
92
|
+
const result = await runConferQuorum(process.cwd(), sid, conferOpts);
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: formatConferQuorumReport(result) }],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
22
97
|
const { description, tasks = [], sessionId = `session_${Date.now()}`, executionMode = 'optimized', timeout = 300000 } = args;
|
|
23
98
|
await frameworkLogger.log('orchestrator.server', 'orchestrate-task-start', 'info', { description, taskCount: tasks.length, sessionId, executionMode });
|
|
24
99
|
const orchestrationResult = {
|
|
@@ -99,13 +99,37 @@ export class OrchestratorServer {
|
|
|
99
99
|
default: 'optimized',
|
|
100
100
|
},
|
|
101
101
|
timeout: { type: 'number', default: 300000 },
|
|
102
|
+
confer: {
|
|
103
|
+
type: 'boolean',
|
|
104
|
+
description: 'Run mandatory 3-agent confer quorum (researcher, architect-tools, code-review) instead of task execution',
|
|
105
|
+
},
|
|
106
|
+
conferFixture: {
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
description: 'Use fixture confer receipts (CI/verify)',
|
|
109
|
+
},
|
|
110
|
+
collocatedText: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
description: 'Collocated synthesis context for confer prompts',
|
|
113
|
+
},
|
|
114
|
+
userAsideId: {
|
|
115
|
+
type: 'string',
|
|
116
|
+
description: 'Activate an existing user aside for spawn routing',
|
|
117
|
+
},
|
|
118
|
+
setActiveAside: {
|
|
119
|
+
type: 'boolean',
|
|
120
|
+
description: 'Set userAsideId as the active aside (default true)',
|
|
121
|
+
},
|
|
122
|
+
clearActiveAside: {
|
|
123
|
+
type: 'boolean',
|
|
124
|
+
description: 'Clear active aside — resume main lead-dev plan spawns',
|
|
125
|
+
},
|
|
102
126
|
},
|
|
103
|
-
required: ['description'
|
|
127
|
+
required: ['description'],
|
|
104
128
|
},
|
|
105
129
|
},
|
|
106
130
|
{
|
|
107
131
|
name: 'analyze-complexity',
|
|
108
|
-
description: 'Analyze task complexity and recommend orchestration strategy. When lead_dev_mode is on (features.json), includes phased plan + todos + subagent routes. During synthesis checkpoint, returns collocated context and mandatory-consult realignment plan — pass sessionId from the active session.',
|
|
132
|
+
description: 'Analyze task complexity and recommend orchestration strategy. When lead_dev_mode is on (features.json), includes phased plan + todos + subagent routes. Pass userAsideId to intake a parallel user aside ({asideId}.a.* namespaced todos, worktree-like). During synthesis checkpoint, returns collocated context and mandatory-consult realignment plan — pass sessionId from the active session.',
|
|
109
133
|
inputSchema: {
|
|
110
134
|
type: 'object',
|
|
111
135
|
properties: {
|
|
@@ -113,6 +137,26 @@ export class OrchestratorServer {
|
|
|
113
137
|
type: 'string',
|
|
114
138
|
description: 'Active session id (required to clear synthesis checkpoint; inferred from checkpoint state when omitted)',
|
|
115
139
|
},
|
|
140
|
+
userAsideId: {
|
|
141
|
+
type: 'string',
|
|
142
|
+
description: 'User aside id — persists .xray/state/asides/{id}.json with {asideId}.a.* todos (parallel track)',
|
|
143
|
+
},
|
|
144
|
+
userAsideTitle: {
|
|
145
|
+
type: 'string',
|
|
146
|
+
description: 'Display title for the user aside (defaults to userAsideId)',
|
|
147
|
+
},
|
|
148
|
+
worktree: {
|
|
149
|
+
type: 'string',
|
|
150
|
+
description: 'Optional worktree path for aside isolation',
|
|
151
|
+
},
|
|
152
|
+
branch: {
|
|
153
|
+
type: 'string',
|
|
154
|
+
description: 'Optional git branch for the aside',
|
|
155
|
+
},
|
|
156
|
+
setActiveAside: {
|
|
157
|
+
type: 'boolean',
|
|
158
|
+
description: 'Activate aside for spawn routing (default true when userAsideId set)',
|
|
159
|
+
},
|
|
116
160
|
tasks: {
|
|
117
161
|
type: 'array',
|
|
118
162
|
items: {
|
|
@@ -308,18 +352,23 @@ export class OrchestratorServer {
|
|
|
308
352
|
...complexityArgs,
|
|
309
353
|
...(sessionId ? { sessionId } : {}),
|
|
310
354
|
...(synthesisDue
|
|
311
|
-
? {
|
|
355
|
+
? {
|
|
356
|
+
synthesisCheckpoint: true,
|
|
357
|
+
synthesisDueReason: dueReason,
|
|
358
|
+
collocatedText: collocated?.collatedText ?? null,
|
|
359
|
+
conferFixture: process.env.XRAY_CONFER_FIXTURE === '1',
|
|
360
|
+
}
|
|
312
361
|
: {}),
|
|
313
362
|
}, aside.asideId);
|
|
314
363
|
let content = result.content;
|
|
315
364
|
if (synthesisDue && collocated?.collatedText) {
|
|
316
365
|
content = appendSynthesisContextToResponse(content, collocated.collatedText);
|
|
317
366
|
}
|
|
318
|
-
if (synthesisDue && result.ok) {
|
|
367
|
+
if (synthesisDue && result.ok && !result.content[0]?.text?.includes('Confer quorum')) {
|
|
319
368
|
content = content.map((block, index) => index === 0
|
|
320
369
|
? {
|
|
321
370
|
...block,
|
|
322
|
-
text: `${block.text}\n\n**
|
|
371
|
+
text: `${block.text}\n\n**Confer** runs automatically at synthesis checkpoint (researcher → architect-tools → code-review). Checkpoint clears when all consult todos complete.`,
|
|
323
372
|
}
|
|
324
373
|
: block);
|
|
325
374
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { MemoryRoutingProvider, MemoryRoutingContext, MemoryInheritedContext, MemoryAgentCapability, MemoryOrchestrationTask, MemoryThinDispatchResult, MemoryRoutingConfig, OrchestratorFeedbackEntry, } from './types.js';
|
|
2
2
|
export { getMemoryRoutingProvider, getMemoryRoutingProviderSync, getMemoryRoutingConfig, resetMemoryRoutingProvider, initializeMemoryRouting, } from './provider-registry.js';
|
|
3
3
|
export { NullMemoryRoutingProvider, createMemoryRoutingProvider } from './null-provider.js';
|
|
4
|
-
export { loadMemoryRoutingProvider } from './provider-loader.js';
|
|
4
|
+
export { loadMemoryRoutingProvider, isLeftoverMemoryRoutingOff, isExplicitMemoryRoutingOptOut, resolveLeftoverEnabledConfig, } from './provider-loader.js';
|
|
5
5
|
export { validateMemoryRoutingConfig } from './validate-config.js';
|
|
6
6
|
export type { MemoryRoutingValidation } from './validate-config.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getMemoryRoutingProvider, getMemoryRoutingProviderSync, getMemoryRoutingConfig, resetMemoryRoutingProvider, initializeMemoryRouting, } from './provider-registry.js';
|
|
2
2
|
export { NullMemoryRoutingProvider, createMemoryRoutingProvider } from './null-provider.js';
|
|
3
|
-
export { loadMemoryRoutingProvider } from './provider-loader.js';
|
|
3
|
+
export { loadMemoryRoutingProvider, isLeftoverMemoryRoutingOff, isExplicitMemoryRoutingOptOut, resolveLeftoverEnabledConfig, } from './provider-loader.js';
|
|
4
4
|
export { validateMemoryRoutingConfig } from './validate-config.js';
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import type { MemoryRoutingConfig, MemoryRoutingProvider } from './types.js';
|
|
2
|
+
export declare function isExplicitMemoryRoutingOptOut(config: MemoryRoutingConfig): boolean;
|
|
3
|
+
/** Leftover shipped default: enabled false + provider null. Not an explicit opt-out. */
|
|
4
|
+
export declare function isLeftoverMemoryRoutingOff(config: MemoryRoutingConfig): boolean;
|
|
5
|
+
export declare function resolveLeftoverEnabledConfig(config: MemoryRoutingConfig, cwd: string): MemoryRoutingConfig | null;
|
|
2
6
|
export declare function loadMemoryRoutingProvider(config: MemoryRoutingConfig, cwd?: string): Promise<MemoryRoutingProvider>;
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { resolve, dirname } from 'node:path';
|
|
2
|
+
import { resolve, dirname, join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { frameworkLogger } from '../core/framework-logger.js';
|
|
5
5
|
import { createMemoryRoutingProvider as createNullProvider } from './null-provider.js';
|
|
6
6
|
import { validateMemoryRoutingConfig } from './validate-config.js';
|
|
7
|
+
function sleep(ms) {
|
|
8
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
10
|
+
function resolveUnavailableReason(provider) {
|
|
11
|
+
const statusProvider = provider;
|
|
12
|
+
if (typeof statusProvider.getAvailabilityStatus !== 'function') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return statusProvider.getAvailabilityStatus().reason ?? null;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
7
22
|
const REPERTOIRE_CANDIDATE_PATHS = [
|
|
23
|
+
'node_modules/@0xray/repertoire/dist/provider/memory-routing-provider.js',
|
|
24
|
+
'vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js',
|
|
8
25
|
'../repertoire/dist/provider/memory-routing-provider.js',
|
|
9
26
|
'../../repertoire/dist/provider/memory-routing-provider.js',
|
|
10
27
|
'../../../repertoire/dist/provider/memory-routing-provider.js',
|
|
@@ -35,15 +52,55 @@ function defaultPathForProvider(provider, cwd) {
|
|
|
35
52
|
if (existsSync(abs))
|
|
36
53
|
return abs;
|
|
37
54
|
}
|
|
55
|
+
const nm = join(cwd, 'node_modules', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js');
|
|
56
|
+
return existsSync(nm) ? nm : null;
|
|
57
|
+
}
|
|
58
|
+
export function isExplicitMemoryRoutingOptOut(config) {
|
|
59
|
+
return config.enabled === false && config.provider === 'repertoire';
|
|
60
|
+
}
|
|
61
|
+
/** Leftover shipped default: enabled false + provider null. Not an explicit opt-out. */
|
|
62
|
+
export function isLeftoverMemoryRoutingOff(config) {
|
|
63
|
+
if (config.enabled === true)
|
|
64
|
+
return false;
|
|
65
|
+
if (isExplicitMemoryRoutingOptOut(config))
|
|
66
|
+
return false;
|
|
67
|
+
return config.provider === 'null' || !config.provider;
|
|
68
|
+
}
|
|
69
|
+
function leftoverRepertoireModulePath(cwd) {
|
|
70
|
+
const nm = join(cwd, 'node_modules', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js');
|
|
71
|
+
if (existsSync(nm))
|
|
72
|
+
return nm;
|
|
73
|
+
const vendor = join(cwd, 'vendor', '@0xray', 'repertoire', 'dist', 'provider', 'memory-routing-provider.js');
|
|
74
|
+
if (existsSync(vendor))
|
|
75
|
+
return vendor;
|
|
76
|
+
const sibling = resolve(cwd, '../repertoire/dist/provider/memory-routing-provider.js');
|
|
77
|
+
if (existsSync(sibling))
|
|
78
|
+
return sibling;
|
|
38
79
|
return null;
|
|
39
80
|
}
|
|
81
|
+
export function resolveLeftoverEnabledConfig(config, cwd) {
|
|
82
|
+
if (!isLeftoverMemoryRoutingOff(config))
|
|
83
|
+
return null;
|
|
84
|
+
const modulePath = resolveModulePath(config.module_path, cwd) ?? leftoverRepertoireModulePath(cwd);
|
|
85
|
+
if (!modulePath)
|
|
86
|
+
return null;
|
|
87
|
+
const enabled = {
|
|
88
|
+
enabled: true,
|
|
89
|
+
provider: 'repertoire',
|
|
90
|
+
module_path: modulePath,
|
|
91
|
+
};
|
|
92
|
+
if (config.config)
|
|
93
|
+
enabled.config = config.config;
|
|
94
|
+
return enabled;
|
|
95
|
+
}
|
|
40
96
|
export async function loadMemoryRoutingProvider(config, cwd = process.cwd()) {
|
|
41
97
|
const validation = validateMemoryRoutingConfig(config);
|
|
42
98
|
if (!validation.valid) {
|
|
43
99
|
await frameworkLogger.log('memory-routing', 'config-invalid', 'error', { errors: validation.errors, provider: config.provider });
|
|
44
100
|
return createNullProvider();
|
|
45
101
|
}
|
|
46
|
-
const
|
|
102
|
+
const leftover = resolveLeftoverEnabledConfig(validation.normalized, cwd);
|
|
103
|
+
const effective = leftover ?? validation.normalized;
|
|
47
104
|
if (!effective.enabled || effective.provider === 'null') {
|
|
48
105
|
return createNullProvider();
|
|
49
106
|
}
|
|
@@ -68,13 +125,26 @@ export async function loadMemoryRoutingProvider(config, cwd = process.cwd()) {
|
|
|
68
125
|
if (!provider?.id || typeof provider.isAvailable !== 'function') {
|
|
69
126
|
throw new Error(`Invalid memory routing provider from ${modulePath}`);
|
|
70
127
|
}
|
|
128
|
+
const availabilityReason = resolveUnavailableReason(provider);
|
|
71
129
|
if (!provider.isAvailable()) {
|
|
72
130
|
await frameworkLogger.log('memory-routing', 'provider-unavailable', 'error', {
|
|
73
131
|
providerId: provider.id,
|
|
74
132
|
modulePath,
|
|
75
|
-
|
|
133
|
+
unavailableReason: availabilityReason,
|
|
134
|
+
message: `Provider "${provider.id}" loaded but isAvailable() returned false (${availabilityReason ?? 'unknown'}). Falling back to null provider.`,
|
|
76
135
|
});
|
|
77
|
-
|
|
136
|
+
if (availabilityReason === 'empty_registry') {
|
|
137
|
+
await sleep(100);
|
|
138
|
+
if (provider.isAvailable()) {
|
|
139
|
+
await frameworkLogger.log('memory-routing', 'provider-retry-ok', 'info', { providerId: provider.id, modulePath });
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
return createNullProvider();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return createNullProvider();
|
|
147
|
+
}
|
|
78
148
|
}
|
|
79
149
|
await frameworkLogger.log('memory-routing', 'provider-loaded', 'info', { providerId: provider.id, name: provider.name, modulePath });
|
|
80
150
|
return provider;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { featuresConfigLoader } from '../core/features-config.js';
|
|
2
2
|
import { NullMemoryRoutingProvider } from './null-provider.js';
|
|
3
|
-
import { loadMemoryRoutingProvider } from './provider-loader.js';
|
|
3
|
+
import { loadMemoryRoutingProvider, resolveLeftoverEnabledConfig } from './provider-loader.js';
|
|
4
4
|
import { validateMemoryRoutingConfig } from './validate-config.js';
|
|
5
5
|
let cachedProvider = null;
|
|
6
6
|
let loadPromise = null;
|
|
@@ -8,7 +8,8 @@ const nullProviderSingleton = new NullMemoryRoutingProvider();
|
|
|
8
8
|
export function getMemoryRoutingConfig() {
|
|
9
9
|
const raw = featuresConfigLoader.loadConfig().memory_routing;
|
|
10
10
|
const validation = validateMemoryRoutingConfig(raw ?? { enabled: false, provider: 'null' });
|
|
11
|
-
return validation.normalized
|
|
11
|
+
return (resolveLeftoverEnabledConfig(validation.normalized, process.cwd()) ??
|
|
12
|
+
validation.normalized);
|
|
12
13
|
}
|
|
13
14
|
export async function getMemoryRoutingProvider(forceReload = false) {
|
|
14
15
|
if (!forceReload && cachedProvider)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-aside worktree path resolution, spawn cwd validation, optional git provision.
|
|
3
|
+
*/
|
|
4
|
+
/** Minimal spawn tool input for cwd extraction (avoids circular import with delegation-gate). */
|
|
5
|
+
export interface SpawnCwdToolInput {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
working_directory?: string;
|
|
8
|
+
workingDirectory?: string;
|
|
9
|
+
isolation?: string;
|
|
10
|
+
isolation_mode?: string;
|
|
11
|
+
worktree_path?: string;
|
|
12
|
+
worktreePath?: string;
|
|
13
|
+
worktree?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface AsideWorktreeCwdResult {
|
|
17
|
+
valid: boolean;
|
|
18
|
+
gate?: 'aside-worktree-cwd-missing' | 'aside-worktree-cwd-mismatch';
|
|
19
|
+
reason?: string;
|
|
20
|
+
hint?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
export interface WorktreeProvisionResult {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
path: string;
|
|
25
|
+
created: boolean;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function normalizeWorktreePath(worktree: string, projectRoot: string): string;
|
|
29
|
+
export declare function isAutoProvisionWorktreeEnabled(projectRoot?: string): boolean;
|
|
30
|
+
/** Extract spawn cwd from host Task / spawn_subagent tool input. */
|
|
31
|
+
export declare function extractSpawnCwd(toolInput: SpawnCwdToolInput, projectRoot: string): string | null;
|
|
32
|
+
export declare function validateAsideWorktreeCwd(worktree: string | undefined, toolInput: SpawnCwdToolInput, projectRoot: string): AsideWorktreeCwdResult;
|
|
33
|
+
/**
|
|
34
|
+
* Guarded `git worktree add` when auto_provision_worktree is enabled.
|
|
35
|
+
* Creates branch with -b when it does not exist locally.
|
|
36
|
+
*/
|
|
37
|
+
export declare function provisionGitWorktree(opts: {
|
|
38
|
+
projectRoot: string;
|
|
39
|
+
worktree: string;
|
|
40
|
+
branch: string;
|
|
41
|
+
}): WorktreeProvisionResult;
|