mindforge-cc 10.0.3 → 11.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/.mindforge/MINDFORGE-V2-SCHEMA.json +43 -10
- package/.mindforge/config.json +30 -2
- package/.mindforge/engine/cross-model-eval.md +74 -0
- package/.mindforge/engine/proactive/signal-detector.md +60 -0
- package/.mindforge/engine/proactive/suggestion-engine.md +100 -0
- package/.mindforge/personas/agent-architect.md +57 -0
- package/.mindforge/personas/agent-evaluator.md +162 -0
- package/.mindforge/personas/agent-memory-designer.md +157 -0
- package/.mindforge/personas/agent-ops-engineer.md +120 -0
- package/.mindforge/personas/agent-orchestrator.md +112 -0
- package/.mindforge/personas/ai-economist.md +57 -0
- package/.mindforge/personas/ai-safety-engineer.md +57 -0
- package/.mindforge/personas/analytics-engineer.md +57 -0
- package/.mindforge/personas/anti-pattern-hunter.md +61 -0
- package/.mindforge/personas/api-gateway-designer.md +132 -0
- package/.mindforge/personas/auth-engineer.md +112 -0
- package/.mindforge/personas/build-engineer.md +57 -0
- package/.mindforge/personas/business-analyst.md +56 -0
- package/.mindforge/personas/cache-architect.md +100 -0
- package/.mindforge/personas/causal-scientist.md +57 -0
- package/.mindforge/personas/cdn-architect.md +118 -0
- package/.mindforge/personas/change-agent.md +104 -0
- package/.mindforge/personas/code-narrator.md +52 -0
- package/.mindforge/personas/codegen-specialist.md +68 -0
- package/.mindforge/personas/communication-architect.md +102 -0
- package/.mindforge/personas/compliance-engineer.md +96 -0
- package/.mindforge/personas/consensus-engineer.md +116 -0
- package/.mindforge/personas/contract-tester.md +60 -192
- package/.mindforge/personas/data-architect.md +108 -0
- package/.mindforge/personas/data-mesh-architect.md +57 -0
- package/.mindforge/personas/data-pipeline-architect.md +120 -0
- package/.mindforge/personas/de-sloppifier.md +60 -0
- package/.mindforge/personas/debt-manager.md +66 -0
- package/.mindforge/personas/decision-architect.md +82 -51
- package/.mindforge/personas/deployment-captain.md +74 -0
- package/.mindforge/personas/design-system-lead.md +112 -0
- package/.mindforge/personas/dmux-orchestrator.md +75 -0
- package/.mindforge/personas/dx-engineer.md +96 -0
- package/.mindforge/personas/ecommerce-engineer.md +57 -0
- package/.mindforge/personas/edge-engineer.md +94 -0
- package/.mindforge/personas/edtech-architect.md +106 -0
- package/.mindforge/personas/embedding-architect.md +57 -0
- package/.mindforge/personas/environment-engineer.md +57 -0
- package/.mindforge/personas/eval-judge.md +55 -0
- package/.mindforge/personas/event-architect.md +102 -0
- package/.mindforge/personas/experiment-designer.md +138 -0
- package/.mindforge/personas/feature-store-engineer.md +57 -0
- package/.mindforge/personas/finops-analyst.md +66 -0
- package/.mindforge/personas/fintech-architect.md +57 -0
- package/.mindforge/personas/flutter-engineer.md +104 -0
- package/.mindforge/personas/gaming-engineer.md +57 -0
- package/.mindforge/personas/graphql-designer.md +73 -0
- package/.mindforge/personas/healthcare-engineer.md +57 -0
- package/.mindforge/personas/hiring-strategist.md +105 -0
- package/.mindforge/personas/hitl-architect.md +165 -0
- package/.mindforge/personas/i18n-architect.md +69 -0
- package/.mindforge/personas/iot-architect.md +105 -0
- package/.mindforge/personas/knowledge-curator.md +139 -0
- package/.mindforge/personas/knowledge-engineer.md +57 -0
- package/.mindforge/personas/lakehouse-architect.md +57 -0
- package/.mindforge/personas/llm-orchestrator.md +57 -0
- package/.mindforge/personas/logistics-architect.md +106 -0
- package/.mindforge/personas/market-analyst.md +53 -0
- package/.mindforge/personas/marketplace-engineer.md +105 -0
- package/.mindforge/personas/mcp-designer.md +54 -0
- package/.mindforge/personas/meeting-designer.md +104 -0
- package/.mindforge/personas/mentorship-lead.md +106 -0
- package/.mindforge/personas/migration-architect.md +57 -0
- package/.mindforge/personas/ml-ops-engineer.md +101 -0
- package/.mindforge/personas/mobile-architect.md +105 -0
- package/.mindforge/personas/mobile-security-engineer.md +106 -0
- package/.mindforge/personas/multi-tenancy-architect.md +71 -0
- package/.mindforge/personas/multimodal-engineer.md +57 -0
- package/.mindforge/personas/offline-specialist.md +105 -0
- package/.mindforge/personas/onboarding-navigator.md +63 -0
- package/.mindforge/personas/payments-engineer.md +135 -0
- package/.mindforge/personas/pipeline-engineer.md +115 -0
- package/.mindforge/personas/platform-engineer.md +97 -0
- package/.mindforge/personas/platform-lead.md +57 -0
- package/.mindforge/personas/privacy-engineer.md +57 -0
- package/.mindforge/personas/product-owner.md +56 -0
- package/.mindforge/personas/productivity-analyst.md +57 -0
- package/.mindforge/personas/prompt-architect.md +101 -0
- package/.mindforge/personas/proofreader.md +53 -0
- package/.mindforge/personas/pwa-architect.md +105 -0
- package/.mindforge/personas/quality-scorer.md +63 -0
- package/.mindforge/personas/react-native-engineer.md +106 -0
- package/.mindforge/personas/resilience-engineer.md +69 -0
- package/.mindforge/personas/rfc-architect.md +64 -0
- package/.mindforge/personas/saga-orchestrator.md +80 -0
- package/.mindforge/personas/secrets-engineer.md +57 -0
- package/.mindforge/personas/skill-smith.md +79 -0
- package/.mindforge/personas/sre-lead.md +107 -0
- package/.mindforge/personas/stream-engineer.md +57 -0
- package/.mindforge/personas/streaming-engineer.md +64 -0
- package/.mindforge/personas/swarm-templates.json +674 -44
- package/.mindforge/personas/system-designer.md +57 -0
- package/.mindforge/personas/team-coach.md +120 -0
- package/.mindforge/personas/tech-lead-coach.md +103 -0
- package/.mindforge/personas/technical-writer-lead.md +111 -0
- package/.mindforge/personas/vibe-checker.md +75 -0
- package/.mindforge/personas/worktree-manager.md +56 -0
- package/.mindforge/personas/zero-trust-engineer.md +113 -0
- package/.mindforge/skills/a11y-testing/SKILL.md +143 -0
- package/.mindforge/skills/agent-evaluation-framework/SKILL.md +227 -0
- package/.mindforge/skills/agent-memory-design/SKILL.md +199 -0
- package/.mindforge/skills/agent-orchestration-patterns/SKILL.md +129 -0
- package/.mindforge/skills/agent-tool-selection/SKILL.md +204 -0
- package/.mindforge/skills/ai-agent-deployment/SKILL.md +176 -0
- package/.mindforge/skills/ai-cost-management/SKILL.md +57 -0
- package/.mindforge/skills/ai-safety-alignment/SKILL.md +53 -0
- package/.mindforge/skills/analytics-instrumentation/SKILL.md +172 -0
- package/.mindforge/skills/api-gateway-patterns/SKILL.md +177 -0
- package/.mindforge/skills/api-marketplace/SKILL.md +56 -0
- package/.mindforge/skills/api-versioning/SKILL.md +100 -0
- package/.mindforge/skills/app-store-deployment/SKILL.md +44 -0
- package/.mindforge/skills/architecture-tradeoff-analysis/SKILL.md +97 -0
- package/.mindforge/skills/audit-logging/SKILL.md +140 -0
- package/.mindforge/skills/auth-patterns/SKILL.md +148 -0
- package/.mindforge/skills/autonomous-agent-harness/SKILL.md +218 -0
- package/.mindforge/skills/autonomous-agents/SKILL.md +59 -0
- package/.mindforge/skills/build-system-optimization/SKILL.md +54 -0
- package/.mindforge/skills/build-vs-buy/SKILL.md +80 -0
- package/.mindforge/skills/bundle-optimization/SKILL.md +174 -0
- package/.mindforge/skills/business-analyst/SKILL.md +82 -0
- package/.mindforge/skills/caching-strategies/SKILL.md +132 -0
- package/.mindforge/skills/capacity-planning/SKILL.md +96 -0
- package/.mindforge/skills/causal-inference/SKILL.md +42 -0
- package/.mindforge/skills/cdn-optimization/SKILL.md +212 -0
- package/.mindforge/skills/change-management/SKILL.md +106 -0
- package/.mindforge/skills/chaos-engineering/SKILL.md +99 -0
- package/.mindforge/skills/ci-cd-pipeline/SKILL.md +118 -0
- package/.mindforge/skills/cli-design/SKILL.md +118 -0
- package/.mindforge/skills/code-generation-patterns/SKILL.md +92 -0
- package/.mindforge/skills/code-review-methodology/SKILL.md +180 -0
- package/.mindforge/skills/code-tour/SKILL.md +145 -0
- package/.mindforge/skills/codebase-onboarding/SKILL.md +95 -0
- package/.mindforge/skills/compliance-as-code/SKILL.md +195 -0
- package/.mindforge/skills/conflict-resolution/SKILL.md +87 -0
- package/.mindforge/skills/connection-pooling/SKILL.md +151 -0
- package/.mindforge/skills/container-security/SKILL.md +151 -0
- package/.mindforge/skills/context-engineering/SKILL.md +114 -0
- package/.mindforge/skills/contract-testing/SKILL.md +85 -0
- package/.mindforge/skills/cost-estimation/SKILL.md +82 -0
- package/.mindforge/skills/cqrs-event-sourcing/SKILL.md +95 -0
- package/.mindforge/skills/cross-platform-testing/SKILL.md +43 -0
- package/.mindforge/skills/data-governance/SKILL.md +42 -0
- package/.mindforge/skills/data-lakehouse/SKILL.md +42 -0
- package/.mindforge/skills/data-mesh/SKILL.md +42 -0
- package/.mindforge/skills/data-modeling/SKILL.md +107 -0
- package/.mindforge/skills/data-pipeline-design/SKILL.md +171 -0
- package/.mindforge/skills/data-privacy-engineering/SKILL.md +42 -0
- package/.mindforge/skills/database-performance/SKILL.md +174 -0
- package/.mindforge/skills/database-sharding-advanced/SKILL.md +206 -0
- package/.mindforge/skills/de-sloppify/SKILL.md +120 -0
- package/.mindforge/skills/defense-in-depth/SKILL.md +84 -0
- package/.mindforge/skills/delegation-patterns/SKILL.md +123 -0
- package/.mindforge/skills/dependency-management/SKILL.md +94 -0
- package/.mindforge/skills/deployment-workflow/SKILL.md +135 -0
- package/.mindforge/skills/design-system/SKILL.md +113 -0
- package/.mindforge/skills/developer-onboarding/SKILL.md +99 -0
- package/.mindforge/skills/developer-productivity-metrics/SKILL.md +59 -0
- package/.mindforge/skills/distributed-consensus/SKILL.md +141 -0
- package/.mindforge/skills/dmux-workflows/SKILL.md +141 -0
- package/.mindforge/skills/dns-architecture/SKILL.md +167 -0
- package/.mindforge/skills/ecommerce-architecture/SKILL.md +41 -0
- package/.mindforge/skills/edge-computing/SKILL.md +91 -0
- package/.mindforge/skills/edtech-platform/SKILL.md +41 -0
- package/.mindforge/skills/email-deliverability/SKILL.md +177 -0
- package/.mindforge/skills/embedding-systems/SKILL.md +55 -0
- package/.mindforge/skills/environment-management/SKILL.md +54 -0
- package/.mindforge/skills/error-handling-architecture/SKILL.md +118 -0
- package/.mindforge/skills/estimation-techniques/SKILL.md +113 -0
- package/.mindforge/skills/eval-harness/SKILL.md +180 -0
- package/.mindforge/skills/event-driven-architecture/SKILL.md +162 -0
- package/.mindforge/skills/experiment-design/SKILL.md +139 -0
- package/.mindforge/skills/experiment-platform/SKILL.md +43 -0
- package/.mindforge/skills/feature-engineering/SKILL.md +42 -0
- package/.mindforge/skills/feature-flag-management/SKILL.md +183 -0
- package/.mindforge/skills/fine-tuning-workflow/SKILL.md +189 -0
- package/.mindforge/skills/fintech-patterns/SKILL.md +41 -0
- package/.mindforge/skills/flutter-architecture/SKILL.md +42 -0
- package/.mindforge/skills/gaming-backend/SKILL.md +41 -0
- package/.mindforge/skills/git-workflow-design/SKILL.md +129 -0
- package/.mindforge/skills/graceful-degradation/SKILL.md +95 -0
- package/.mindforge/skills/graphql-patterns/SKILL.md +243 -0
- package/.mindforge/skills/guardrails-and-safety/SKILL.md +137 -0
- package/.mindforge/skills/healthcare-systems/SKILL.md +40 -0
- package/.mindforge/skills/hiring-engineering/SKILL.md +119 -0
- package/.mindforge/skills/human-in-the-loop-design/SKILL.md +234 -0
- package/.mindforge/skills/i18n-architecture/SKILL.md +147 -0
- package/.mindforge/skills/idempotency-patterns/SKILL.md +84 -0
- package/.mindforge/skills/incident-communication/SKILL.md +96 -0
- package/.mindforge/skills/incident-management/SKILL.md +97 -0
- package/.mindforge/skills/infrastructure-as-code/SKILL.md +98 -0
- package/.mindforge/skills/instinct-clustering/SKILL.md +190 -0
- package/.mindforge/skills/internal-developer-platform/SKILL.md +51 -0
- package/.mindforge/skills/iot-platform/SKILL.md +41 -0
- package/.mindforge/skills/k8s-deployment/SKILL.md +358 -0
- package/.mindforge/skills/knowledge-graphs/SKILL.md +56 -0
- package/.mindforge/skills/knowledge-sharing-systems/SKILL.md +112 -0
- package/.mindforge/skills/llm-cost-optimization/SKILL.md +198 -0
- package/.mindforge/skills/llm-orchestration/SKILL.md +56 -0
- package/.mindforge/skills/load-testing/SKILL.md +84 -0
- package/.mindforge/skills/logistics-optimization/SKILL.md +40 -0
- package/.mindforge/skills/market-researcher/SKILL.md +99 -0
- package/.mindforge/skills/marketplace-trust/SKILL.md +40 -0
- package/.mindforge/skills/mcp-server-patterns/SKILL.md +264 -0
- package/.mindforge/skills/media-streaming/SKILL.md +41 -0
- package/.mindforge/skills/meeting-architecture/SKILL.md +146 -0
- package/.mindforge/skills/mentoring-patterns/SKILL.md +77 -0
- package/.mindforge/skills/microservices-patterns/SKILL.md +83 -0
- package/.mindforge/skills/migration-platform/SKILL.md +61 -0
- package/.mindforge/skills/migration-strategies/SKILL.md +129 -0
- package/.mindforge/skills/ml-feature-store/SKILL.md +56 -0
- package/.mindforge/skills/ml-monitoring/SKILL.md +42 -0
- package/.mindforge/skills/mobile-performance/SKILL.md +44 -0
- package/.mindforge/skills/mobile-security/SKILL.md +45 -0
- package/.mindforge/skills/model-evaluation/SKILL.md +53 -0
- package/.mindforge/skills/monorepo-management/SKILL.md +100 -0
- package/.mindforge/skills/multi-tenancy-patterns/SKILL.md +145 -0
- package/.mindforge/skills/multi-turn-conversation-design/SKILL.md +206 -0
- package/.mindforge/skills/multimodal-ai/SKILL.md +51 -0
- package/.mindforge/skills/mutation-testing/SKILL.md +97 -0
- package/.mindforge/skills/notification-system-design/SKILL.md +168 -0
- package/.mindforge/skills/observability-stack/SKILL.md +136 -0
- package/.mindforge/skills/offline-first-design/SKILL.md +43 -0
- package/.mindforge/skills/on-call-design/SKILL.md +111 -0
- package/.mindforge/skills/pagination-patterns/SKILL.md +230 -0
- package/.mindforge/skills/payment-integration/SKILL.md +176 -0
- package/.mindforge/skills/performance-reviews/SKILL.md +140 -0
- package/.mindforge/skills/platform-observability/SKILL.md +58 -0
- package/.mindforge/skills/platform-reliability/SKILL.md +52 -0
- package/.mindforge/skills/post-incident-learning/SKILL.md +96 -0
- package/.mindforge/skills/product-manager/SKILL.md +104 -0
- package/.mindforge/skills/progressive-web-app/SKILL.md +44 -0
- package/.mindforge/skills/prompt-engineering/SKILL.md +94 -0
- package/.mindforge/skills/proofreader/SKILL.md +158 -0
- package/.mindforge/skills/push-notification-architecture/SKILL.md +45 -0
- package/.mindforge/skills/python-performance/SKILL.md +183 -0
- package/.mindforge/skills/quality-audit/SKILL.md +171 -0
- package/.mindforge/skills/queue-design/SKILL.md +85 -0
- package/.mindforge/skills/rag-architecture/SKILL.md +176 -0
- package/.mindforge/skills/rate-limiting-design/SKILL.md +94 -0
- package/.mindforge/skills/react-native-patterns/SKILL.md +42 -0
- package/.mindforge/skills/react-performance/SKILL.md +229 -0
- package/.mindforge/skills/real-time-analytics/SKILL.md +42 -0
- package/.mindforge/skills/real-time-sync/SKILL.md +83 -0
- package/.mindforge/skills/responsive-native/SKILL.md +44 -0
- package/.mindforge/skills/responsive-patterns/SKILL.md +141 -0
- package/.mindforge/skills/rfc-pipeline/SKILL.md +114 -0
- package/.mindforge/skills/saas-multi-tenant/SKILL.md +41 -0
- package/.mindforge/skills/santa-method/SKILL.md +134 -0
- package/.mindforge/skills/search-implementation/SKILL.md +98 -0
- package/.mindforge/skills/secrets-platform/SKILL.md +56 -0
- package/.mindforge/skills/secrets-rotation/SKILL.md +173 -0
- package/.mindforge/skills/self-serve-infrastructure/SKILL.md +51 -0
- package/.mindforge/skills/serverless-patterns/SKILL.md +119 -0
- package/.mindforge/skills/skill-creator-meta/SKILL.md +146 -0
- package/.mindforge/skills/sprint-retrospective-facilitation/SKILL.md +112 -0
- package/.mindforge/skills/stakeholder-communication/SKILL.md +85 -0
- package/.mindforge/skills/state-management/SKILL.md +104 -0
- package/.mindforge/skills/stream-processing/SKILL.md +43 -0
- package/.mindforge/skills/streaming-architecture/SKILL.md +81 -0
- package/.mindforge/skills/supply-chain-security/SKILL.md +145 -0
- package/.mindforge/skills/synthetic-data-generation/SKILL.md +52 -0
- package/.mindforge/skills/system-design/SKILL.md +88 -0
- package/.mindforge/skills/team-topology-design/SKILL.md +107 -0
- package/.mindforge/skills/technical-debt-management/SKILL.md +86 -0
- package/.mindforge/skills/technical-interview-design/SKILL.md +98 -0
- package/.mindforge/skills/technical-leadership/SKILL.md +75 -0
- package/.mindforge/skills/technical-writing/SKILL.md +237 -0
- package/.mindforge/skills/technology-radar/SKILL.md +88 -0
- package/.mindforge/skills/testing-anti-patterns/SKILL.md +288 -0
- package/.mindforge/skills/tool-design/SKILL.md +138 -0
- package/.mindforge/skills/typescript-advanced/SKILL.md +198 -0
- package/.mindforge/skills/using-git-worktrees/SKILL.md +139 -0
- package/.mindforge/skills/verification-loop/SKILL.md +13 -1
- package/.mindforge/skills/vibe-security/SKILL.md +165 -0
- package/.mindforge/skills/visual-regression-testing/SKILL.md +97 -0
- package/.mindforge/skills/websocket-patterns/SKILL.md +203 -0
- package/.mindforge/skills/writing-plans/SKILL.md +170 -0
- package/.mindforge/skills/writing-skills/SKILL.md +216 -0
- package/.mindforge/skills/zero-trust-architecture/SKILL.md +166 -0
- package/CHANGELOG.md +240 -0
- package/MINDFORGE.md +4 -4
- package/README.md +49 -4
- package/RELEASENOTES.md +80 -0
- package/SECURITY.md +20 -8
- package/bin/autonomous/audit-writer.js +13 -0
- package/bin/autonomous/auto-runner.js +74 -16
- package/bin/autonomous/context-refactorer.js +26 -11
- package/bin/autonomous/state-manager.js +62 -6
- package/bin/autonomous/stuck-monitor.js +46 -7
- package/bin/autonomous/wave-executor.js +66 -25
- package/bin/dashboard/api-router.js +43 -0
- package/bin/dashboard/metrics-aggregator.js +28 -1
- package/bin/dashboard/server.js +67 -4
- package/bin/dashboard/sse-bridge.js +4 -4
- package/bin/engine/feedback-loop.js +8 -0
- package/bin/engine/intelligence-interlock.js +32 -15
- package/bin/engine/logic-drift-detector.js +2 -1
- package/bin/engine/nexus-tracer.js +3 -2
- package/bin/engine/remediation-engine.js +155 -32
- package/bin/engine/self-corrective-synthesizer.js +84 -10
- package/bin/engine/sre-manager.js +12 -4
- package/bin/engine/temporal-hub.js +131 -34
- package/bin/governance/approve.js +41 -5
- package/bin/governance/impact-analyzer.js +28 -0
- package/bin/governance/policy-engine.js +10 -3
- package/bin/governance/quantum-crypto.js +32 -19
- package/bin/governance/rbac-manager.js +74 -2
- package/bin/governance/ztai-manager.js +49 -7
- package/bin/hindsight-injector.js +3 -3
- package/bin/memory/eis-client.js +71 -34
- package/bin/memory/embedding-engine.js +61 -0
- package/bin/memory/knowledge-graph.js +58 -5
- package/bin/memory/knowledge-indexer.js +53 -6
- package/bin/memory/knowledge-store.js +22 -0
- package/bin/migrations/10.7.0-to-11.0.0.js +110 -0
- package/bin/migrations/schema-versions.js +13 -0
- package/bin/models/anthropic-provider.js +45 -0
- package/bin/models/cloud-broker.js +68 -20
- package/bin/models/gemini-provider.js +51 -0
- package/bin/models/model-client.js +20 -0
- package/bin/models/model-router.js +28 -8
- package/bin/models/openai-provider.js +44 -0
- package/bin/utils/file-io.js +63 -1
- package/bin/utils/index.js +58 -0
- package/docs/getting-started.md +1 -1
- package/docs/user-guide.md +2 -2
- package/package.json +2 -2
- package/.mindforge/personas/data-privacy-engineer.md +0 -187
|
@@ -122,9 +122,10 @@ class QuantumSafeKeyProvider extends KeyProvider {
|
|
|
122
122
|
async sign(did, data) {
|
|
123
123
|
const record = this.keyStore.get(did);
|
|
124
124
|
if (!record) throw new Error(`PQ record not found for ${did}`);
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
console.log(`[PQAS-DILITHIUM] Delegating signature to lattice enclave [DID: ${did}]`);
|
|
127
|
-
|
|
127
|
+
const result = await this.quantumCrypto.signPQ(data, record.privateKey);
|
|
128
|
+
return result;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
async rotate(did) {
|
|
@@ -148,24 +149,34 @@ class ZTAIManager {
|
|
|
148
149
|
|
|
149
150
|
/**
|
|
150
151
|
* Registers a new agent and assigns a provider based on Trust Tier.
|
|
152
|
+
* @param {string} persona - Agent persona identifier
|
|
153
|
+
* @param {number} tier - Trust tier (1-4)
|
|
154
|
+
* @param {string|null} sessionId - Optional session scope for isolation
|
|
151
155
|
*/
|
|
152
|
-
async registerAgent(persona, tier = 1) {
|
|
156
|
+
async registerAgent(persona, tier = 1, sessionId = null) {
|
|
153
157
|
const uuid = crypto.randomUUID();
|
|
154
158
|
const did = `did:mindforge:${uuid}`;
|
|
155
|
-
|
|
159
|
+
|
|
156
160
|
// Tier 3 agents use the SecureEnclaveProvider
|
|
157
161
|
const providerType = tier >= 3 ? 'enclave' : 'local';
|
|
158
162
|
const provider = this.providers[providerType];
|
|
159
|
-
|
|
163
|
+
|
|
160
164
|
const publicKeyPEM = await provider.generate(did);
|
|
161
165
|
|
|
162
|
-
|
|
166
|
+
const agentData = {
|
|
163
167
|
publicKey: publicKeyPEM,
|
|
164
168
|
persona,
|
|
165
169
|
tier,
|
|
166
170
|
providerType,
|
|
167
171
|
createdAt: new Date().toISOString()
|
|
168
|
-
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Store sessionId if provided for session-scoped isolation
|
|
175
|
+
if (sessionId) {
|
|
176
|
+
agentData.sessionId = sessionId;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.agentRegistry.set(did, agentData);
|
|
169
180
|
|
|
170
181
|
return did;
|
|
171
182
|
}
|
|
@@ -219,6 +230,37 @@ class ZTAIManager {
|
|
|
219
230
|
return this.agentRegistry.get(did);
|
|
220
231
|
}
|
|
221
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Returns all agents registered under a specific session.
|
|
235
|
+
* @param {string} sessionId - Session identifier to filter by
|
|
236
|
+
*/
|
|
237
|
+
getSessionAgents(sessionId) {
|
|
238
|
+
const results = [];
|
|
239
|
+
for (const [did, agent] of this.agentRegistry.entries()) {
|
|
240
|
+
if (agent.sessionId === sessionId) {
|
|
241
|
+
results.push({ did, ...agent });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Revokes all agents belonging to a session. Used for session cleanup.
|
|
249
|
+
* @param {string} sessionId - Session identifier
|
|
250
|
+
*/
|
|
251
|
+
revokeSessionAgents(sessionId) {
|
|
252
|
+
const dids = [];
|
|
253
|
+
for (const [did, agent] of this.agentRegistry.entries()) {
|
|
254
|
+
if (agent.sessionId === sessionId) {
|
|
255
|
+
dids.push(did);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
for (const did of dids) {
|
|
259
|
+
this.revokeAgent(did);
|
|
260
|
+
}
|
|
261
|
+
return dids;
|
|
262
|
+
}
|
|
263
|
+
|
|
222
264
|
/**
|
|
223
265
|
* Specialized signing for FinOps budget decisions (Pillar V).
|
|
224
266
|
*/
|
|
@@ -43,9 +43,9 @@ class HindsightInjector {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// 4. Capture the new state immediately
|
|
46
|
-
TemporalHub.captureState(hindsightEvent.id, {
|
|
47
|
-
event: 'hindsight_injected',
|
|
48
|
-
target_id: auditId
|
|
46
|
+
await TemporalHub.captureState(hindsightEvent.id, {
|
|
47
|
+
event: 'hindsight_injected',
|
|
48
|
+
target_id: auditId
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
return { success: true, event: hindsightEvent };
|
package/bin/memory/eis-client.js
CHANGED
|
@@ -22,19 +22,42 @@ class EISClient {
|
|
|
22
22
|
* @param {Array} entries - Local knowledge entries to sync.
|
|
23
23
|
*/
|
|
24
24
|
async push(entries) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
if (!this.endpoint || this.endpoint === 'http://localhost:7340') {
|
|
26
|
+
return {
|
|
27
|
+
synced: entries.length,
|
|
28
|
+
hashes: entries.map(e => e.id || crypto.createHash('sha256').update(JSON.stringify(e)).digest('hex').slice(0, 8))
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const url = `${this.endpoint}/api/v1/knowledge/push`;
|
|
33
|
+
const body = JSON.stringify({ entries, orgId: this.orgId });
|
|
34
|
+
|
|
35
|
+
let lastError;
|
|
36
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
const headers = await this.getAuthHeader('push', 'knowledge');
|
|
39
|
+
headers['Content-Type'] = 'application/json';
|
|
40
|
+
|
|
41
|
+
const response = await fetch(url, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers,
|
|
44
|
+
body,
|
|
45
|
+
signal: AbortSignal.timeout(10000)
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`EIS push failed: ${response.status}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return await response.json();
|
|
53
|
+
} catch (e) {
|
|
54
|
+
lastError = e;
|
|
55
|
+
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.warn(`[EIS] Push failed after 3 retries: ${lastError.message}`);
|
|
60
|
+
return { synced: 0, error: lastError.message };
|
|
38
61
|
}
|
|
39
62
|
|
|
40
63
|
/**
|
|
@@ -42,35 +65,49 @@ class EISClient {
|
|
|
42
65
|
* @param {Object} filter - Filter criteria (e.g. since timestamp).
|
|
43
66
|
*/
|
|
44
67
|
async pull(filter = {}) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
if (!this.endpoint || this.endpoint === 'http://localhost:7340') {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const url = `${this.endpoint}/api/v1/knowledge/pull`;
|
|
73
|
+
const body = JSON.stringify({ filter, orgId: this.orgId });
|
|
74
|
+
|
|
75
|
+
let lastError;
|
|
76
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
77
|
+
try {
|
|
78
|
+
const headers = await this.getAuthHeader('pull', 'knowledge');
|
|
79
|
+
headers['Content-Type'] = 'application/json';
|
|
80
|
+
|
|
81
|
+
const response = await fetch(url, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers,
|
|
84
|
+
body,
|
|
85
|
+
signal: AbortSignal.timeout(10000)
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
throw new Error(`EIS pull failed: ${response.status}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return await response.json();
|
|
93
|
+
} catch (e) {
|
|
94
|
+
lastError = e;
|
|
95
|
+
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.warn(`[EIS] Pull failed after 3 retries: ${lastError.message}`);
|
|
100
|
+
return [];
|
|
54
101
|
}
|
|
55
102
|
|
|
56
|
-
|
|
57
|
-
* Verifies the authenticity of a remote knowledge entry.
|
|
58
|
-
* @param {Object} entry - The remote entry.
|
|
59
|
-
* @param {String} signature - The ZTAI signature from the remote agent.
|
|
60
|
-
*/
|
|
103
|
+
// TODO: implement when remote nodes are available
|
|
61
104
|
verifyRemoteProvenance(entry, signature) {
|
|
62
105
|
if (!signature) return false;
|
|
63
|
-
// Real implementation would use ZTAIManager to verify the DID signature
|
|
64
106
|
return true;
|
|
65
107
|
}
|
|
66
108
|
|
|
67
|
-
|
|
68
|
-
* Resolves a remote node reference.
|
|
69
|
-
* @param {String} nodeId - The ID of the remote node.
|
|
70
|
-
*/
|
|
109
|
+
// TODO: implement when remote nodes are available
|
|
71
110
|
async resolveRemoteNode(nodeId) {
|
|
72
|
-
console.log(`[EIS-RESOLVE] Resolving remote node: ${nodeId}`);
|
|
73
|
-
// Real implementation would fetch from the EIS API
|
|
74
111
|
return null;
|
|
75
112
|
}
|
|
76
113
|
|
|
@@ -130,6 +130,65 @@ function computeTfIdfVector(tokens, df, N) {
|
|
|
130
130
|
return capped;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// ── BM25 Scoring ─────────────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* BM25 relevance scoring with document length normalization.
|
|
137
|
+
* @param {string[]} queryTokens - Tokenized query
|
|
138
|
+
* @param {string[]} docTokens - Tokenized document
|
|
139
|
+
* @param {Object<string, number>} docFrequency - term → number of docs containing term
|
|
140
|
+
* @param {number} totalDocs - Total documents in corpus
|
|
141
|
+
* @param {number} avgDocLength - Average document length across corpus
|
|
142
|
+
* @returns {number} BM25 score
|
|
143
|
+
*/
|
|
144
|
+
function bm25Score(queryTokens, docTokens, docFrequency, totalDocs, avgDocLength) {
|
|
145
|
+
const k1 = 1.5;
|
|
146
|
+
const b = 0.75;
|
|
147
|
+
let score = 0;
|
|
148
|
+
const docLength = docTokens.length;
|
|
149
|
+
|
|
150
|
+
for (const term of queryTokens) {
|
|
151
|
+
const tf = docTokens.filter(t => t === term).length;
|
|
152
|
+
const df = docFrequency[term] || 0;
|
|
153
|
+
const idf = Math.log((totalDocs - df + 0.5) / (df + 0.5) + 1);
|
|
154
|
+
const tfNorm = (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * (docLength / avgDocLength)));
|
|
155
|
+
score += idf * tfNorm;
|
|
156
|
+
}
|
|
157
|
+
return score;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Build a reusable BM25 index structure from knowledge entries.
|
|
162
|
+
* Applies 2x weighting to compound terms (camelCase/underscore bigrams).
|
|
163
|
+
* @param {object[]} entries - Knowledge entries with { id, topic, content, tags }
|
|
164
|
+
* @returns {{ docFrequency: Object<string, number>, avgDocLength: number, tokenizedDocs: Array<{id: string, tokens: string[]}> }}
|
|
165
|
+
*/
|
|
166
|
+
function buildBM25Index(entries) {
|
|
167
|
+
const tokenizedDocs = entries
|
|
168
|
+
.filter(e => !e.deprecated)
|
|
169
|
+
.map(e => {
|
|
170
|
+
const text = `${e.topic || ''} ${e.content || ''} ${(e.tags || []).join(' ')}`;
|
|
171
|
+
const unigrams = tokenize(text);
|
|
172
|
+
const bi = bigrams(unigrams);
|
|
173
|
+
// Weight compound terms at 2x by duplicating bigrams
|
|
174
|
+
const tokens = [...unigrams, ...bi, ...bi];
|
|
175
|
+
return { id: e.id, tokens };
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const docFrequency = {};
|
|
179
|
+
for (const doc of tokenizedDocs) {
|
|
180
|
+
const unique = new Set(doc.tokens);
|
|
181
|
+
for (const term of unique) {
|
|
182
|
+
docFrequency[term] = (docFrequency[term] || 0) + 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const totalTokens = tokenizedDocs.reduce((sum, doc) => sum + doc.tokens.length, 0);
|
|
187
|
+
const avgDocLength = tokenizedDocs.length > 0 ? totalTokens / tokenizedDocs.length : 0;
|
|
188
|
+
|
|
189
|
+
return { docFrequency, avgDocLength, tokenizedDocs };
|
|
190
|
+
}
|
|
191
|
+
|
|
133
192
|
// ── Similarity ────────────────────────────────────────────────────────────────
|
|
134
193
|
|
|
135
194
|
/**
|
|
@@ -321,6 +380,8 @@ module.exports = {
|
|
|
321
380
|
inferEdges,
|
|
322
381
|
saveCache,
|
|
323
382
|
loadCache,
|
|
383
|
+
bm25Score,
|
|
384
|
+
buildBM25Index,
|
|
324
385
|
SIMILARITY_THRESHOLD,
|
|
325
386
|
SHADOW_THRESHOLD,
|
|
326
387
|
};
|
|
@@ -109,6 +109,7 @@ function addEdge(edge) {
|
|
|
109
109
|
record.checksum = crypto.createHash('sha256').update(payload).digest('hex');
|
|
110
110
|
|
|
111
111
|
fs.appendFileSync(paths.EDGES_PATH, JSON.stringify(record) + '\n');
|
|
112
|
+
invalidateAdjacencyCache();
|
|
112
113
|
return id;
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -155,6 +156,7 @@ function deprecateEdge(edgeId, reason) {
|
|
|
155
156
|
};
|
|
156
157
|
|
|
157
158
|
fs.appendFileSync(paths.EDGES_PATH, JSON.stringify(deprecated) + '\n');
|
|
159
|
+
invalidateAdjacencyCache();
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
/**
|
|
@@ -181,18 +183,68 @@ function reinforceEdge(edgeId) {
|
|
|
181
183
|
fs.appendFileSync(paths.EDGES_PATH, JSON.stringify(reinforced) + '\n');
|
|
182
184
|
}
|
|
183
185
|
|
|
184
|
-
// ── Adjacency Index
|
|
186
|
+
// ── Adjacency Index (with persistent cache) ─────────────────────────────────
|
|
187
|
+
|
|
188
|
+
function getAdjacencyCachePath() {
|
|
189
|
+
const paths = getPaths();
|
|
190
|
+
return path.join(paths.MEMORY_DIR, '.adjacency-cache.json');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function invalidateAdjacencyCache() {
|
|
194
|
+
const cachePath = getAdjacencyCachePath();
|
|
195
|
+
if (fs.existsSync(cachePath)) {
|
|
196
|
+
fs.unlinkSync(cachePath);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Load adjacency index from cache if edges file hasn't changed,
|
|
202
|
+
* otherwise rebuild and persist.
|
|
203
|
+
* @param {object[]} edges - All active edges (used for rebuild)
|
|
204
|
+
* @returns {Map<string, object[]>} nodeId → [{ edge, neighborId, direction }]
|
|
205
|
+
*/
|
|
206
|
+
function loadOrBuildAdjacencyIndex(edges) {
|
|
207
|
+
const paths = getPaths();
|
|
208
|
+
const cachePath = getAdjacencyCachePath();
|
|
209
|
+
const edgesStat = fs.statSync(paths.EDGES_PATH, { throwIfNoEntry: false });
|
|
210
|
+
|
|
211
|
+
if (edgesStat && fs.existsSync(cachePath)) {
|
|
212
|
+
try {
|
|
213
|
+
const cache = JSON.parse(fs.readFileSync(cachePath, 'utf8'));
|
|
214
|
+
if (cache.mtime === edgesStat.mtimeMs) {
|
|
215
|
+
const index = new Map();
|
|
216
|
+
for (const [nodeId, neighbors] of Object.entries(cache.adjacency)) {
|
|
217
|
+
index.set(nodeId, neighbors);
|
|
218
|
+
}
|
|
219
|
+
return index;
|
|
220
|
+
}
|
|
221
|
+
} catch (e) { /* cache corrupt, rebuild */ }
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const index = buildAdjacencyIndex(edges);
|
|
225
|
+
|
|
226
|
+
if (edgesStat) {
|
|
227
|
+
const serialized = {};
|
|
228
|
+
for (const [nodeId, neighbors] of index) {
|
|
229
|
+
serialized[nodeId] = neighbors;
|
|
230
|
+
}
|
|
231
|
+
const cacheData = { mtime: edgesStat.mtimeMs, adjacency: serialized };
|
|
232
|
+
ensureDir(paths.MEMORY_DIR);
|
|
233
|
+
fs.writeFileSync(cachePath, JSON.stringify(cacheData));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return index;
|
|
237
|
+
}
|
|
185
238
|
|
|
186
239
|
/**
|
|
187
240
|
* Build an in-memory adjacency index for O(1) neighbor lookups.
|
|
188
241
|
* @param {object[]} edges - All active edges
|
|
189
|
-
* @returns {Map<string, object[]>} nodeId → [{ edge, neighborId }]
|
|
242
|
+
* @returns {Map<string, object[]>} nodeId → [{ edge, neighborId, direction }]
|
|
190
243
|
*/
|
|
191
244
|
function buildAdjacencyIndex(edges) {
|
|
192
245
|
const index = new Map();
|
|
193
246
|
|
|
194
247
|
for (const edge of edges) {
|
|
195
|
-
// Forward direction
|
|
196
248
|
if (!index.has(edge.sourceId)) index.set(edge.sourceId, []);
|
|
197
249
|
index.get(edge.sourceId).push({
|
|
198
250
|
edge,
|
|
@@ -200,7 +252,6 @@ function buildAdjacencyIndex(edges) {
|
|
|
200
252
|
direction: 'outgoing',
|
|
201
253
|
});
|
|
202
254
|
|
|
203
|
-
// Reverse direction (for bidirectional traversal)
|
|
204
255
|
if (!index.has(edge.targetId)) index.set(edge.targetId, []);
|
|
205
256
|
index.get(edge.targetId).push({
|
|
206
257
|
edge,
|
|
@@ -262,7 +313,7 @@ function addFederatedEdge(edge) {
|
|
|
262
313
|
function traverse(startId, maxDepth = 2, opts = {}) {
|
|
263
314
|
const { edgeTypes, minWeight = 0 } = opts;
|
|
264
315
|
const edges = readAllEdges();
|
|
265
|
-
const adjacency =
|
|
316
|
+
const adjacency = loadOrBuildAdjacencyIndex(edges);
|
|
266
317
|
|
|
267
318
|
const visited = new Set();
|
|
268
319
|
const results = [];
|
|
@@ -598,6 +649,8 @@ module.exports = {
|
|
|
598
649
|
deprecateEdge,
|
|
599
650
|
reinforceEdge,
|
|
600
651
|
buildAdjacencyIndex,
|
|
652
|
+
loadOrBuildAdjacencyIndex,
|
|
653
|
+
invalidateAdjacencyCache,
|
|
601
654
|
traverse,
|
|
602
655
|
findRelated,
|
|
603
656
|
getNodeEdges,
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
12
14
|
const Store = require('./knowledge-store');
|
|
15
|
+
const { buildBM25Index, bm25Score } = require('./embedding-engine');
|
|
13
16
|
|
|
14
17
|
// ── Stopwords (excluded from TF-IDF scoring) ──────────────────────────────────
|
|
15
18
|
const STOPWORDS = new Set([
|
|
@@ -79,6 +82,48 @@ function tfidfScore(queryTokens, entryId, index, docTokenCounts, N) {
|
|
|
79
82
|
return score;
|
|
80
83
|
}
|
|
81
84
|
|
|
85
|
+
// ── Persistent BM25 Index Cache ──────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
function getKbPath() {
|
|
88
|
+
const memoryDir = path.join(process.cwd(), '.mindforge', 'memory');
|
|
89
|
+
return path.join(memoryDir, 'knowledge.jsonl');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getCachePath() {
|
|
93
|
+
const memoryDir = path.join(process.cwd(), '.mindforge', 'memory');
|
|
94
|
+
return path.join(memoryDir, '.index-cache.json');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Load BM25 index from cache if source file hasn't changed,
|
|
99
|
+
* otherwise rebuild and persist.
|
|
100
|
+
*/
|
|
101
|
+
function loadOrBuildIndex(entries) {
|
|
102
|
+
const kbPath = getKbPath();
|
|
103
|
+
const cachePath = getCachePath();
|
|
104
|
+
const stat = fs.statSync(kbPath, { throwIfNoEntry: false });
|
|
105
|
+
|
|
106
|
+
if (stat && fs.existsSync(cachePath)) {
|
|
107
|
+
try {
|
|
108
|
+
const cache = JSON.parse(fs.readFileSync(cachePath, 'utf8'));
|
|
109
|
+
if (cache.mtime === stat.mtimeMs && cache.entryCount === entries.length) {
|
|
110
|
+
return cache.index;
|
|
111
|
+
}
|
|
112
|
+
} catch (e) { /* cache corrupt, rebuild */ }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const index = buildBM25Index(entries);
|
|
116
|
+
|
|
117
|
+
if (stat) {
|
|
118
|
+
const dir = path.dirname(cachePath);
|
|
119
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
120
|
+
const cacheData = { mtime: stat.mtimeMs, entryCount: entries.length, index };
|
|
121
|
+
fs.writeFileSync(cachePath, JSON.stringify(cacheData));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return index;
|
|
125
|
+
}
|
|
126
|
+
|
|
82
127
|
// ── Main search function ──────────────────────────────────────────────────────
|
|
83
128
|
/**
|
|
84
129
|
* Search knowledge base with TF-IDF scoring.
|
|
@@ -106,18 +151,20 @@ function search(queryText, filters = {}, limit = 10) {
|
|
|
106
151
|
|
|
107
152
|
const queryTokens = tokenize(queryText);
|
|
108
153
|
if (queryTokens.length === 0) {
|
|
109
|
-
// No meaningful query tokens — return by confidence
|
|
110
154
|
return candidates
|
|
111
155
|
.sort((a, b) => b.confidence - a.confidence)
|
|
112
156
|
.slice(0, limit);
|
|
113
157
|
}
|
|
114
158
|
|
|
115
|
-
|
|
159
|
+
// Use cached BM25 index for scoring
|
|
160
|
+
const bm25Index = loadOrBuildIndex(candidates);
|
|
161
|
+
const { docFrequency, avgDocLength, tokenizedDocs } = bm25Index;
|
|
162
|
+
const totalDocs = tokenizedDocs.length;
|
|
163
|
+
const docMap = new Map(tokenizedDocs.map(d => [d.id, d.tokens]));
|
|
116
164
|
|
|
117
|
-
// Score each candidate
|
|
118
165
|
const scored = candidates.map(entry => {
|
|
119
|
-
const
|
|
120
|
-
|
|
166
|
+
const docTokens = docMap.get(entry.id) || [];
|
|
167
|
+
const textScore = bm25Score(queryTokens, docTokens, docFrequency, totalDocs, avgDocLength);
|
|
121
168
|
const finalScore = textScore > 0
|
|
122
169
|
? textScore * 0.7 + entry.confidence * 0.3
|
|
123
170
|
: 0;
|
|
@@ -169,4 +216,4 @@ function loadSessionContext(context = {}) {
|
|
|
169
216
|
return { preferences, decisions, bugPatterns, codePatterns, domain };
|
|
170
217
|
}
|
|
171
218
|
|
|
172
|
-
module.exports = { search, loadSessionContext, buildIndex, tfidfScore, tokenize };
|
|
219
|
+
module.exports = { search, loadSessionContext, buildIndex, tfidfScore, tokenize, loadOrBuildIndex };
|
|
@@ -126,6 +126,22 @@ function getFilePath(type) {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// ── File Integrity ────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Ensures a JSONL file doesn't end with a partial/truncated line.
|
|
133
|
+
* Appends a trailing newline if missing — prevents corruption from propagating.
|
|
134
|
+
*/
|
|
135
|
+
function verifyFileIntegrity(filePath) {
|
|
136
|
+
if (!fs.existsSync(filePath)) return true;
|
|
137
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
138
|
+
if (content.length === 0) return true;
|
|
139
|
+
if (!content.endsWith('\n')) {
|
|
140
|
+
fs.appendFileSync(filePath, '\n');
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
129
145
|
// ── Write operations ──────────────────────────────────────────────────────────
|
|
130
146
|
|
|
131
147
|
/**
|
|
@@ -184,10 +200,12 @@ function add(entry) {
|
|
|
184
200
|
};
|
|
185
201
|
|
|
186
202
|
const filePath = getFilePath(entry.type);
|
|
203
|
+
verifyFileIntegrity(filePath);
|
|
187
204
|
fs.appendFileSync(filePath, JSON.stringify(full) + '\n');
|
|
188
205
|
|
|
189
206
|
// Also append to unified knowledge-base.jsonl for cross-type queries
|
|
190
207
|
if (filePath !== paths.KB_PATH) {
|
|
208
|
+
verifyFileIntegrity(paths.KB_PATH);
|
|
191
209
|
fs.appendFileSync(paths.KB_PATH, JSON.stringify(full) + '\n');
|
|
192
210
|
}
|
|
193
211
|
|
|
@@ -217,8 +235,10 @@ function deprecate(id, reason, supersededBy = null) {
|
|
|
217
235
|
deprecated_at: new Date().toISOString(),
|
|
218
236
|
};
|
|
219
237
|
|
|
238
|
+
verifyFileIntegrity(filePath);
|
|
220
239
|
fs.appendFileSync(filePath, JSON.stringify(deprecated) + '\n');
|
|
221
240
|
if (filePath !== paths.KB_PATH) {
|
|
241
|
+
verifyFileIntegrity(paths.KB_PATH);
|
|
222
242
|
fs.appendFileSync(paths.KB_PATH, JSON.stringify(deprecated) + '\n');
|
|
223
243
|
}
|
|
224
244
|
|
|
@@ -246,8 +266,10 @@ function reinforce(id) {
|
|
|
246
266
|
};
|
|
247
267
|
|
|
248
268
|
const filePath = getFilePath(entry.type);
|
|
269
|
+
verifyFileIntegrity(filePath);
|
|
249
270
|
fs.appendFileSync(filePath, JSON.stringify(reinforced) + '\n');
|
|
250
271
|
if (filePath !== paths.KB_PATH) {
|
|
272
|
+
verifyFileIntegrity(paths.KB_PATH);
|
|
251
273
|
fs.appendFileSync(paths.KB_PATH, JSON.stringify(reinforced) + '\n');
|
|
252
274
|
}
|
|
253
275
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const MIGRATION_ID = '10.7.0-to-11.0.0';
|
|
7
|
+
const TARGET_VERSION = '11.0.0';
|
|
8
|
+
|
|
9
|
+
async function migrate(projectRoot) {
|
|
10
|
+
const results = { steps: [], success: true };
|
|
11
|
+
|
|
12
|
+
// Step 1: Backup config.json
|
|
13
|
+
const configPath = path.join(projectRoot, '.mindforge', 'config.json');
|
|
14
|
+
if (fs.existsSync(configPath)) {
|
|
15
|
+
const backupPath = configPath + '.v10-backup';
|
|
16
|
+
fs.copyFileSync(configPath, backupPath);
|
|
17
|
+
results.steps.push({ step: 'backup_config', status: 'done', path: backupPath });
|
|
18
|
+
|
|
19
|
+
// Step 2: Add new config sections
|
|
20
|
+
try {
|
|
21
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
22
|
+
|
|
23
|
+
if (!config.temporal) {
|
|
24
|
+
config.temporal = { max_snapshots: 50, max_age_days: 7 };
|
|
25
|
+
}
|
|
26
|
+
if (!config.rate_limiting) {
|
|
27
|
+
config.rate_limiting = { dashboard_rpm: 100, model_rpm: {} };
|
|
28
|
+
}
|
|
29
|
+
if (!config.session) {
|
|
30
|
+
config.session = { token_expiry_hours: 24 };
|
|
31
|
+
}
|
|
32
|
+
if (!config.wave_execution) {
|
|
33
|
+
config.wave_execution = { max_concurrency: 3 };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
config.version = TARGET_VERSION;
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
39
|
+
results.steps.push({ step: 'update_config', status: 'done' });
|
|
40
|
+
} catch (e) {
|
|
41
|
+
results.steps.push({ step: 'update_config', status: 'warning', error: e.message });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Step 3: Archive old AUDIT lines if > 5000
|
|
46
|
+
const auditPath = path.join(projectRoot, '.planning', 'AUDIT.jsonl');
|
|
47
|
+
if (fs.existsSync(auditPath)) {
|
|
48
|
+
try {
|
|
49
|
+
const content = fs.readFileSync(auditPath, 'utf8');
|
|
50
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
51
|
+
if (lines.length > 5000) {
|
|
52
|
+
const archiveDir = path.join(projectRoot, '.planning', 'audit-archive');
|
|
53
|
+
if (!fs.existsSync(archiveDir)) fs.mkdirSync(archiveDir, { recursive: true });
|
|
54
|
+
|
|
55
|
+
const zlib = require('zlib');
|
|
56
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
57
|
+
const archivePath = path.join(archiveDir, `AUDIT-pre-v11-${timestamp}.jsonl.gz`);
|
|
58
|
+
const toArchive = lines.slice(0, -500).join('\n') + '\n';
|
|
59
|
+
fs.writeFileSync(archivePath, zlib.gzipSync(toArchive));
|
|
60
|
+
|
|
61
|
+
const remaining = lines.slice(-500).join('\n') + '\n';
|
|
62
|
+
fs.writeFileSync(auditPath, remaining);
|
|
63
|
+
results.steps.push({ step: 'archive_audit', status: 'done', archived: lines.length - 500 });
|
|
64
|
+
} else {
|
|
65
|
+
results.steps.push({ step: 'archive_audit', status: 'skipped', reason: 'under_threshold' });
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
results.steps.push({ step: 'archive_audit', status: 'warning', error: e.message });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Step 4: GC old snapshots
|
|
73
|
+
try {
|
|
74
|
+
const TemporalHub = require('../engine/temporal-hub');
|
|
75
|
+
const gcResult = await TemporalHub.gc({ maxSnapshots: 50, maxAgeDays: 30 });
|
|
76
|
+
results.steps.push({ step: 'snapshot_gc', status: 'done', deleted: gcResult.deleted });
|
|
77
|
+
} catch (e) {
|
|
78
|
+
results.steps.push({ step: 'snapshot_gc', status: 'warning', error: e.message });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Step 5: Bump schema_version in HANDOFF.json
|
|
82
|
+
const handoffPath = path.join(projectRoot, '.planning', 'HANDOFF.json');
|
|
83
|
+
if (fs.existsSync(handoffPath)) {
|
|
84
|
+
try {
|
|
85
|
+
const handoff = JSON.parse(fs.readFileSync(handoffPath, 'utf8'));
|
|
86
|
+
handoff.schema_version = TARGET_VERSION;
|
|
87
|
+
fs.writeFileSync(handoffPath, JSON.stringify(handoff, null, 2) + '\n');
|
|
88
|
+
results.steps.push({ step: 'bump_handoff_version', status: 'done' });
|
|
89
|
+
} catch (e) {
|
|
90
|
+
results.steps.push({ step: 'bump_handoff_version', status: 'warning', error: e.message });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Step 6: Update MINDFORGE.md VERSION
|
|
95
|
+
const mindforgeFile = path.join(projectRoot, 'MINDFORGE.md');
|
|
96
|
+
if (fs.existsSync(mindforgeFile)) {
|
|
97
|
+
try {
|
|
98
|
+
let content = fs.readFileSync(mindforgeFile, 'utf8');
|
|
99
|
+
content = content.replace(/VERSION\s*=\s*[\d.]+/, `VERSION = ${TARGET_VERSION}`);
|
|
100
|
+
fs.writeFileSync(mindforgeFile, content);
|
|
101
|
+
results.steps.push({ step: 'bump_mindforge_version', status: 'done' });
|
|
102
|
+
} catch (e) {
|
|
103
|
+
results.steps.push({ step: 'bump_mindforge_version', status: 'warning', error: e.message });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return results;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = { MIGRATION_ID, TARGET_VERSION, migrate };
|