amalfa 0.0.0-reserved → 1.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/.biomeignore +19 -0
- package/:memory: +0 -0
- package/:memory:-shm +0 -0
- package/:memory:-wal +0 -0
- package/LICENSE +21 -0
- package/README.md +343 -13
- package/README.old.md +112 -0
- package/agents.config.json +11 -0
- package/amalfa.config.example.ts +100 -0
- package/biome.json +49 -0
- package/bun.lock +371 -0
- package/docs/AGENT_PROTOCOLS.md +28 -0
- package/docs/ARCHITECTURAL_OVERVIEW.md +123 -0
- package/docs/BENTO_BOXING_DEPRECATION.md +281 -0
- package/docs/Bun-SQLite.html +464 -0
- package/docs/COMMIT_GUIDELINES.md +367 -0
- package/docs/DEVELOPER_ONBOARDING.md +36 -0
- package/docs/Graph and Vector Database Best Practices.md +214 -0
- package/docs/PERFORMANCE_BASELINES.md +88 -0
- package/docs/REPOSITORY_CLEANUP_SUMMARY.md +261 -0
- package/docs/edge-generation-methods.md +57 -0
- package/docs/elevator-pitch.md +118 -0
- package/docs/graph-and-vector-database-playbook.html +480 -0
- package/docs/hardened-sqlite.md +85 -0
- package/docs/headless-knowledge-management.md +79 -0
- package/docs/john-kaye-flux-prompt.md +46 -0
- package/docs/keyboard-shortcuts.md +80 -0
- package/docs/opinion-proceed-pattern.md +29 -0
- package/docs/polyvis-nodes-edges-schema.md +77 -0
- package/docs/protocols/lab-protocol.md +30 -0
- package/docs/reaction-iquest-loop-coder.md +46 -0
- package/docs/services.md +60 -0
- package/docs/sqlite-wal-readonly-trap.md +228 -0
- package/docs/strategy/css-architecture.md +40 -0
- package/docs/test-document-cycle.md +83 -0
- package/docs/test_lifecycle_E2E.md +4 -0
- package/docs/the-bicameral-graph.md +83 -0
- package/docs/user-guide.md +70 -0
- package/docs/vision-helper.md +53 -0
- package/drizzle/0000_minor_iron_fist.sql +19 -0
- package/drizzle/meta/0000_snapshot.json +139 -0
- package/drizzle/meta/_journal.json +13 -0
- package/example_usage.ts +39 -0
- package/experiment.sh +35 -0
- package/hello +2 -0
- package/index.html +52 -0
- package/knowledge/excalibur.md +12 -0
- package/package.json +60 -15
- package/plans/experience-graph-integration.md +60 -0
- package/prompts/gemini-king-mode-prompt.md +46 -0
- package/public/docs/MCP_TOOLS.md +372 -0
- package/schemas/README.md +20 -0
- package/schemas/cda.schema.json +84 -0
- package/schemas/conceptual-lexicon.schema.json +75 -0
- package/scratchpads/dummy-debrief-boxed.md +39 -0
- package/scratchpads/dummy-debrief.md +27 -0
- package/scratchpads/scratchpad-design.md +50 -0
- package/scratchpads/scratchpad-scrolling.md +20 -0
- package/scratchpads/scratchpad-toc-disappearance.md +23 -0
- package/scratchpads/scratchpad-toc.md +28 -0
- package/scratchpads/test_gardener.md +7 -0
- package/src/EnlightenedTriad.ts +146 -0
- package/src/JIT_Triad.ts +137 -0
- package/src/cli.ts +318 -0
- package/src/config/constants.ts +7 -0
- package/src/config/defaults.ts +81 -0
- package/src/core/BentoNormalizer.ts +113 -0
- package/src/core/EdgeWeaver.ts +145 -0
- package/src/core/FractureLogic.ts +22 -0
- package/src/core/Harvester.ts +73 -0
- package/src/core/LLMClient.ts +93 -0
- package/src/core/LouvainGate.ts +67 -0
- package/src/core/MarkdownMasker.ts +49 -0
- package/src/core/README.md +11 -0
- package/src/core/SemanticMatcher.ts +89 -0
- package/src/core/SemanticWeaver.ts +96 -0
- package/src/core/TagEngine.ts +56 -0
- package/src/core/TimelineWeaver.ts +61 -0
- package/src/core/VectorEngine.ts +232 -0
- package/src/daemon/index.ts +221 -0
- package/src/data/experience/test_doc_1.md +2 -0
- package/src/data/experience/test_doc_2.md +2 -0
- package/src/db/schema.ts +46 -0
- package/src/demo-triad.ts +45 -0
- package/src/gardeners/AutoTagger.ts +116 -0
- package/src/gardeners/BaseGardener.ts +55 -0
- package/src/llm/EnlightenedProvider.ts +95 -0
- package/src/mcp/README.md +6 -0
- package/src/mcp/index.ts +341 -0
- package/src/pipeline/AmalfaIngestor.ts +262 -0
- package/src/pipeline/HarvesterPipeline.ts +101 -0
- package/src/pipeline/Ingestor.ts +555 -0
- package/src/pipeline/README.md +7 -0
- package/src/pipeline/SemanticHarvester.ts +222 -0
- package/src/resonance/DatabaseFactory.ts +100 -0
- package/src/resonance/README.md +148 -0
- package/src/resonance/cli/README.md +7 -0
- package/src/resonance/cli/ingest.ts +41 -0
- package/src/resonance/cli/migrate.ts +54 -0
- package/src/resonance/config.ts +40 -0
- package/src/resonance/daemon.ts +236 -0
- package/src/resonance/db.ts +422 -0
- package/src/resonance/pipeline/README.md +7 -0
- package/src/resonance/pipeline/extract.ts +89 -0
- package/src/resonance/pipeline/transform_docs.ts +60 -0
- package/src/resonance/schema.ts +138 -0
- package/src/resonance/services/embedder.ts +131 -0
- package/src/resonance/services/simpleTokenizer.ts +119 -0
- package/src/resonance/services/stats.ts +327 -0
- package/src/resonance/services/tokenizer.ts +159 -0
- package/src/resonance/transform/cda.ts +393 -0
- package/src/resonance/types/enriched-cda.ts +112 -0
- package/src/services/README.md +56 -0
- package/src/services/llama.ts +59 -0
- package/src/services/llamauv.ts +56 -0
- package/src/services/olmo3.ts +58 -0
- package/src/services/phi.ts +52 -0
- package/src/types/artifact.ts +12 -0
- package/src/utils/EnvironmentVerifier.ts +67 -0
- package/src/utils/Logger.ts +21 -0
- package/src/utils/ServiceLifecycle.ts +207 -0
- package/src/utils/ZombieDefense.ts +244 -0
- package/src/utils/validator.ts +264 -0
- package/substack/substack-playbook-1.md +95 -0
- package/substack/substack-playbook-2.md +78 -0
- package/tasks/ui-investigation.md +26 -0
- package/test-db +0 -0
- package/test-db-shm +0 -0
- package/test-db-wal +0 -0
- package/tests/canary/verify_pinch_check.ts +44 -0
- package/tests/fixtures/ingest_test.md +12 -0
- package/tests/fixtures/ingest_test_boxed.md +13 -0
- package/tests/fixtures/safety_test.md +45 -0
- package/tests/fixtures/safety_test_boxed.md +49 -0
- package/tests/fixtures/tagged_output.md +49 -0
- package/tests/fixtures/tagged_test.md +49 -0
- package/tests/mcp-server-settings.json +8 -0
- package/tsconfig.json +46 -0
- package/verify-embedder.ts +54 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CDA/CL Transformation Pipeline
|
|
5
|
+
*
|
|
6
|
+
* Transforms raw CDA and Lexicon into enriched intermediate structure
|
|
7
|
+
* with keyword extraction and candidate relationship generation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { SemanticMatcher } from "@src/core/SemanticMatcher";
|
|
12
|
+
import type {
|
|
13
|
+
CandidateRelationship,
|
|
14
|
+
EnrichedCdaDocument,
|
|
15
|
+
EnrichedCdaEntry,
|
|
16
|
+
EnrichedLexiconConcept,
|
|
17
|
+
EnrichedLexiconDocument,
|
|
18
|
+
} from "@src/resonance/types/enriched-cda";
|
|
19
|
+
import settings from "@/polyvis.settings.json";
|
|
20
|
+
|
|
21
|
+
// Simple keyword extraction (can be enhanced later)
|
|
22
|
+
function extractKeywords(text: string): string[] {
|
|
23
|
+
if (!text) return [];
|
|
24
|
+
|
|
25
|
+
// Remove common words, extract significant terms
|
|
26
|
+
const stopWords = new Set([
|
|
27
|
+
"the",
|
|
28
|
+
"a",
|
|
29
|
+
"an",
|
|
30
|
+
"and",
|
|
31
|
+
"or",
|
|
32
|
+
"but",
|
|
33
|
+
"in",
|
|
34
|
+
"on",
|
|
35
|
+
"at",
|
|
36
|
+
"to",
|
|
37
|
+
"for",
|
|
38
|
+
"of",
|
|
39
|
+
"with",
|
|
40
|
+
"by",
|
|
41
|
+
"from",
|
|
42
|
+
"as",
|
|
43
|
+
"is",
|
|
44
|
+
"are",
|
|
45
|
+
"was",
|
|
46
|
+
"were",
|
|
47
|
+
"be",
|
|
48
|
+
"been",
|
|
49
|
+
"being",
|
|
50
|
+
"have",
|
|
51
|
+
"has",
|
|
52
|
+
"had",
|
|
53
|
+
"do",
|
|
54
|
+
"does",
|
|
55
|
+
"did",
|
|
56
|
+
"will",
|
|
57
|
+
"would",
|
|
58
|
+
"should",
|
|
59
|
+
"could",
|
|
60
|
+
"may",
|
|
61
|
+
"might",
|
|
62
|
+
"must",
|
|
63
|
+
"can",
|
|
64
|
+
"this",
|
|
65
|
+
"that",
|
|
66
|
+
"these",
|
|
67
|
+
"those",
|
|
68
|
+
"it",
|
|
69
|
+
"its",
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
const words = text
|
|
73
|
+
.toLowerCase()
|
|
74
|
+
.replace(/[^a-z0-9\s-]/g, " ")
|
|
75
|
+
.split(/\s+/)
|
|
76
|
+
.filter((w) => w.length > 3 && !stopWords.has(w));
|
|
77
|
+
|
|
78
|
+
// Return unique keywords
|
|
79
|
+
return [...new Set(words)];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Match keywords to lexicon concepts
|
|
83
|
+
function matchKeywordsToConcepts(
|
|
84
|
+
keywords: string[],
|
|
85
|
+
concepts: EnrichedLexiconConcept[],
|
|
86
|
+
): CandidateRelationship[] {
|
|
87
|
+
const relationships: CandidateRelationship[] = [];
|
|
88
|
+
|
|
89
|
+
for (const keyword of keywords) {
|
|
90
|
+
for (const concept of concepts) {
|
|
91
|
+
// Check title match
|
|
92
|
+
const titleMatch = concept.title.toLowerCase().includes(keyword);
|
|
93
|
+
const aliasMatch = concept.aliases.some((alias) =>
|
|
94
|
+
alias.toLowerCase().includes(keyword),
|
|
95
|
+
);
|
|
96
|
+
const keywordMatch = concept.extracted_keywords.includes(keyword);
|
|
97
|
+
|
|
98
|
+
if (titleMatch || aliasMatch || keywordMatch) {
|
|
99
|
+
// Calculate confidence based on match type
|
|
100
|
+
let confidence = 0.5; // Base confidence for keyword match
|
|
101
|
+
if (titleMatch) confidence = 0.85;
|
|
102
|
+
if (aliasMatch) confidence = 0.75;
|
|
103
|
+
|
|
104
|
+
relationships.push({
|
|
105
|
+
type: "MENTIONS",
|
|
106
|
+
target: concept.id,
|
|
107
|
+
confidence,
|
|
108
|
+
source: "keyword_match",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Deduplicate and keep highest confidence
|
|
115
|
+
const deduped = new Map<string, CandidateRelationship>();
|
|
116
|
+
for (const rel of relationships) {
|
|
117
|
+
const existing = deduped.get(rel.target);
|
|
118
|
+
if (!existing || rel.confidence > existing.confidence) {
|
|
119
|
+
deduped.set(rel.target, rel);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return Array.from(deduped.values());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Parse explicit tags from CDA entries
|
|
127
|
+
function parseExplicitTags(
|
|
128
|
+
tags: string[],
|
|
129
|
+
concepts: EnrichedLexiconConcept[],
|
|
130
|
+
): CandidateRelationship[] {
|
|
131
|
+
const relationships: CandidateRelationship[] = [];
|
|
132
|
+
|
|
133
|
+
for (const tag of tags) {
|
|
134
|
+
// Match pattern: [TYPE: Target]
|
|
135
|
+
const match = tag.match(/\[([A-Z_]+):\s*([^\]]+)\]/);
|
|
136
|
+
if (!match) continue;
|
|
137
|
+
|
|
138
|
+
const typeStr = match[1];
|
|
139
|
+
const targetStr = match[2];
|
|
140
|
+
if (!typeStr || !targetStr) continue;
|
|
141
|
+
|
|
142
|
+
const target = targetStr.trim().toLowerCase().replace(/\s+/g, "-");
|
|
143
|
+
|
|
144
|
+
// Map tag types to relationship types
|
|
145
|
+
const typeMap: Record<string, CandidateRelationship["type"]> = {
|
|
146
|
+
SUBSTRATE_ISSUE: "ADDRESSES",
|
|
147
|
+
IMPLEMENTS: "IMPLEMENTS",
|
|
148
|
+
GUIDED_BY: "GUIDED_BY",
|
|
149
|
+
RELATED_TO: "RELATED_TO",
|
|
150
|
+
REQUIRES: "REQUIRES",
|
|
151
|
+
ENABLES: "ENABLES",
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const relType = typeMap[typeStr] || "RELATED_TO";
|
|
155
|
+
|
|
156
|
+
// Try to find matching concept
|
|
157
|
+
const concept = concepts.find(
|
|
158
|
+
(c) =>
|
|
159
|
+
c.id.includes(target) ||
|
|
160
|
+
c.title.toLowerCase().replace(/\s+/g, "-") === target ||
|
|
161
|
+
c.aliases.some((a) => a.toLowerCase().replace(/\s+/g, "-") === target),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (concept) {
|
|
165
|
+
relationships.push({
|
|
166
|
+
type: relType,
|
|
167
|
+
target: concept.id,
|
|
168
|
+
confidence: 1.0, // Explicit tags have high confidence
|
|
169
|
+
source: "explicit_tag",
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
console.warn(
|
|
173
|
+
`⚠️ Tag target not found in lexicon: ${targetStr} (from tag: ${tag})`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return relationships;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function main() {
|
|
182
|
+
console.log("🔄 CDA/CL Transformation Pipeline");
|
|
183
|
+
console.log("═".repeat(60));
|
|
184
|
+
|
|
185
|
+
const root = process.cwd();
|
|
186
|
+
|
|
187
|
+
// Load source files
|
|
188
|
+
console.log("\n📂 Loading source files...");
|
|
189
|
+
const lexiconPath = join(root, settings.paths.sources.persona.lexicon);
|
|
190
|
+
const cdaPath = join(root, settings.paths.sources.persona.cda);
|
|
191
|
+
|
|
192
|
+
const lexiconData = await Bun.file(lexiconPath).json();
|
|
193
|
+
const cdaData = await Bun.file(cdaPath).json();
|
|
194
|
+
|
|
195
|
+
// Transform Lexicon
|
|
196
|
+
console.log("\n🧠 Transforming Lexicon...");
|
|
197
|
+
const lexiconConcepts = (
|
|
198
|
+
Array.isArray(lexiconData) ? lexiconData : lexiconData.concepts
|
|
199
|
+
) as EnrichedLexiconConcept[];
|
|
200
|
+
|
|
201
|
+
const enrichedConcepts: EnrichedLexiconConcept[] = lexiconConcepts.map(
|
|
202
|
+
(c) => ({
|
|
203
|
+
id: c.id,
|
|
204
|
+
type: "concept",
|
|
205
|
+
title: c.title,
|
|
206
|
+
description: c.description || c.title,
|
|
207
|
+
category: c.category || "uncategorized",
|
|
208
|
+
extracted_keywords: extractKeywords(`${c.title} ${c.description || ""}`),
|
|
209
|
+
aliases: c.aliases || [],
|
|
210
|
+
meta: {
|
|
211
|
+
type: c.type,
|
|
212
|
+
},
|
|
213
|
+
}),
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
const enrichedLexicon: EnrichedLexiconDocument = {
|
|
217
|
+
version: "1.0.0",
|
|
218
|
+
generated_at: new Date().toISOString(),
|
|
219
|
+
source_file: lexiconPath,
|
|
220
|
+
concepts: enrichedConcepts,
|
|
221
|
+
stats: {
|
|
222
|
+
total_concepts: enrichedConcepts.length,
|
|
223
|
+
total_keywords_extracted: enrichedConcepts.reduce(
|
|
224
|
+
(sum, c) => sum + c.extracted_keywords.length,
|
|
225
|
+
0,
|
|
226
|
+
),
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
console.log(` ✅ ${enrichedConcepts.length} concepts enriched`);
|
|
231
|
+
console.log(
|
|
232
|
+
` ✅ ${enrichedLexicon.stats.total_keywords_extracted} keywords extracted`,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
// Transform CDA
|
|
236
|
+
console.log("\n📋 Transforming CDA...");
|
|
237
|
+
const cdaEntries: EnrichedCdaEntry[] = [];
|
|
238
|
+
|
|
239
|
+
// Initialize Semantic Matcher (mgrep wrapper)
|
|
240
|
+
const semanticMatcher = new SemanticMatcher();
|
|
241
|
+
console.log(" 🤖 Initialized Semantic Matcher");
|
|
242
|
+
let totalSemanticRels = 0;
|
|
243
|
+
|
|
244
|
+
for (const section of cdaData.directives) {
|
|
245
|
+
for (const entry of section.entries) {
|
|
246
|
+
const keywords = extractKeywords(entry.definition || "");
|
|
247
|
+
const explicitRels = parseExplicitTags(
|
|
248
|
+
entry.tags || [],
|
|
249
|
+
enrichedConcepts,
|
|
250
|
+
);
|
|
251
|
+
const keywordRels = matchKeywordsToConcepts(keywords, enrichedConcepts);
|
|
252
|
+
|
|
253
|
+
// Semantic Search Soft Links
|
|
254
|
+
const semanticRels: CandidateRelationship[] = [];
|
|
255
|
+
|
|
256
|
+
// Only run if we have a meaty definition to search with
|
|
257
|
+
if (entry.definition && entry.definition.length > 15) {
|
|
258
|
+
try {
|
|
259
|
+
// Search known documentation for semantic references
|
|
260
|
+
const docsPath = join(process.cwd(), settings.paths.docs.public);
|
|
261
|
+
|
|
262
|
+
const matches = await semanticMatcher.findCandidates(
|
|
263
|
+
entry.definition,
|
|
264
|
+
docsPath,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
for (const match of matches) {
|
|
268
|
+
// Logic: If mgrep returns a match in the lexicon file,
|
|
269
|
+
// we need to identify WHICH concept that line belongs to.
|
|
270
|
+
// Naive approach: Basic text proximity or line number mapping.
|
|
271
|
+
// Better approach for MVP: Check if the matched content *contains* a concept title.
|
|
272
|
+
|
|
273
|
+
const relatedConcept = enrichedConcepts.find((c) =>
|
|
274
|
+
match.content.toLowerCase().includes(c.title.toLowerCase()),
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
if (relatedConcept) {
|
|
278
|
+
// Avoid dupes from keywords
|
|
279
|
+
if (!keywordRels.some((r) => r.target === relatedConcept.id)) {
|
|
280
|
+
semanticRels.push({
|
|
281
|
+
type: "RELATED_TO",
|
|
282
|
+
target: relatedConcept.id,
|
|
283
|
+
confidence: 0.65, // Lower than keyword, but significant
|
|
284
|
+
source: "semantic_search",
|
|
285
|
+
});
|
|
286
|
+
totalSemanticRels++;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} catch (_e) {
|
|
291
|
+
// Fail silently to normal flow
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const candidateRels = [...explicitRels, ...keywordRels, ...semanticRels];
|
|
296
|
+
|
|
297
|
+
// Auto-validate high-confidence relationships
|
|
298
|
+
const validatedRels = candidateRels
|
|
299
|
+
.filter((rel) => rel.confidence >= 0.75) // High confidence threshold
|
|
300
|
+
.map((rel) => ({
|
|
301
|
+
type: rel.type,
|
|
302
|
+
target: rel.target,
|
|
303
|
+
source: rel.source,
|
|
304
|
+
validated: true,
|
|
305
|
+
validator:
|
|
306
|
+
rel.source === "explicit_tag" ? "auto" : "confidence_threshold",
|
|
307
|
+
validated_at: new Date().toISOString(),
|
|
308
|
+
}));
|
|
309
|
+
|
|
310
|
+
cdaEntries.push({
|
|
311
|
+
id: entry.id,
|
|
312
|
+
type: "directive",
|
|
313
|
+
title: entry.term || entry.id,
|
|
314
|
+
definition: entry.definition || "",
|
|
315
|
+
section: section.section,
|
|
316
|
+
explicit_tags: entry.tags || [],
|
|
317
|
+
extracted_keywords: keywords,
|
|
318
|
+
candidate_relationships: candidateRels,
|
|
319
|
+
validated_relationships: validatedRels,
|
|
320
|
+
meta: {},
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const enrichedCda: EnrichedCdaDocument = {
|
|
326
|
+
version: "1.0.0",
|
|
327
|
+
generated_at: new Date().toISOString(),
|
|
328
|
+
source_files: {
|
|
329
|
+
cda: cdaPath,
|
|
330
|
+
lexicon: lexiconPath,
|
|
331
|
+
},
|
|
332
|
+
entries: cdaEntries,
|
|
333
|
+
stats: {
|
|
334
|
+
total_entries: cdaEntries.length,
|
|
335
|
+
entries_with_tags: cdaEntries.filter((e) => e.explicit_tags.length > 0)
|
|
336
|
+
.length,
|
|
337
|
+
total_explicit_tags: cdaEntries.reduce(
|
|
338
|
+
(sum, e) => sum + e.explicit_tags.length,
|
|
339
|
+
0,
|
|
340
|
+
),
|
|
341
|
+
total_keywords_extracted: cdaEntries.reduce(
|
|
342
|
+
(sum, e) => sum + e.extracted_keywords.length,
|
|
343
|
+
0,
|
|
344
|
+
),
|
|
345
|
+
total_candidate_relationships: cdaEntries.reduce(
|
|
346
|
+
(sum, e) => sum + e.candidate_relationships.length,
|
|
347
|
+
0,
|
|
348
|
+
),
|
|
349
|
+
total_validated_relationships: cdaEntries.reduce(
|
|
350
|
+
(sum, e) => sum + e.validated_relationships.length,
|
|
351
|
+
0,
|
|
352
|
+
),
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
console.log(` ✅ ${cdaEntries.length} directives enriched`);
|
|
357
|
+
console.log(
|
|
358
|
+
` ✅ ${enrichedCda.stats.total_keywords_extracted} keywords extracted`,
|
|
359
|
+
);
|
|
360
|
+
console.log(
|
|
361
|
+
` ✅ ${enrichedCda.stats.total_candidate_relationships} candidate relationships generated`,
|
|
362
|
+
);
|
|
363
|
+
console.log(
|
|
364
|
+
` ✅ ${enrichedCda.stats.total_validated_relationships} relationships validated`,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
console.log(
|
|
368
|
+
` ✅ ${enrichedCda.stats.total_validated_relationships} relationships validated`,
|
|
369
|
+
);
|
|
370
|
+
console.log(
|
|
371
|
+
` ✨ ${totalSemanticRels} SWL (Semantic Soft Links) discovered`,
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// Write output
|
|
375
|
+
console.log("\n💾 Writing enriched artifacts...");
|
|
376
|
+
const outputDir = join(root, ".resonance", "artifacts");
|
|
377
|
+
await Bun.write(
|
|
378
|
+
join(outputDir, "lexicon-enriched.json"),
|
|
379
|
+
JSON.stringify(enrichedLexicon, null, 2),
|
|
380
|
+
);
|
|
381
|
+
await Bun.write(
|
|
382
|
+
join(outputDir, "cda-enriched.json"),
|
|
383
|
+
JSON.stringify(enrichedCda, null, 2),
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
console.log(` ✅ Lexicon: .resonance/artifacts/lexicon-enriched.json`);
|
|
387
|
+
console.log(` ✅ CDA: .resonance/artifacts/cda-enriched.json`);
|
|
388
|
+
|
|
389
|
+
console.log(`\n${"═".repeat(60)}`);
|
|
390
|
+
console.log("✅ Transformation Complete");
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intermediate Structure for Enriched CDA/CL
|
|
3
|
+
*
|
|
4
|
+
* This schema defines the transformation output before database ingestion.
|
|
5
|
+
* Supports both hard links (explicit tags) and soft links (keyword matching).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface CandidateRelationship {
|
|
9
|
+
type:
|
|
10
|
+
| "IMPLEMENTS"
|
|
11
|
+
| "GUIDED_BY"
|
|
12
|
+
| "RELATED_TO"
|
|
13
|
+
| "MENTIONS"
|
|
14
|
+
| "ADDRESSES"
|
|
15
|
+
| "REQUIRES"
|
|
16
|
+
| "ENABLES";
|
|
17
|
+
target: string; // Concept ID (e.g., "term-context-preservation")
|
|
18
|
+
confidence: number; // 0.0 - 1.0
|
|
19
|
+
source:
|
|
20
|
+
| "explicit_tag"
|
|
21
|
+
| "keyword_match"
|
|
22
|
+
| "semantic_similarity"
|
|
23
|
+
| "semantic_search";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ValidatedRelationship {
|
|
27
|
+
type: CandidateRelationship["type"];
|
|
28
|
+
target: string;
|
|
29
|
+
source: CandidateRelationship["source"];
|
|
30
|
+
validated: boolean;
|
|
31
|
+
validator?: string; // Who validated (human or auto)
|
|
32
|
+
validated_at?: string; // ISO timestamp
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface EnrichedCdaEntry {
|
|
36
|
+
id: string;
|
|
37
|
+
type: "directive" | "concept";
|
|
38
|
+
title: string;
|
|
39
|
+
definition: string;
|
|
40
|
+
section?: string; // CDA section (e.g., "PHI: Processing Philosophy")
|
|
41
|
+
|
|
42
|
+
// Original tags from CDA
|
|
43
|
+
explicit_tags: string[];
|
|
44
|
+
|
|
45
|
+
// Extracted during transformation
|
|
46
|
+
extracted_keywords: string[];
|
|
47
|
+
|
|
48
|
+
// Generated candidate relationships
|
|
49
|
+
candidate_relationships: CandidateRelationship[];
|
|
50
|
+
|
|
51
|
+
// Validated relationships (ready for ingestion)
|
|
52
|
+
validated_relationships: ValidatedRelationship[];
|
|
53
|
+
|
|
54
|
+
// Metadata
|
|
55
|
+
meta?: {
|
|
56
|
+
category?: string;
|
|
57
|
+
aliases?: string[];
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface EnrichedCdaDocument {
|
|
63
|
+
version: string;
|
|
64
|
+
generated_at: string;
|
|
65
|
+
source_files: {
|
|
66
|
+
cda: string;
|
|
67
|
+
lexicon: string;
|
|
68
|
+
};
|
|
69
|
+
entries: EnrichedCdaEntry[];
|
|
70
|
+
stats: {
|
|
71
|
+
total_entries: number;
|
|
72
|
+
entries_with_tags: number;
|
|
73
|
+
total_explicit_tags: number;
|
|
74
|
+
total_keywords_extracted: number;
|
|
75
|
+
total_candidate_relationships: number;
|
|
76
|
+
total_validated_relationships: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Enriched Lexicon Concept
|
|
82
|
+
* (Lexicon concepts are simpler, mostly just need keywords)
|
|
83
|
+
*/
|
|
84
|
+
export interface EnrichedLexiconConcept {
|
|
85
|
+
id: string;
|
|
86
|
+
type: "concept";
|
|
87
|
+
title: string;
|
|
88
|
+
description: string;
|
|
89
|
+
category: string;
|
|
90
|
+
|
|
91
|
+
// Extracted keywords for matching
|
|
92
|
+
extracted_keywords: string[];
|
|
93
|
+
|
|
94
|
+
// Aliases for fuzzy matching
|
|
95
|
+
aliases: string[];
|
|
96
|
+
|
|
97
|
+
// Metadata
|
|
98
|
+
meta?: {
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface EnrichedLexiconDocument {
|
|
104
|
+
version: string;
|
|
105
|
+
generated_at: string;
|
|
106
|
+
source_file: string;
|
|
107
|
+
concepts: EnrichedLexiconConcept[];
|
|
108
|
+
stats: {
|
|
109
|
+
total_concepts: number;
|
|
110
|
+
total_keywords_extracted: number;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# PolyVis Services
|
|
2
|
+
|
|
3
|
+
This directory contains the service wrappers for the PolyVis backend infrastructure, including the AI model servers.
|
|
4
|
+
|
|
5
|
+
## Service Lifecycle Management
|
|
6
|
+
|
|
7
|
+
All services in this directory must implement the `ServiceLifecycle` pattern (`src/utils/ServiceLifecycle.ts`). This ensures consistent behavior for:
|
|
8
|
+
- **Startup**: checking for zombie processes, stale PID files, and creating log files.
|
|
9
|
+
- **Process Management**: standard `start`, `stop`, `restart`, `status` commands.
|
|
10
|
+
- **Zombie Defense**: Integration with the `ZombieDefense` system to prevent rogue processes.
|
|
11
|
+
|
|
12
|
+
## Available Services
|
|
13
|
+
|
|
14
|
+
| Service | Script | Port | Description |
|
|
15
|
+
| :--- | :--- | :--- | :--- |
|
|
16
|
+
| **Olmo-3** | `olmo3.ts` | `8084` | The "Auditor" model. Runs with DeepSeek reasoning format for heavy verification tasks. |
|
|
17
|
+
| **Phi-3.5** | `phi.ts` | `8082` | The "Scout" model. Fast, lightweight model for initial queries. |
|
|
18
|
+
| **Llama-3** | `llama.ts` | `8083` | The "Architect" / "Accountant". Steered via Control Vector (Scale: -0.11) for professional, structured output. |
|
|
19
|
+
| **Llama-3-UV** | `llamauv.ts` | `8085` | Unvectored Llama-3. Runs the raw base model for comparison/baseline purposes. |
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
All services can be managed via `bun run`.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Start a service
|
|
27
|
+
bun run <service_name> start
|
|
28
|
+
|
|
29
|
+
# Stop a service
|
|
30
|
+
bun run <service_name> stop
|
|
31
|
+
|
|
32
|
+
# Check status
|
|
33
|
+
bun run <service_name> status
|
|
34
|
+
|
|
35
|
+
# Restart
|
|
36
|
+
bun run <service_name> restart
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Master Status CLI
|
|
40
|
+
|
|
41
|
+
To view the status of ALL running services:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bun run servers
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Adding a New Service
|
|
48
|
+
|
|
49
|
+
1. **Duplicate** an existing wrapper (e.g., `src/services/llamauv.ts`).
|
|
50
|
+
2. **Configure**:
|
|
51
|
+
* Update `PORT`, `name`, `pidFile`, and `logFile`.
|
|
52
|
+
* Set the correct binary path and arguments in `runServer()`.
|
|
53
|
+
3. **Register**:
|
|
54
|
+
* Add a script to `package.json`.
|
|
55
|
+
* Add to the whitelist in `src/utils/ZombieDefense.ts`.
|
|
56
|
+
* Add to the status list in `scripts/cli/servers.ts`.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { ServiceLifecycle } from "../utils/ServiceLifecycle";
|
|
3
|
+
|
|
4
|
+
// --- Configuration ---
|
|
5
|
+
const BASE_DIR = join(import.meta.dir, "../../experiments/enlightenment");
|
|
6
|
+
const BIN_PATH = join(BASE_DIR, "llama.cpp/build/bin/llama-server");
|
|
7
|
+
const MODEL_PATH = join(
|
|
8
|
+
BASE_DIR,
|
|
9
|
+
"vectors/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf",
|
|
10
|
+
);
|
|
11
|
+
const VECTOR_PATH = join(BASE_DIR, "vectors/enlightenment_vector_v2.gguf");
|
|
12
|
+
|
|
13
|
+
const PORT = 8083;
|
|
14
|
+
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const command = args[0] || "serve";
|
|
17
|
+
|
|
18
|
+
// --- Service Lifecycle ---
|
|
19
|
+
|
|
20
|
+
const lifecycle = new ServiceLifecycle({
|
|
21
|
+
name: "Llama-3",
|
|
22
|
+
pidFile: ".llama.pid",
|
|
23
|
+
logFile: ".llama.log",
|
|
24
|
+
entryPoint: "src/services/llama.ts",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// --- Server Logic ---
|
|
28
|
+
|
|
29
|
+
async function runServer() {
|
|
30
|
+
console.log(`🚀 Starting Llama-3 Server on port ${PORT}...`);
|
|
31
|
+
console.log(` 🧠 Applying Control Vector: The Accountant (-0.11)`);
|
|
32
|
+
|
|
33
|
+
const cmd = [
|
|
34
|
+
BIN_PATH,
|
|
35
|
+
"-m",
|
|
36
|
+
MODEL_PATH,
|
|
37
|
+
"--port",
|
|
38
|
+
PORT.toString(),
|
|
39
|
+
"--ctx-size",
|
|
40
|
+
"8192",
|
|
41
|
+
"--n-gpu-layers",
|
|
42
|
+
"99", // Offload to GPU/Metal
|
|
43
|
+
"--control-vector-scaled",
|
|
44
|
+
`${VECTOR_PATH}:-0.11`, // The Accountant (Calibrated: Optimal Strength)
|
|
45
|
+
"--log-disable",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const serverProcess = Bun.spawn(cmd, {
|
|
49
|
+
stdout: "inherit",
|
|
50
|
+
stderr: "inherit",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Wait for process to exit
|
|
54
|
+
await serverProcess.exited;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// --- Dispatch ---
|
|
58
|
+
|
|
59
|
+
await lifecycle.run(command, runServer);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { ServiceLifecycle } from "../utils/ServiceLifecycle";
|
|
3
|
+
|
|
4
|
+
// --- Configuration ---
|
|
5
|
+
const BASE_DIR = join(import.meta.dir, "../../experiments/enlightenment");
|
|
6
|
+
const BIN_PATH = join(BASE_DIR, "llama.cpp/build/bin/llama-server");
|
|
7
|
+
const MODEL_PATH = join(
|
|
8
|
+
BASE_DIR,
|
|
9
|
+
"vectors/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf",
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const PORT = 8085;
|
|
13
|
+
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const command = args[0] || "serve";
|
|
16
|
+
|
|
17
|
+
// --- Service Lifecycle ---
|
|
18
|
+
|
|
19
|
+
const lifecycle = new ServiceLifecycle({
|
|
20
|
+
name: "Llama-3-UV",
|
|
21
|
+
pidFile: ".llamauv.pid",
|
|
22
|
+
logFile: ".llamauv.log",
|
|
23
|
+
entryPoint: "src/services/llamauv.ts",
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// --- Server Logic ---
|
|
27
|
+
|
|
28
|
+
async function runServer() {
|
|
29
|
+
console.log(`🚀 Starting Llama-3-UV (Unvectored) Server on port ${PORT}...`);
|
|
30
|
+
console.log(` 🧠 Mode: RAW (No Control Vector)`);
|
|
31
|
+
|
|
32
|
+
const cmd = [
|
|
33
|
+
BIN_PATH,
|
|
34
|
+
"-m",
|
|
35
|
+
MODEL_PATH,
|
|
36
|
+
"--port",
|
|
37
|
+
PORT.toString(),
|
|
38
|
+
"--ctx-size",
|
|
39
|
+
"8192",
|
|
40
|
+
"--n-gpu-layers",
|
|
41
|
+
"99", // Offload to GPU/Metal
|
|
42
|
+
"--log-disable",
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const serverProcess = Bun.spawn(cmd, {
|
|
46
|
+
stdout: "inherit",
|
|
47
|
+
stderr: "inherit",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Wait for process to exit
|
|
51
|
+
await serverProcess.exited;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// --- Dispatch ---
|
|
55
|
+
|
|
56
|
+
await lifecycle.run(command, runServer);
|