@clawdactual/chitin 0.1.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/LICENSE +21 -0
- package/README.md +318 -0
- package/dist/carapace/client.d.ts +41 -0
- package/dist/carapace/client.d.ts.map +1 -0
- package/dist/carapace/client.js +62 -0
- package/dist/carapace/client.js.map +1 -0
- package/dist/carapace/config.d.ts +9 -0
- package/dist/carapace/config.d.ts.map +1 -0
- package/dist/carapace/config.js +24 -0
- package/dist/carapace/config.js.map +1 -0
- package/dist/carapace/index.d.ts +5 -0
- package/dist/carapace/index.d.ts.map +1 -0
- package/dist/carapace/index.js +3 -0
- package/dist/carapace/index.js.map +1 -0
- package/dist/carapace/mapper.d.ts +71 -0
- package/dist/carapace/mapper.d.ts.map +1 -0
- package/dist/carapace/mapper.js +83 -0
- package/dist/carapace/mapper.js.map +1 -0
- package/dist/db/embeddings.d.ts +12 -0
- package/dist/db/embeddings.d.ts.map +1 -0
- package/dist/db/embeddings.js +58 -0
- package/dist/db/embeddings.js.map +1 -0
- package/dist/db/history.d.ts +52 -0
- package/dist/db/history.d.ts.map +1 -0
- package/dist/db/history.js +99 -0
- package/dist/db/history.js.map +1 -0
- package/dist/db/repository.d.ts +64 -0
- package/dist/db/repository.d.ts.map +1 -0
- package/dist/db/repository.js +298 -0
- package/dist/db/repository.js.map +1 -0
- package/dist/db/schema.d.ts +5 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +68 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/engine/conflicts.d.ts +52 -0
- package/dist/engine/conflicts.d.ts.map +1 -0
- package/dist/engine/conflicts.js +232 -0
- package/dist/engine/conflicts.js.map +1 -0
- package/dist/engine/context-detect.d.ts +17 -0
- package/dist/engine/context-detect.d.ts.map +1 -0
- package/dist/engine/context-detect.js +132 -0
- package/dist/engine/context-detect.js.map +1 -0
- package/dist/engine/marshal.d.ts +19 -0
- package/dist/engine/marshal.d.ts.map +1 -0
- package/dist/engine/marshal.js +74 -0
- package/dist/engine/marshal.js.map +1 -0
- package/dist/engine/retrieve.d.ts +36 -0
- package/dist/engine/retrieve.d.ts.map +1 -0
- package/dist/engine/retrieve.js +45 -0
- package/dist/engine/retrieve.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +769 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
- package/seed.json +45 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
let db = null;
|
|
3
|
+
const CREATE_INSIGHTS = `
|
|
4
|
+
CREATE TABLE IF NOT EXISTS insights (
|
|
5
|
+
id TEXT PRIMARY KEY,
|
|
6
|
+
type TEXT NOT NULL CHECK(type IN ('behavioral','personality','relational','principle','skill')),
|
|
7
|
+
claim TEXT NOT NULL,
|
|
8
|
+
reasoning TEXT,
|
|
9
|
+
context TEXT,
|
|
10
|
+
limitations TEXT,
|
|
11
|
+
confidence REAL NOT NULL CHECK(confidence >= 0 AND confidence <= 1),
|
|
12
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
13
|
+
source TEXT,
|
|
14
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
15
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
16
|
+
reinforcement_count INTEGER NOT NULL DEFAULT 0,
|
|
17
|
+
last_retrieved_at TEXT
|
|
18
|
+
);
|
|
19
|
+
`;
|
|
20
|
+
const CREATE_EMBEDDINGS = `
|
|
21
|
+
CREATE TABLE IF NOT EXISTS insight_embeddings (
|
|
22
|
+
insight_id TEXT PRIMARY KEY REFERENCES insights(id) ON DELETE CASCADE,
|
|
23
|
+
embedding BLOB NOT NULL
|
|
24
|
+
);
|
|
25
|
+
`;
|
|
26
|
+
const CREATE_HISTORY = `
|
|
27
|
+
CREATE TABLE IF NOT EXISTS insight_history (
|
|
28
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
|
+
insight_id TEXT NOT NULL REFERENCES insights(id) ON DELETE CASCADE,
|
|
30
|
+
field TEXT NOT NULL,
|
|
31
|
+
old_value TEXT,
|
|
32
|
+
new_value TEXT,
|
|
33
|
+
change_type TEXT NOT NULL CHECK(change_type IN ('create','update','reinforce','merge')),
|
|
34
|
+
changed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
35
|
+
source TEXT
|
|
36
|
+
);
|
|
37
|
+
`;
|
|
38
|
+
const CREATE_HISTORY_INDEX = `
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_history_insight_id ON insight_history(insight_id);
|
|
40
|
+
`;
|
|
41
|
+
export function initDatabase(dbPath) {
|
|
42
|
+
if (db) {
|
|
43
|
+
db.close();
|
|
44
|
+
db = null;
|
|
45
|
+
}
|
|
46
|
+
db = new Database(dbPath);
|
|
47
|
+
// Performance settings
|
|
48
|
+
db.pragma('journal_mode = WAL');
|
|
49
|
+
db.pragma('foreign_keys = ON');
|
|
50
|
+
// Create tables
|
|
51
|
+
db.exec(CREATE_INSIGHTS);
|
|
52
|
+
db.exec(CREATE_EMBEDDINGS);
|
|
53
|
+
db.exec(CREATE_HISTORY);
|
|
54
|
+
db.exec(CREATE_HISTORY_INDEX);
|
|
55
|
+
}
|
|
56
|
+
export function getDatabase() {
|
|
57
|
+
if (!db) {
|
|
58
|
+
throw new Error('Database not initialized. Call initDatabase() first.');
|
|
59
|
+
}
|
|
60
|
+
return db;
|
|
61
|
+
}
|
|
62
|
+
export function closeDatabase() {
|
|
63
|
+
if (db) {
|
|
64
|
+
db.close();
|
|
65
|
+
db = null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,IAAI,EAAE,GAAwB,IAAI,CAAC;AAEnC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;CAgBvB,CAAC;AAEF,MAAM,iBAAiB,GAAG;;;;;CAKzB,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;;;;;;;CAWtB,CAAC;AAEF,MAAM,oBAAoB,GAAG;;CAE5B,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;IAED,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE1B,uBAAuB;IACvB,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,gBAAgB;IAChB,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzB,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3B,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxB,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Insight, ContributeInput } from '../types.js';
|
|
2
|
+
import type { InsightRepository } from '../db/repository.js';
|
|
3
|
+
/**
|
|
4
|
+
* A pair of opposing terms detected between two claims.
|
|
5
|
+
*/
|
|
6
|
+
export type TensionPair = [string, string];
|
|
7
|
+
/**
|
|
8
|
+
* Result of computing semantic tension between two text claims.
|
|
9
|
+
*/
|
|
10
|
+
export interface TensionResult {
|
|
11
|
+
score: number;
|
|
12
|
+
pairs: TensionPair[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A detected conflict between a new insight and an existing one.
|
|
16
|
+
*/
|
|
17
|
+
export interface ConflictResult {
|
|
18
|
+
insight: Insight;
|
|
19
|
+
similarity: number;
|
|
20
|
+
tensionScore: number;
|
|
21
|
+
tensionReason: string;
|
|
22
|
+
conflictScore: number;
|
|
23
|
+
}
|
|
24
|
+
export interface DetectConflictsOptions {
|
|
25
|
+
minConflictScore?: number;
|
|
26
|
+
maxResults?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Compute the semantic tension between two text claims.
|
|
30
|
+
*
|
|
31
|
+
* Scans both claims for opposing term pairs. Each matched pair contributes
|
|
32
|
+
* to the tension score. The score is normalized by the number of pairs checked.
|
|
33
|
+
*
|
|
34
|
+
* This is deliberately simple — keyword matching, no ML. The agent's LLM
|
|
35
|
+
* already understands nuance; this just needs to be "good enough" to flag
|
|
36
|
+
* potential conflicts for review.
|
|
37
|
+
*/
|
|
38
|
+
export declare function computeTensionScore(claimA: string, claimB: string): TensionResult;
|
|
39
|
+
/**
|
|
40
|
+
* Detect conflicts between a proposed new insight and existing insights.
|
|
41
|
+
*
|
|
42
|
+
* Combines word overlap (Jaccard similarity) with semantic tension
|
|
43
|
+
* to identify insights that may contradict the new one.
|
|
44
|
+
*
|
|
45
|
+
* conflictScore = similarity * 0.3 + tensionScore * 0.7
|
|
46
|
+
*
|
|
47
|
+
* Tension is weighted higher because two insights can be about different
|
|
48
|
+
* topics (low similarity) but still contradict each other, and vice versa —
|
|
49
|
+
* similar topics with no tension aren't conflicts.
|
|
50
|
+
*/
|
|
51
|
+
export declare function detectConflicts(repo: InsightRepository, input: ContributeInput, options?: DetectConflictsOptions): ConflictResult[];
|
|
52
|
+
//# sourceMappingURL=conflicts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflicts.d.ts","sourceRoot":"","sources":["../../src/engine/conflicts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAqKD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAkCjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,sBAA2B,GACnC,cAAc,EAAE,CAsClB"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opposing term pairs. If claim A contains a term from column 1
|
|
3
|
+
* and claim B contains the corresponding term from column 2 (or vice versa),
|
|
4
|
+
* that's a tension signal.
|
|
5
|
+
*
|
|
6
|
+
* These are intentionally broad semantic oppositions, not strict antonyms.
|
|
7
|
+
* The goal is "good enough" detection — the agent's LLM handles nuance.
|
|
8
|
+
*/
|
|
9
|
+
const TENSION_PAIRS = [
|
|
10
|
+
// Communication style
|
|
11
|
+
['verbose', 'concise'],
|
|
12
|
+
['verbose', 'brief'],
|
|
13
|
+
['verbose', 'direct'],
|
|
14
|
+
['verbose', 'efficient'],
|
|
15
|
+
['detailed', 'concise'],
|
|
16
|
+
['detailed', 'brief'],
|
|
17
|
+
['detailed', 'direct'],
|
|
18
|
+
['detailed', 'efficient'],
|
|
19
|
+
['thorough', 'concise'],
|
|
20
|
+
['thorough', 'brief'],
|
|
21
|
+
['elaborate', 'concise'],
|
|
22
|
+
['elaborate', 'brief'],
|
|
23
|
+
['lengthy', 'short'],
|
|
24
|
+
['wordy', 'terse'],
|
|
25
|
+
['wordy', 'direct'],
|
|
26
|
+
// Action orientation
|
|
27
|
+
['ask', 'act'],
|
|
28
|
+
['cautious', 'bold'],
|
|
29
|
+
['careful', 'fast'],
|
|
30
|
+
['slow', 'fast'],
|
|
31
|
+
['deliberate', 'quick'],
|
|
32
|
+
['wait', 'proceed'],
|
|
33
|
+
['hesitate', 'decisive'],
|
|
34
|
+
['passive', 'proactive'],
|
|
35
|
+
// Formality
|
|
36
|
+
['formal', 'casual'],
|
|
37
|
+
['formal', 'informal'],
|
|
38
|
+
['professional', 'casual'],
|
|
39
|
+
['polite', 'blunt'],
|
|
40
|
+
['diplomatic', 'direct'],
|
|
41
|
+
// Approach
|
|
42
|
+
['strict', 'flexible'],
|
|
43
|
+
['rigid', 'adaptive'],
|
|
44
|
+
['conservative', 'aggressive'],
|
|
45
|
+
['minimal', 'comprehensive'],
|
|
46
|
+
['simple', 'complex'],
|
|
47
|
+
['silent', 'vocal'],
|
|
48
|
+
['quiet', 'loud'],
|
|
49
|
+
// Knowledge sharing
|
|
50
|
+
['explain', 'execute'],
|
|
51
|
+
['narrate', 'silent'],
|
|
52
|
+
['transparent', 'opaque'],
|
|
53
|
+
// Risk
|
|
54
|
+
['safe', 'risky'],
|
|
55
|
+
['cautious', 'adventurous'],
|
|
56
|
+
['careful', 'reckless'],
|
|
57
|
+
// Independence
|
|
58
|
+
['independent', 'dependent'],
|
|
59
|
+
['autonomous', 'supervised'],
|
|
60
|
+
['initiative', 'permission'],
|
|
61
|
+
];
|
|
62
|
+
/**
|
|
63
|
+
* Very simple suffix stemmer. Strips common English suffixes to normalize
|
|
64
|
+
* word forms: "directness" → "direct", "brevity" → "brief", etc.
|
|
65
|
+
*
|
|
66
|
+
* This isn't Porter stemming — it's deliberately minimal. We only need
|
|
67
|
+
* enough normalization to match our tension pair terms.
|
|
68
|
+
*/
|
|
69
|
+
const STEM_RULES = [
|
|
70
|
+
[/ness$/, ''], // directness → direct, conciseness → concise
|
|
71
|
+
[/ity$/, ''], // brevity → brev (handled by explicit map below)
|
|
72
|
+
[/tion$/, ''], // explanation → explana (not great, but we match on stems)
|
|
73
|
+
[/ment$/, ''], // involvement → involve
|
|
74
|
+
[/ing$/, ''], // asking → ask, acting → act
|
|
75
|
+
[/ly$/, ''], // quickly → quick, formally → formal
|
|
76
|
+
[/ous$/, ''], // cautious → cauti (partial, but helps)
|
|
77
|
+
[/ive$/, ''], // proactive → proact (partial)
|
|
78
|
+
[/ful$/, ''], // careful → care
|
|
79
|
+
[/ed$/, ''], // detailed → detail
|
|
80
|
+
[/er$/, ''], // faster → fast
|
|
81
|
+
[/est$/, ''], // fastest → fast
|
|
82
|
+
[/al$/, ''], // formal → form (too aggressive alone, but we check both)
|
|
83
|
+
[/s$/, ''], // explanations → explanation (then tion rule)
|
|
84
|
+
];
|
|
85
|
+
/**
|
|
86
|
+
* Explicit stem mappings for irregular forms that matter for our tension pairs.
|
|
87
|
+
*/
|
|
88
|
+
const STEM_MAP = {
|
|
89
|
+
'brevity': 'brief',
|
|
90
|
+
'verbosity': 'verbose',
|
|
91
|
+
'cautiously': 'cautious',
|
|
92
|
+
'decisive': 'decisive',
|
|
93
|
+
'indecisive': 'hesitate',
|
|
94
|
+
'efficiency': 'efficient',
|
|
95
|
+
'flexibility': 'flexible',
|
|
96
|
+
'rigidity': 'rigid',
|
|
97
|
+
'formality': 'formal',
|
|
98
|
+
'informality': 'informal',
|
|
99
|
+
'complexity': 'complex',
|
|
100
|
+
'simplicity': 'simple',
|
|
101
|
+
'asking': 'ask',
|
|
102
|
+
'acting': 'act',
|
|
103
|
+
'waiting': 'wait',
|
|
104
|
+
'proceeding': 'proceed',
|
|
105
|
+
};
|
|
106
|
+
function stem(word) {
|
|
107
|
+
if (STEM_MAP[word])
|
|
108
|
+
return STEM_MAP[word];
|
|
109
|
+
let result = word;
|
|
110
|
+
for (const [pattern, replacement] of STEM_RULES) {
|
|
111
|
+
const stemmed = result.replace(pattern, replacement);
|
|
112
|
+
if (stemmed.length >= 3) { // don't over-stem
|
|
113
|
+
result = stemmed;
|
|
114
|
+
break; // apply only the first matching rule
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Tokenize text into a set of lowercase words + their stems,
|
|
121
|
+
* filtering out tiny words.
|
|
122
|
+
*/
|
|
123
|
+
function tokenize(text) {
|
|
124
|
+
const words = text.toLowerCase()
|
|
125
|
+
.split(/\W+/)
|
|
126
|
+
.filter(w => w.length > 2);
|
|
127
|
+
const result = new Set();
|
|
128
|
+
for (const word of words) {
|
|
129
|
+
result.add(word);
|
|
130
|
+
const stemmed = stem(word);
|
|
131
|
+
if (stemmed !== word) {
|
|
132
|
+
result.add(stemmed);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Jaccard similarity between two word sets.
|
|
139
|
+
*/
|
|
140
|
+
function jaccardSimilarity(a, b) {
|
|
141
|
+
if (a.size === 0 && b.size === 0)
|
|
142
|
+
return 0;
|
|
143
|
+
let intersection = 0;
|
|
144
|
+
for (const word of a) {
|
|
145
|
+
if (b.has(word))
|
|
146
|
+
intersection++;
|
|
147
|
+
}
|
|
148
|
+
const union = a.size + b.size - intersection;
|
|
149
|
+
return union === 0 ? 0 : intersection / union;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Compute the semantic tension between two text claims.
|
|
153
|
+
*
|
|
154
|
+
* Scans both claims for opposing term pairs. Each matched pair contributes
|
|
155
|
+
* to the tension score. The score is normalized by the number of pairs checked.
|
|
156
|
+
*
|
|
157
|
+
* This is deliberately simple — keyword matching, no ML. The agent's LLM
|
|
158
|
+
* already understands nuance; this just needs to be "good enough" to flag
|
|
159
|
+
* potential conflicts for review.
|
|
160
|
+
*/
|
|
161
|
+
export function computeTensionScore(claimA, claimB) {
|
|
162
|
+
const wordsA = tokenize(claimA);
|
|
163
|
+
const wordsB = tokenize(claimB);
|
|
164
|
+
const foundPairs = [];
|
|
165
|
+
for (const [term1, term2] of TENSION_PAIRS) {
|
|
166
|
+
// Check both directions: A has term1 & B has term2, or A has term2 & B has term1
|
|
167
|
+
const aHas1 = wordsA.has(term1);
|
|
168
|
+
const aHas2 = wordsA.has(term2);
|
|
169
|
+
const bHas1 = wordsB.has(term1);
|
|
170
|
+
const bHas2 = wordsB.has(term2);
|
|
171
|
+
if ((aHas1 && bHas2) || (aHas2 && bHas1)) {
|
|
172
|
+
// Genuine tension: opposing terms in different claims
|
|
173
|
+
// Skip only if BOTH claims contain BOTH terms — that suggests
|
|
174
|
+
// nuanced discussion rather than contradiction
|
|
175
|
+
if (aHas1 && aHas2 && bHas1 && bHas2)
|
|
176
|
+
continue;
|
|
177
|
+
foundPairs.push([term1, term2]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (foundPairs.length === 0) {
|
|
181
|
+
return { score: 0, pairs: [] };
|
|
182
|
+
}
|
|
183
|
+
// Score: each pair contributes, with diminishing returns
|
|
184
|
+
// 1 pair = 0.4, 2 pairs = 0.6, 3 pairs = 0.73, etc.
|
|
185
|
+
// Formula: 1 - (1 / (1 + 0.4 * count)) — sigmoid-ish curve
|
|
186
|
+
const rawScore = 1 - (1 / (1 + 0.6 * foundPairs.length));
|
|
187
|
+
const score = Math.min(1.0, rawScore);
|
|
188
|
+
return { score, pairs: foundPairs };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Detect conflicts between a proposed new insight and existing insights.
|
|
192
|
+
*
|
|
193
|
+
* Combines word overlap (Jaccard similarity) with semantic tension
|
|
194
|
+
* to identify insights that may contradict the new one.
|
|
195
|
+
*
|
|
196
|
+
* conflictScore = similarity * 0.3 + tensionScore * 0.7
|
|
197
|
+
*
|
|
198
|
+
* Tension is weighted higher because two insights can be about different
|
|
199
|
+
* topics (low similarity) but still contradict each other, and vice versa —
|
|
200
|
+
* similar topics with no tension aren't conflicts.
|
|
201
|
+
*/
|
|
202
|
+
export function detectConflicts(repo, input, options = {}) {
|
|
203
|
+
const { minConflictScore = 0.15, maxResults = 5, } = options;
|
|
204
|
+
const allInsights = repo.list();
|
|
205
|
+
if (allInsights.length === 0)
|
|
206
|
+
return [];
|
|
207
|
+
const inputWords = tokenize(input.claim);
|
|
208
|
+
const results = [];
|
|
209
|
+
for (const insight of allInsights) {
|
|
210
|
+
const insightWords = tokenize(insight.claim);
|
|
211
|
+
const similarity = jaccardSimilarity(inputWords, insightWords);
|
|
212
|
+
const tension = computeTensionScore(input.claim, insight.claim);
|
|
213
|
+
if (tension.score === 0 && similarity < 0.3)
|
|
214
|
+
continue;
|
|
215
|
+
const conflictScore = similarity * 0.3 + tension.score * 0.7;
|
|
216
|
+
if (conflictScore < minConflictScore)
|
|
217
|
+
continue;
|
|
218
|
+
const tensionReason = tension.pairs.length > 0
|
|
219
|
+
? tension.pairs.map(([a, b]) => `"${a}" ↔ "${b}"`).join(', ')
|
|
220
|
+
: 'high word overlap with different emphasis';
|
|
221
|
+
results.push({
|
|
222
|
+
insight,
|
|
223
|
+
similarity,
|
|
224
|
+
tensionScore: tension.score,
|
|
225
|
+
tensionReason,
|
|
226
|
+
conflictScore,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
results.sort((a, b) => b.conflictScore - a.conflictScore);
|
|
230
|
+
return results.slice(0, maxResults);
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=conflicts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflicts.js","sourceRoot":"","sources":["../../src/engine/conflicts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InsightType } from '../types.js';
|
|
2
|
+
export type ContextCategory = 'coding' | 'communication' | 'ethical' | 'creative' | 'general';
|
|
3
|
+
export interface DetectedContext {
|
|
4
|
+
category: ContextCategory;
|
|
5
|
+
typeBoosts: Record<InsightType, number>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Detect the context category of an incoming message/query.
|
|
9
|
+
* Uses keyword matching with weighted scoring to classify the
|
|
10
|
+
* dominant context, then returns appropriate type boost multipliers.
|
|
11
|
+
*
|
|
12
|
+
* This is intentionally simple — keyword-based, no ML.
|
|
13
|
+
* The agent's LLM already understands context deeply;
|
|
14
|
+
* this just needs to be "good enough" for boost selection.
|
|
15
|
+
*/
|
|
16
|
+
export declare function detectContext(text: string): DetectedContext;
|
|
17
|
+
//# sourceMappingURL=context-detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-detect.d.ts","sourceRoot":"","sources":["../../src/engine/context-detect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE9F,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;CACzC;AA2FD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA+C3D"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const SIGNALS = [
|
|
2
|
+
{
|
|
3
|
+
category: 'coding',
|
|
4
|
+
weight: 1.0,
|
|
5
|
+
keywords: [
|
|
6
|
+
'code', 'function', 'bug', 'api', 'build', 'deploy', 'test', 'git',
|
|
7
|
+
'commit', 'push', 'pull', 'branch', 'merge', 'refactor', 'debug',
|
|
8
|
+
'typescript', 'javascript', 'python', 'rust', 'html', 'css',
|
|
9
|
+
'database', 'sql', 'server', 'endpoint', 'cli', 'npm', 'package',
|
|
10
|
+
'compile', 'error', 'fix', 'implement', 'architect', 'repo',
|
|
11
|
+
'docker', 'container', 'netlify', 'website', 'tdd', 'lint',
|
|
12
|
+
'schema', 'migration', 'query', 'install', 'config',
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
category: 'communication',
|
|
17
|
+
weight: 1.0,
|
|
18
|
+
keywords: [
|
|
19
|
+
'boss', 'team', 'respond', 'reply', 'message', 'email', 'slack',
|
|
20
|
+
'tell', 'ask', 'explain', 'communicate', 'feedback', 'meeting',
|
|
21
|
+
'person', 'people', 'coworker', 'colleague', 'client', 'user',
|
|
22
|
+
'conversation', 'discuss', 'chat', 'tone', 'polite', 'direct',
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
category: 'ethical',
|
|
27
|
+
weight: 1.2, // Slightly higher weight — ethical signals should be strong
|
|
28
|
+
keywords: [
|
|
29
|
+
'ethical', 'moral', 'right', 'wrong', 'honest', 'honesty', 'lie',
|
|
30
|
+
'private', 'privacy', 'security', 'trust', 'principle', 'value',
|
|
31
|
+
'should', 'fair', 'integrity', 'permission', 'consent', 'safe',
|
|
32
|
+
'appropriate', 'harmful', 'responsible', 'christian', 'faith',
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
category: 'creative',
|
|
37
|
+
weight: 0.9,
|
|
38
|
+
keywords: [
|
|
39
|
+
'story', 'write', 'creative', 'fun', 'humor', 'joke', 'poem',
|
|
40
|
+
'imagine', 'design', 'art', 'style', 'voice', 'personality',
|
|
41
|
+
'dream', 'philosophical', 'reflect', 'muse', 'inspire',
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
const BOOST_PROFILES = {
|
|
46
|
+
coding: {
|
|
47
|
+
skill: 1.8,
|
|
48
|
+
behavioral: 1.3,
|
|
49
|
+
principle: 1.0,
|
|
50
|
+
personality: 0.7,
|
|
51
|
+
relational: 0.8,
|
|
52
|
+
},
|
|
53
|
+
communication: {
|
|
54
|
+
relational: 1.8,
|
|
55
|
+
behavioral: 1.5,
|
|
56
|
+
personality: 1.2,
|
|
57
|
+
principle: 1.0,
|
|
58
|
+
skill: 0.6,
|
|
59
|
+
},
|
|
60
|
+
ethical: {
|
|
61
|
+
principle: 2.0,
|
|
62
|
+
behavioral: 1.2,
|
|
63
|
+
personality: 1.0,
|
|
64
|
+
relational: 1.0,
|
|
65
|
+
skill: 0.5,
|
|
66
|
+
},
|
|
67
|
+
creative: {
|
|
68
|
+
personality: 1.8,
|
|
69
|
+
behavioral: 1.2,
|
|
70
|
+
relational: 1.0,
|
|
71
|
+
principle: 0.8,
|
|
72
|
+
skill: 0.6,
|
|
73
|
+
},
|
|
74
|
+
general: {
|
|
75
|
+
personality: 1.0,
|
|
76
|
+
behavioral: 1.0,
|
|
77
|
+
relational: 1.0,
|
|
78
|
+
principle: 1.0,
|
|
79
|
+
skill: 1.0,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Detect the context category of an incoming message/query.
|
|
84
|
+
* Uses keyword matching with weighted scoring to classify the
|
|
85
|
+
* dominant context, then returns appropriate type boost multipliers.
|
|
86
|
+
*
|
|
87
|
+
* This is intentionally simple — keyword-based, no ML.
|
|
88
|
+
* The agent's LLM already understands context deeply;
|
|
89
|
+
* this just needs to be "good enough" for boost selection.
|
|
90
|
+
*/
|
|
91
|
+
export function detectContext(text) {
|
|
92
|
+
if (!text || text.trim().length === 0) {
|
|
93
|
+
return { category: 'general', typeBoosts: BOOST_PROFILES.general };
|
|
94
|
+
}
|
|
95
|
+
const lower = text.toLowerCase();
|
|
96
|
+
const words = new Set(lower.split(/\W+/).filter(w => w.length > 0));
|
|
97
|
+
const scores = {
|
|
98
|
+
coding: 0,
|
|
99
|
+
communication: 0,
|
|
100
|
+
ethical: 0,
|
|
101
|
+
creative: 0,
|
|
102
|
+
general: 0,
|
|
103
|
+
};
|
|
104
|
+
for (const signal of SIGNALS) {
|
|
105
|
+
let matches = 0;
|
|
106
|
+
for (const keyword of signal.keywords) {
|
|
107
|
+
// Check both word-level match and substring match for compound words
|
|
108
|
+
if (words.has(keyword) || lower.includes(keyword)) {
|
|
109
|
+
matches++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
scores[signal.category] = matches * signal.weight;
|
|
113
|
+
}
|
|
114
|
+
// Find the category with the highest score
|
|
115
|
+
let bestCategory = 'general';
|
|
116
|
+
let bestScore = 0;
|
|
117
|
+
for (const [category, score] of Object.entries(scores)) {
|
|
118
|
+
if (score > bestScore) {
|
|
119
|
+
bestScore = score;
|
|
120
|
+
bestCategory = category;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Need at least 1 match to classify as non-general
|
|
124
|
+
if (bestScore < 1) {
|
|
125
|
+
bestCategory = 'general';
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
category: bestCategory,
|
|
129
|
+
typeBoosts: BOOST_PROFILES[bestCategory],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=context-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-detect.js","sourceRoot":"","sources":["../../src/engine/context-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ScoredInsight } from './retrieve.js';
|
|
2
|
+
export interface MarshalOptions {
|
|
3
|
+
tokenBudget?: number;
|
|
4
|
+
includeContext?: boolean;
|
|
5
|
+
format?: 'compact' | 'full';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Rough token estimation. ~1 token per 4 characters for English text.
|
|
9
|
+
* Not exact, but sufficient for budgeting.
|
|
10
|
+
*/
|
|
11
|
+
export declare function estimateTokens(text: string): number;
|
|
12
|
+
/**
|
|
13
|
+
* Marshal scored insights into a compact, token-efficient context block
|
|
14
|
+
* suitable for injection into a system prompt.
|
|
15
|
+
*
|
|
16
|
+
* Groups insights by type, uses bullet-point format, respects token budget.
|
|
17
|
+
*/
|
|
18
|
+
export declare function marshal(scored: ScoredInsight[], options?: MarshalOptions): string;
|
|
19
|
+
//# sourceMappingURL=marshal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marshal.d.ts","sourceRoot":"","sources":["../../src/engine/marshal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAC7B;AAaD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CA4DrF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const TYPE_LABELS = {
|
|
2
|
+
behavioral: 'Behavioral',
|
|
3
|
+
personality: 'Personality',
|
|
4
|
+
relational: 'Relational',
|
|
5
|
+
principle: 'Principle',
|
|
6
|
+
skill: 'Skill',
|
|
7
|
+
};
|
|
8
|
+
// Type display order — personality/relational first (identity), then behavioral, principles, skills
|
|
9
|
+
const TYPE_ORDER = ['personality', 'relational', 'behavioral', 'principle', 'skill'];
|
|
10
|
+
/**
|
|
11
|
+
* Rough token estimation. ~1 token per 4 characters for English text.
|
|
12
|
+
* Not exact, but sufficient for budgeting.
|
|
13
|
+
*/
|
|
14
|
+
export function estimateTokens(text) {
|
|
15
|
+
if (!text)
|
|
16
|
+
return 0;
|
|
17
|
+
return Math.ceil(text.length / 4);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Marshal scored insights into a compact, token-efficient context block
|
|
21
|
+
* suitable for injection into a system prompt.
|
|
22
|
+
*
|
|
23
|
+
* Groups insights by type, uses bullet-point format, respects token budget.
|
|
24
|
+
*/
|
|
25
|
+
export function marshal(scored, options = {}) {
|
|
26
|
+
const { tokenBudget = 2000, includeContext = false, format = 'compact', } = options;
|
|
27
|
+
if (scored.length === 0)
|
|
28
|
+
return '';
|
|
29
|
+
// Group by type
|
|
30
|
+
const groups = new Map();
|
|
31
|
+
for (const s of scored) {
|
|
32
|
+
const existing = groups.get(s.insight.type) ?? [];
|
|
33
|
+
existing.push(s);
|
|
34
|
+
groups.set(s.insight.type, existing);
|
|
35
|
+
}
|
|
36
|
+
const lines = [];
|
|
37
|
+
let currentTokens = 0;
|
|
38
|
+
const headerBudget = estimateTokens('## Personality Context\n\n');
|
|
39
|
+
currentTokens += headerBudget;
|
|
40
|
+
// Build sections in display order
|
|
41
|
+
for (const type of TYPE_ORDER) {
|
|
42
|
+
const insights = groups.get(type);
|
|
43
|
+
if (!insights || insights.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
const sectionHeader = `### ${TYPE_LABELS[type]}`;
|
|
46
|
+
const headerTokens = estimateTokens(sectionHeader + '\n');
|
|
47
|
+
if (currentTokens + headerTokens > tokenBudget)
|
|
48
|
+
break;
|
|
49
|
+
lines.push(sectionHeader);
|
|
50
|
+
currentTokens += headerTokens;
|
|
51
|
+
for (const s of insights) {
|
|
52
|
+
let line = `- ${s.insight.claim}`;
|
|
53
|
+
if (includeContext && s.insight.context && format === 'compact') {
|
|
54
|
+
line += ` (${s.insight.context})`;
|
|
55
|
+
}
|
|
56
|
+
if (format === 'full') {
|
|
57
|
+
if (s.insight.context)
|
|
58
|
+
line += `\n Context: ${s.insight.context}`;
|
|
59
|
+
if (s.insight.reasoning)
|
|
60
|
+
line += `\n Reasoning: ${s.insight.reasoning}`;
|
|
61
|
+
if (s.insight.limitations)
|
|
62
|
+
line += `\n Limitations: ${s.insight.limitations}`;
|
|
63
|
+
}
|
|
64
|
+
const lineTokens = estimateTokens(line + '\n');
|
|
65
|
+
if (currentTokens + lineTokens > tokenBudget)
|
|
66
|
+
break;
|
|
67
|
+
lines.push(line);
|
|
68
|
+
currentTokens += lineTokens;
|
|
69
|
+
}
|
|
70
|
+
lines.push(''); // blank line between sections
|
|
71
|
+
}
|
|
72
|
+
return lines.join('\n').trim();
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=marshal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marshal.js","sourceRoot":"","sources":["../../src/engine/marshal.ts"],"names":[],"mappings":"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"}
|