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.
Files changed (139) hide show
  1. package/.biomeignore +19 -0
  2. package/:memory: +0 -0
  3. package/:memory:-shm +0 -0
  4. package/:memory:-wal +0 -0
  5. package/LICENSE +21 -0
  6. package/README.md +343 -13
  7. package/README.old.md +112 -0
  8. package/agents.config.json +11 -0
  9. package/amalfa.config.example.ts +100 -0
  10. package/biome.json +49 -0
  11. package/bun.lock +371 -0
  12. package/docs/AGENT_PROTOCOLS.md +28 -0
  13. package/docs/ARCHITECTURAL_OVERVIEW.md +123 -0
  14. package/docs/BENTO_BOXING_DEPRECATION.md +281 -0
  15. package/docs/Bun-SQLite.html +464 -0
  16. package/docs/COMMIT_GUIDELINES.md +367 -0
  17. package/docs/DEVELOPER_ONBOARDING.md +36 -0
  18. package/docs/Graph and Vector Database Best Practices.md +214 -0
  19. package/docs/PERFORMANCE_BASELINES.md +88 -0
  20. package/docs/REPOSITORY_CLEANUP_SUMMARY.md +261 -0
  21. package/docs/edge-generation-methods.md +57 -0
  22. package/docs/elevator-pitch.md +118 -0
  23. package/docs/graph-and-vector-database-playbook.html +480 -0
  24. package/docs/hardened-sqlite.md +85 -0
  25. package/docs/headless-knowledge-management.md +79 -0
  26. package/docs/john-kaye-flux-prompt.md +46 -0
  27. package/docs/keyboard-shortcuts.md +80 -0
  28. package/docs/opinion-proceed-pattern.md +29 -0
  29. package/docs/polyvis-nodes-edges-schema.md +77 -0
  30. package/docs/protocols/lab-protocol.md +30 -0
  31. package/docs/reaction-iquest-loop-coder.md +46 -0
  32. package/docs/services.md +60 -0
  33. package/docs/sqlite-wal-readonly-trap.md +228 -0
  34. package/docs/strategy/css-architecture.md +40 -0
  35. package/docs/test-document-cycle.md +83 -0
  36. package/docs/test_lifecycle_E2E.md +4 -0
  37. package/docs/the-bicameral-graph.md +83 -0
  38. package/docs/user-guide.md +70 -0
  39. package/docs/vision-helper.md +53 -0
  40. package/drizzle/0000_minor_iron_fist.sql +19 -0
  41. package/drizzle/meta/0000_snapshot.json +139 -0
  42. package/drizzle/meta/_journal.json +13 -0
  43. package/example_usage.ts +39 -0
  44. package/experiment.sh +35 -0
  45. package/hello +2 -0
  46. package/index.html +52 -0
  47. package/knowledge/excalibur.md +12 -0
  48. package/package.json +60 -15
  49. package/plans/experience-graph-integration.md +60 -0
  50. package/prompts/gemini-king-mode-prompt.md +46 -0
  51. package/public/docs/MCP_TOOLS.md +372 -0
  52. package/schemas/README.md +20 -0
  53. package/schemas/cda.schema.json +84 -0
  54. package/schemas/conceptual-lexicon.schema.json +75 -0
  55. package/scratchpads/dummy-debrief-boxed.md +39 -0
  56. package/scratchpads/dummy-debrief.md +27 -0
  57. package/scratchpads/scratchpad-design.md +50 -0
  58. package/scratchpads/scratchpad-scrolling.md +20 -0
  59. package/scratchpads/scratchpad-toc-disappearance.md +23 -0
  60. package/scratchpads/scratchpad-toc.md +28 -0
  61. package/scratchpads/test_gardener.md +7 -0
  62. package/src/EnlightenedTriad.ts +146 -0
  63. package/src/JIT_Triad.ts +137 -0
  64. package/src/cli.ts +318 -0
  65. package/src/config/constants.ts +7 -0
  66. package/src/config/defaults.ts +81 -0
  67. package/src/core/BentoNormalizer.ts +113 -0
  68. package/src/core/EdgeWeaver.ts +145 -0
  69. package/src/core/FractureLogic.ts +22 -0
  70. package/src/core/Harvester.ts +73 -0
  71. package/src/core/LLMClient.ts +93 -0
  72. package/src/core/LouvainGate.ts +67 -0
  73. package/src/core/MarkdownMasker.ts +49 -0
  74. package/src/core/README.md +11 -0
  75. package/src/core/SemanticMatcher.ts +89 -0
  76. package/src/core/SemanticWeaver.ts +96 -0
  77. package/src/core/TagEngine.ts +56 -0
  78. package/src/core/TimelineWeaver.ts +61 -0
  79. package/src/core/VectorEngine.ts +232 -0
  80. package/src/daemon/index.ts +221 -0
  81. package/src/data/experience/test_doc_1.md +2 -0
  82. package/src/data/experience/test_doc_2.md +2 -0
  83. package/src/db/schema.ts +46 -0
  84. package/src/demo-triad.ts +45 -0
  85. package/src/gardeners/AutoTagger.ts +116 -0
  86. package/src/gardeners/BaseGardener.ts +55 -0
  87. package/src/llm/EnlightenedProvider.ts +95 -0
  88. package/src/mcp/README.md +6 -0
  89. package/src/mcp/index.ts +341 -0
  90. package/src/pipeline/AmalfaIngestor.ts +262 -0
  91. package/src/pipeline/HarvesterPipeline.ts +101 -0
  92. package/src/pipeline/Ingestor.ts +555 -0
  93. package/src/pipeline/README.md +7 -0
  94. package/src/pipeline/SemanticHarvester.ts +222 -0
  95. package/src/resonance/DatabaseFactory.ts +100 -0
  96. package/src/resonance/README.md +148 -0
  97. package/src/resonance/cli/README.md +7 -0
  98. package/src/resonance/cli/ingest.ts +41 -0
  99. package/src/resonance/cli/migrate.ts +54 -0
  100. package/src/resonance/config.ts +40 -0
  101. package/src/resonance/daemon.ts +236 -0
  102. package/src/resonance/db.ts +422 -0
  103. package/src/resonance/pipeline/README.md +7 -0
  104. package/src/resonance/pipeline/extract.ts +89 -0
  105. package/src/resonance/pipeline/transform_docs.ts +60 -0
  106. package/src/resonance/schema.ts +138 -0
  107. package/src/resonance/services/embedder.ts +131 -0
  108. package/src/resonance/services/simpleTokenizer.ts +119 -0
  109. package/src/resonance/services/stats.ts +327 -0
  110. package/src/resonance/services/tokenizer.ts +159 -0
  111. package/src/resonance/transform/cda.ts +393 -0
  112. package/src/resonance/types/enriched-cda.ts +112 -0
  113. package/src/services/README.md +56 -0
  114. package/src/services/llama.ts +59 -0
  115. package/src/services/llamauv.ts +56 -0
  116. package/src/services/olmo3.ts +58 -0
  117. package/src/services/phi.ts +52 -0
  118. package/src/types/artifact.ts +12 -0
  119. package/src/utils/EnvironmentVerifier.ts +67 -0
  120. package/src/utils/Logger.ts +21 -0
  121. package/src/utils/ServiceLifecycle.ts +207 -0
  122. package/src/utils/ZombieDefense.ts +244 -0
  123. package/src/utils/validator.ts +264 -0
  124. package/substack/substack-playbook-1.md +95 -0
  125. package/substack/substack-playbook-2.md +78 -0
  126. package/tasks/ui-investigation.md +26 -0
  127. package/test-db +0 -0
  128. package/test-db-shm +0 -0
  129. package/test-db-wal +0 -0
  130. package/tests/canary/verify_pinch_check.ts +44 -0
  131. package/tests/fixtures/ingest_test.md +12 -0
  132. package/tests/fixtures/ingest_test_boxed.md +13 -0
  133. package/tests/fixtures/safety_test.md +45 -0
  134. package/tests/fixtures/safety_test_boxed.md +49 -0
  135. package/tests/fixtures/tagged_output.md +49 -0
  136. package/tests/fixtures/tagged_test.md +49 -0
  137. package/tests/mcp-server-settings.json +8 -0
  138. package/tsconfig.json +46 -0
  139. 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);