AI Newsletter Digest improvements: fixed QP soft line break decoding, URL extraction, and content cleaning

This commit is contained in:
Krilly
2026-03-04 13:29:22 +00:00
parent 29a98137a7
commit 57dd294675
13706 changed files with 2114953 additions and 237629 deletions
+134
View File
@@ -0,0 +1,134 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const {
PROTOCOL_NAME,
PROTOCOL_VERSION,
VALID_MESSAGE_TYPES,
buildMessage,
buildHello,
buildPublish,
buildFetch,
buildReport,
buildDecision,
buildRevoke,
isValidProtocolMessage,
unwrapAssetFromMessage,
} = require('../src/gep/a2aProtocol');
describe('protocol constants', () => {
it('has expected protocol name', () => {
assert.equal(PROTOCOL_NAME, 'gep-a2a');
});
it('has 6 valid message types', () => {
assert.equal(VALID_MESSAGE_TYPES.length, 6);
for (const t of ['hello', 'publish', 'fetch', 'report', 'decision', 'revoke']) {
assert.ok(VALID_MESSAGE_TYPES.includes(t), `missing type: ${t}`);
}
});
});
describe('buildMessage', () => {
it('builds a valid protocol message', () => {
const msg = buildMessage({ messageType: 'hello', payload: { test: true } });
assert.equal(msg.protocol, PROTOCOL_NAME);
assert.equal(msg.message_type, 'hello');
assert.ok(msg.message_id.startsWith('msg_'));
assert.ok(msg.timestamp);
assert.deepEqual(msg.payload, { test: true });
});
it('rejects invalid message type', () => {
assert.throws(() => buildMessage({ messageType: 'invalid' }), /Invalid message type/);
});
});
describe('typed message builders', () => {
it('buildHello includes env_fingerprint', () => {
const msg = buildHello({});
assert.equal(msg.message_type, 'hello');
assert.ok(msg.payload.env_fingerprint);
});
it('buildPublish requires asset with type and id', () => {
assert.throws(() => buildPublish({}), /asset must have type and id/);
assert.throws(() => buildPublish({ asset: { type: 'Gene' } }), /asset must have type and id/);
const msg = buildPublish({ asset: { type: 'Gene', id: 'g1' } });
assert.equal(msg.message_type, 'publish');
assert.equal(msg.payload.asset_type, 'Gene');
assert.equal(msg.payload.local_id, 'g1');
assert.ok(msg.payload.signature);
});
it('buildFetch creates a fetch message', () => {
const msg = buildFetch({ assetType: 'Capsule', localId: 'c1' });
assert.equal(msg.message_type, 'fetch');
assert.equal(msg.payload.asset_type, 'Capsule');
});
it('buildReport creates a report message', () => {
const msg = buildReport({ assetId: 'sha256:abc', validationReport: { ok: true } });
assert.equal(msg.message_type, 'report');
assert.equal(msg.payload.target_asset_id, 'sha256:abc');
});
it('buildDecision validates decision values', () => {
assert.throws(() => buildDecision({ decision: 'maybe' }), /decision must be/);
for (const d of ['accept', 'reject', 'quarantine']) {
const msg = buildDecision({ decision: d, assetId: 'test' });
assert.equal(msg.payload.decision, d);
}
});
it('buildRevoke creates a revoke message', () => {
const msg = buildRevoke({ assetId: 'sha256:abc', reason: 'outdated' });
assert.equal(msg.message_type, 'revoke');
assert.equal(msg.payload.reason, 'outdated');
});
});
describe('isValidProtocolMessage', () => {
it('returns true for well-formed messages', () => {
const msg = buildHello({});
assert.ok(isValidProtocolMessage(msg));
});
it('returns false for null/undefined', () => {
assert.ok(!isValidProtocolMessage(null));
assert.ok(!isValidProtocolMessage(undefined));
});
it('returns false for wrong protocol', () => {
assert.ok(!isValidProtocolMessage({ protocol: 'other', message_type: 'hello', message_id: 'x', timestamp: 'y' }));
});
it('returns false for missing fields', () => {
assert.ok(!isValidProtocolMessage({ protocol: PROTOCOL_NAME }));
});
});
describe('unwrapAssetFromMessage', () => {
it('extracts asset from publish message', () => {
const asset = { type: 'Gene', id: 'g1', strategy: ['test'] };
const msg = buildPublish({ asset });
const result = unwrapAssetFromMessage(msg);
assert.equal(result.type, 'Gene');
assert.equal(result.id, 'g1');
});
it('returns plain asset objects as-is', () => {
const gene = { type: 'Gene', id: 'g1' };
assert.deepEqual(unwrapAssetFromMessage(gene), gene);
const capsule = { type: 'Capsule', id: 'c1' };
assert.deepEqual(unwrapAssetFromMessage(capsule), capsule);
});
it('returns null for unrecognized input', () => {
assert.equal(unwrapAssetFromMessage(null), null);
assert.equal(unwrapAssetFromMessage({ random: true }), null);
assert.equal(unwrapAssetFromMessage('string'), null);
});
});
+106
View File
@@ -0,0 +1,106 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { canonicalize, computeAssetId, verifyAssetId, SCHEMA_VERSION } = require('../src/gep/contentHash');
describe('canonicalize', () => {
it('serializes null and undefined as "null"', () => {
assert.equal(canonicalize(null), 'null');
assert.equal(canonicalize(undefined), 'null');
});
it('serializes primitives', () => {
assert.equal(canonicalize(true), 'true');
assert.equal(canonicalize(false), 'false');
assert.equal(canonicalize(42), '42');
assert.equal(canonicalize('hello'), '"hello"');
});
it('serializes non-finite numbers as null', () => {
assert.equal(canonicalize(Infinity), 'null');
assert.equal(canonicalize(-Infinity), 'null');
assert.equal(canonicalize(NaN), 'null');
});
it('serializes arrays preserving order', () => {
assert.equal(canonicalize([1, 2, 3]), '[1,2,3]');
assert.equal(canonicalize([]), '[]');
});
it('serializes objects with sorted keys', () => {
assert.equal(canonicalize({ b: 2, a: 1 }), '{"a":1,"b":2}');
assert.equal(canonicalize({ z: 'last', a: 'first' }), '{"a":"first","z":"last"}');
});
it('produces deterministic output regardless of key insertion order', () => {
const obj1 = { c: 3, a: 1, b: 2 };
const obj2 = { a: 1, b: 2, c: 3 };
assert.equal(canonicalize(obj1), canonicalize(obj2));
});
it('handles nested objects and arrays', () => {
const nested = { arr: [{ b: 2, a: 1 }], val: null };
const result = canonicalize(nested);
assert.equal(result, '{"arr":[{"a":1,"b":2}],"val":null}');
});
});
describe('computeAssetId', () => {
it('returns a sha256-prefixed hash string', () => {
const id = computeAssetId({ type: 'Gene', id: 'test_gene' });
assert.ok(id.startsWith('sha256:'));
assert.equal(id.length, 7 + 64); // "sha256:" + 64 hex chars
});
it('excludes asset_id field from hash by default', () => {
const obj = { type: 'Gene', id: 'g1', data: 'x' };
const withoutField = computeAssetId(obj);
const withField = computeAssetId({ ...obj, asset_id: 'sha256:something' });
assert.equal(withoutField, withField);
});
it('produces identical hashes for identical content', () => {
const a = computeAssetId({ type: 'Capsule', id: 'c1', value: 42 });
const b = computeAssetId({ type: 'Capsule', id: 'c1', value: 42 });
assert.equal(a, b);
});
it('produces different hashes for different content', () => {
const a = computeAssetId({ type: 'Gene', id: 'g1' });
const b = computeAssetId({ type: 'Gene', id: 'g2' });
assert.notEqual(a, b);
});
it('returns null for non-object input', () => {
assert.equal(computeAssetId(null), null);
assert.equal(computeAssetId('string'), null);
});
});
describe('verifyAssetId', () => {
it('returns true for correct asset_id', () => {
const obj = { type: 'Gene', id: 'g1', data: 'test' };
obj.asset_id = computeAssetId(obj);
assert.ok(verifyAssetId(obj));
});
it('returns false for tampered content', () => {
const obj = { type: 'Gene', id: 'g1', data: 'test' };
obj.asset_id = computeAssetId(obj);
obj.data = 'tampered';
assert.ok(!verifyAssetId(obj));
});
it('returns false for missing asset_id', () => {
assert.ok(!verifyAssetId({ type: 'Gene', id: 'g1' }));
});
it('returns false for null input', () => {
assert.ok(!verifyAssetId(null));
});
});
describe('SCHEMA_VERSION', () => {
it('is a semver string', () => {
assert.match(SCHEMA_VERSION, /^\d+\.\d+\.\d+$/);
});
});
@@ -0,0 +1,89 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { captureEnvFingerprint, envFingerprintKey, isSameEnvClass } = require('../src/gep/envFingerprint');
describe('captureEnvFingerprint', function () {
it('returns an object with expected fields', function () {
const fp = captureEnvFingerprint();
assert.equal(typeof fp, 'object');
assert.equal(typeof fp.device_id, 'string');
assert.equal(typeof fp.node_version, 'string');
assert.equal(typeof fp.platform, 'string');
assert.equal(typeof fp.arch, 'string');
assert.equal(typeof fp.os_release, 'string');
assert.equal(typeof fp.hostname, 'string');
assert.equal(typeof fp.container, 'boolean');
assert.equal(typeof fp.cwd, 'string');
});
it('hashes hostname to 12 chars', function () {
const fp = captureEnvFingerprint();
assert.equal(fp.hostname.length, 12);
});
it('hashes cwd to 12 chars', function () {
const fp = captureEnvFingerprint();
assert.equal(fp.cwd.length, 12);
});
it('node_version starts with v', function () {
const fp = captureEnvFingerprint();
assert.ok(fp.node_version.startsWith('v'));
});
it('returns consistent results across calls', function () {
const fp1 = captureEnvFingerprint();
const fp2 = captureEnvFingerprint();
assert.equal(fp1.device_id, fp2.device_id);
assert.equal(fp1.platform, fp2.platform);
assert.equal(fp1.hostname, fp2.hostname);
});
});
describe('envFingerprintKey', function () {
it('returns a 16-char hex string', function () {
const fp = captureEnvFingerprint();
const key = envFingerprintKey(fp);
assert.equal(typeof key, 'string');
assert.equal(key.length, 16);
assert.match(key, /^[0-9a-f]{16}$/);
});
it('returns unknown for null input', function () {
assert.equal(envFingerprintKey(null), 'unknown');
});
it('returns unknown for non-object input', function () {
assert.equal(envFingerprintKey('string'), 'unknown');
});
it('same fingerprint produces same key', function () {
const fp = captureEnvFingerprint();
assert.equal(envFingerprintKey(fp), envFingerprintKey(fp));
});
it('different fingerprints produce different keys', function () {
const fp1 = captureEnvFingerprint();
const fp2 = { ...fp1, device_id: 'different_device' };
assert.notEqual(envFingerprintKey(fp1), envFingerprintKey(fp2));
});
});
describe('isSameEnvClass', function () {
it('returns true for identical fingerprints', function () {
const fp = captureEnvFingerprint();
assert.equal(isSameEnvClass(fp, fp), true);
});
it('returns true for fingerprints with same key fields', function () {
const fp1 = captureEnvFingerprint();
const fp2 = { ...fp1, cwd: 'different_cwd' };
assert.equal(isSameEnvClass(fp1, fp2), true);
});
it('returns false for different environments', function () {
const fp1 = captureEnvFingerprint();
const fp2 = { ...fp1, device_id: 'other_device' };
assert.equal(isSameEnvClass(fp1, fp2), false);
});
});
+142
View File
@@ -0,0 +1,142 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const {
buildMutation,
isValidMutation,
normalizeMutation,
isHighRiskMutationAllowed,
isHighRiskPersonality,
clamp01,
} = require('../src/gep/mutation');
describe('clamp01', () => {
it('clamps values to [0, 1]', () => {
assert.equal(clamp01(0.5), 0.5);
assert.equal(clamp01(0), 0);
assert.equal(clamp01(1), 1);
assert.equal(clamp01(-0.5), 0);
assert.equal(clamp01(1.5), 1);
});
it('returns 0 for non-finite input', () => {
assert.equal(clamp01(NaN), 0);
assert.equal(clamp01(undefined), 0);
// Note: clamp01(Infinity) returns 0 because the implementation checks
// Number.isFinite() before clamping. Mathematically clamp(Inf, 0, 1) = 1,
// but the current behavior treats all non-finite values uniformly as 0.
assert.equal(clamp01(Infinity), 0);
});
});
describe('buildMutation', () => {
it('returns a valid Mutation object', () => {
const m = buildMutation({ signals: ['log_error'], selectedGene: { id: 'gene_repair' } });
assert.ok(isValidMutation(m));
assert.equal(m.type, 'Mutation');
assert.ok(m.id.startsWith('mut_'));
});
it('selects repair category when error signals present', () => {
const m = buildMutation({ signals: ['log_error', 'errsig:something'] });
assert.equal(m.category, 'repair');
});
it('selects innovate category when drift enabled', () => {
const m = buildMutation({ signals: ['stable_success_plateau'], driftEnabled: true });
assert.equal(m.category, 'innovate');
});
it('selects innovate for opportunity signals without errors', () => {
const m = buildMutation({ signals: ['user_feature_request'] });
assert.equal(m.category, 'innovate');
});
it('downgrades innovate to optimize for high-risk personality', () => {
const highRiskPersonality = { rigor: 0.3, risk_tolerance: 0.8, creativity: 0.5 };
const m = buildMutation({
signals: ['user_feature_request'],
personalityState: highRiskPersonality,
});
assert.equal(m.category, 'optimize');
assert.ok(m.trigger_signals.some(s => s.includes('safety')));
});
it('caps risk_level to medium when personality disallows high risk', () => {
const conservativePersonality = { rigor: 0.5, risk_tolerance: 0.6, creativity: 0.5 };
const m = buildMutation({
signals: ['stable_success_plateau'],
driftEnabled: true,
allowHighRisk: true,
personalityState: conservativePersonality,
});
assert.notEqual(m.risk_level, 'high');
});
});
describe('isValidMutation', () => {
it('returns true for valid mutation', () => {
const m = buildMutation({ signals: ['log_error'] });
assert.ok(isValidMutation(m));
});
it('returns false for missing fields', () => {
assert.ok(!isValidMutation(null));
assert.ok(!isValidMutation({}));
assert.ok(!isValidMutation({ type: 'Mutation' }));
});
it('returns false for invalid category', () => {
assert.ok(!isValidMutation({
type: 'Mutation', id: 'x', category: 'destroy',
trigger_signals: [], target: 't', expected_effect: 'e', risk_level: 'low',
}));
});
});
describe('normalizeMutation', () => {
it('fills defaults for empty object', () => {
const m = normalizeMutation({});
assert.ok(isValidMutation(m));
assert.equal(m.category, 'optimize');
assert.equal(m.risk_level, 'low');
});
it('preserves valid fields', () => {
const m = normalizeMutation({
id: 'mut_custom', category: 'repair',
trigger_signals: ['log_error'], target: 'file.js',
expected_effect: 'fix bug', risk_level: 'medium',
});
assert.equal(m.id, 'mut_custom');
assert.equal(m.category, 'repair');
assert.equal(m.risk_level, 'medium');
});
});
describe('isHighRiskPersonality', () => {
it('detects low rigor as high risk', () => {
assert.ok(isHighRiskPersonality({ rigor: 0.3 }));
});
it('detects high risk_tolerance as high risk', () => {
assert.ok(isHighRiskPersonality({ risk_tolerance: 0.7 }));
});
it('returns false for conservative personality', () => {
assert.ok(!isHighRiskPersonality({ rigor: 0.8, risk_tolerance: 0.2 }));
});
});
describe('isHighRiskMutationAllowed', () => {
it('allows when rigor >= 0.6 and risk_tolerance <= 0.5', () => {
assert.ok(isHighRiskMutationAllowed({ rigor: 0.8, risk_tolerance: 0.3 }));
});
it('disallows when rigor too low', () => {
assert.ok(!isHighRiskMutationAllowed({ rigor: 0.4, risk_tolerance: 0.3 }));
});
it('disallows when risk_tolerance too high', () => {
assert.ok(!isHighRiskMutationAllowed({ rigor: 0.8, risk_tolerance: 0.6 }));
});
});
+90
View File
@@ -0,0 +1,90 @@
const assert = require('assert');
const { sanitizePayload, redactString } = require('../src/gep/sanitize');
const REDACTED = '[REDACTED]';
// --- redactString ---
// Existing patterns (regression)
assert.strictEqual(redactString('Bearer abc123def456ghi789jkl0'), REDACTED);
assert.strictEqual(redactString('sk-abcdefghijklmnopqrstuvwxyz'), REDACTED);
assert.strictEqual(redactString('token=abcdefghijklmnop1234'), REDACTED);
assert.strictEqual(redactString('api_key=abcdefghijklmnop1234'), REDACTED);
assert.strictEqual(redactString('secret: abcdefghijklmnop1234'), REDACTED);
assert.strictEqual(redactString('/home/user/secret/file.txt'), REDACTED);
assert.strictEqual(redactString('/Users/admin/docs'), REDACTED);
assert.strictEqual(redactString('user@example.com'), REDACTED);
// GitHub tokens (bare, without token= prefix)
assert.ok(redactString('ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1234').includes(REDACTED),
'bare ghp_ token should be redacted');
assert.ok(redactString('gho_abcdefghijklmnopqrstuvwxyz1234567890').includes(REDACTED),
'bare gho_ token should be redacted');
assert.ok(redactString('github_pat_abcdefghijklmnopqrstuvwxyz123456').includes(REDACTED),
'github_pat_ token should be redacted');
assert.ok(redactString('use ghs_abcdefghijklmnopqrstuvwxyz1234567890 for auth').includes(REDACTED),
'ghs_ in sentence should be redacted');
// AWS keys
assert.ok(redactString('AKIAIOSFODNN7EXAMPLE').includes(REDACTED),
'AWS access key should be redacted');
// OpenAI project tokens
assert.ok(redactString('sk-proj-bxOCXoWsaPj0IDE1yqlXCXIkWO1f').includes(REDACTED),
'sk-proj- token should be redacted');
// Anthropic tokens
assert.ok(redactString('sk-ant-api03-abcdefghijklmnopqrst').includes(REDACTED),
'sk-ant- token should be redacted');
// npm tokens
assert.ok(redactString('npm_abcdefghijklmnopqrstuvwxyz1234567890').includes(REDACTED),
'npm token should be redacted');
// Private keys
assert.ok(redactString('-----BEGIN RSA PRIVATE KEY-----\nabc\n-----END RSA PRIVATE KEY-----').includes(REDACTED),
'RSA private key should be redacted');
assert.ok(redactString('-----BEGIN PRIVATE KEY-----\ndata\n-----END PRIVATE KEY-----').includes(REDACTED),
'generic private key should be redacted');
// Password fields
assert.ok(redactString('password=mysecretpassword123').includes(REDACTED),
'password= should be redacted');
assert.ok(redactString('PASSWORD: "hunter2xyz"').includes(REDACTED),
'PASSWORD: should be redacted');
// Basic auth in URLs (should preserve scheme and @)
var urlResult = redactString('https://user:pass123@github.com/repo');
assert.ok(urlResult.includes(REDACTED), 'basic auth in URL should be redacted');
assert.ok(urlResult.startsWith('https://'), 'URL scheme should be preserved');
assert.ok(urlResult.includes('@github.com'), '@ and host should be preserved');
// Safe strings should NOT be redacted
assert.strictEqual(redactString('hello world'), 'hello world');
assert.strictEqual(redactString('error: something failed'), 'error: something failed');
assert.strictEqual(redactString('fix the bug in parser'), 'fix the bug in parser');
// --- sanitizePayload ---
// Deep sanitization
var payload = {
summary: 'Fixed auth using ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5678',
nested: {
path: '/home/user/.ssh/id_rsa',
email: 'admin@internal.corp',
safe: 'this is fine',
},
};
var sanitized = sanitizePayload(payload);
assert.ok(sanitized.summary.includes(REDACTED), 'ghp token in summary');
assert.ok(sanitized.nested.path.includes(REDACTED), 'path in nested');
assert.ok(sanitized.nested.email.includes(REDACTED), 'email in nested');
assert.strictEqual(sanitized.nested.safe, 'this is fine');
// Null/undefined/number inputs
assert.strictEqual(sanitizePayload(null), null);
assert.strictEqual(sanitizePayload(undefined), undefined);
assert.strictEqual(redactString(null), null);
assert.strictEqual(redactString(123), 123);
console.log('All sanitize tests passed (34 assertions)');
+124
View File
@@ -0,0 +1,124 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { selectGene, selectCapsule, selectGeneAndCapsule } = require('../src/gep/selector');
const GENES = [
{
type: 'Gene',
id: 'gene_repair',
category: 'repair',
signals_match: ['error', 'exception', 'failed'],
strategy: ['fix it'],
validation: ['node -e "true"'],
},
{
type: 'Gene',
id: 'gene_optimize',
category: 'optimize',
signals_match: ['protocol', 'prompt', 'audit'],
strategy: ['optimize it'],
validation: ['node -e "true"'],
},
{
type: 'Gene',
id: 'gene_innovate',
category: 'innovate',
signals_match: ['user_feature_request', 'user_improvement_suggestion', 'capability_gap', 'stable_success_plateau'],
strategy: ['build it'],
validation: ['node -e "true"'],
},
];
const CAPSULES = [
{
type: 'Capsule',
id: 'capsule_1',
trigger: ['log_error', 'exception'],
gene: 'gene_repair',
summary: 'Fixed an error',
confidence: 0.9,
},
{
type: 'Capsule',
id: 'capsule_2',
trigger: ['protocol', 'gep'],
gene: 'gene_optimize',
summary: 'Optimized prompt',
confidence: 0.85,
},
];
describe('selectGene', () => {
it('selects the gene with highest signal match', () => {
const result = selectGene(GENES, ['error', 'exception', 'failed'], {});
assert.equal(result.selected.id, 'gene_repair');
});
it('returns null when no signals match', () => {
const result = selectGene(GENES, ['completely_unrelated_signal'], {});
assert.equal(result.selected, null);
});
it('returns alternatives when multiple genes match', () => {
const result = selectGene(GENES, ['error', 'protocol'], {});
assert.ok(result.selected);
assert.ok(Array.isArray(result.alternatives));
});
it('includes drift intensity in result', () => {
// Drift intensity is population-size-dependent; verify it is returned.
const result = selectGene(GENES, ['error', 'exception'], {});
assert.ok('driftIntensity' in result);
assert.equal(typeof result.driftIntensity, 'number');
assert.ok(result.driftIntensity >= 0 && result.driftIntensity <= 1);
});
it('respects preferred gene id from memory graph', () => {
const result = selectGene(GENES, ['error', 'protocol'], {
preferredGeneId: 'gene_optimize',
});
// gene_optimize matches 'protocol' so it qualifies as a candidate
// With preference, it should be selected even if gene_repair scores higher
assert.equal(result.selected.id, 'gene_optimize');
});
it('matches gene via baseName:snippet signal (user_feature_request:snippet)', () => {
const result = selectGene(GENES, ['user_feature_request:add a dark mode toggle to the settings'], {});
assert.ok(result.selected);
assert.equal(result.selected.id, 'gene_innovate', 'innovate gene has signals_match user_feature_request');
});
it('matches gene via baseName:snippet signal (user_improvement_suggestion:snippet)', () => {
const result = selectGene(GENES, ['user_improvement_suggestion:refactor the payment module and simplify the API'], {});
assert.ok(result.selected);
assert.equal(result.selected.id, 'gene_innovate', 'innovate gene has signals_match user_improvement_suggestion');
});
});
describe('selectCapsule', () => {
it('selects capsule matching signals', () => {
const result = selectCapsule(CAPSULES, ['log_error', 'exception']);
assert.equal(result.id, 'capsule_1');
});
it('returns null when no triggers match', () => {
const result = selectCapsule(CAPSULES, ['unrelated']);
assert.equal(result, null);
});
});
describe('selectGeneAndCapsule', () => {
it('returns selected gene, capsule candidates, and selector decision', () => {
const result = selectGeneAndCapsule({
genes: GENES,
capsules: CAPSULES,
signals: ['error', 'log_error'],
memoryAdvice: null,
driftEnabled: false,
});
assert.ok(result.selectedGene);
assert.ok(result.selector);
assert.ok(result.selector.selected);
assert.ok(Array.isArray(result.selector.reason));
});
});
+217
View File
@@ -0,0 +1,217 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { extractSignals } = require('../src/gep/signals');
const emptyInput = {
recentSessionTranscript: '',
todayLog: '',
memorySnippet: '',
userSnippet: '',
recentEvents: [],
};
function hasSignal(signals, name) {
return Array.isArray(signals) && signals.some(s => String(s).startsWith(name));
}
function getSignalExtra(signals, name) {
const s = Array.isArray(signals) ? signals.find(x => String(x).startsWith(name + ':')) : undefined;
if (!s) return undefined;
const i = String(s).indexOf(':');
return i === -1 ? '' : String(s).slice(i + 1).trim();
}
describe('extractSignals -- user_feature_request (4 languages)', () => {
it('recognizes English feature request', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'Please add a dark mode toggle to the settings page.',
});
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request in ' + JSON.stringify(r));
});
it('recognizes Simplified Chinese feature request', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '加个支付模块,要支持微信和支付宝。',
});
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request in ' + JSON.stringify(r));
});
it('recognizes Traditional Chinese feature request', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '請加一個匯出報表的功能,要支援 PDF。',
});
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request in ' + JSON.stringify(r));
});
it('recognizes Japanese feature request', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'ダークモードのトグルを追加してほしいです。',
});
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request in ' + JSON.stringify(r));
});
it('user_feature_request signal carries snippet', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'Please add a dark mode toggle to the settings page.',
});
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined, 'expected user_feature_request:extra form');
assert.ok(extra.length > 0, 'extra should not be empty');
assert.ok(extra.toLowerCase().includes('dark') || extra.includes('toggle') || extra.includes('add'), 'extra should reflect request content');
});
});
describe('extractSignals -- user_improvement_suggestion (4 languages)', () => {
it('recognizes English improvement suggestion', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'The UI could be better; we should simplify the onboarding flow.',
});
assert.ok(hasSignal(r, 'user_improvement_suggestion'), 'expected user_improvement_suggestion in ' + JSON.stringify(r));
});
it('recognizes Simplified Chinese improvement suggestion', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '改进一下登录流程,优化一下性能。',
});
assert.ok(hasSignal(r, 'user_improvement_suggestion'), 'expected user_improvement_suggestion in ' + JSON.stringify(r));
});
it('recognizes Traditional Chinese improvement suggestion', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '建議改進匯出速度,優化一下介面。',
});
assert.ok(hasSignal(r, 'user_improvement_suggestion'), 'expected user_improvement_suggestion in ' + JSON.stringify(r));
});
it('recognizes Japanese improvement suggestion', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'ログインの流れを改善してほしい。',
});
assert.ok(hasSignal(r, 'user_improvement_suggestion'), 'expected user_improvement_suggestion in ' + JSON.stringify(r));
});
it('user_improvement_suggestion signal carries snippet', () => {
const r = extractSignals({
...emptyInput,
userSnippet: 'We should refactor the payment module and simplify the API.',
});
const extra = getSignalExtra(r, 'user_improvement_suggestion');
assert.ok(extra !== undefined, 'expected user_improvement_suggestion:extra form');
assert.ok(extra.length > 0, 'extra should not be empty');
});
});
describe('extractSignals -- edge cases (snippet length, empty, punctuation)', () => {
it('long snippet truncated to 200 chars', () => {
const long = '我想让系统支持批量导入用户、导出报表、自定义工作流、多语言切换、主题切换、权限组、审计日志、Webhook 通知、API 限流、缓存策略配置、数据库备份恢复、灰度发布、A/B 测试、埋点统计、性能监控、告警规则、工单流转、知识库搜索、智能推荐、以及一大堆其他功能以便我们能够更好地管理业务。';
const r = extractSignals({ ...emptyInput, userSnippet: long });
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request');
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined && extra.length > 0, 'extra should be present');
assert.ok(extra.length <= 200, 'snippet must be truncated to 200 chars, got ' + extra.length);
});
it('short snippet works', () => {
const r = extractSignals({ ...emptyInput, userSnippet: '我想加一个导出 Excel 的功能。' });
assert.ok(hasSignal(r, 'user_feature_request'));
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined && extra.length > 0);
});
it('bare "我想。" still triggers', () => {
const r = extractSignals({ ...emptyInput, userSnippet: '我想。' });
assert.ok(hasSignal(r, 'user_feature_request'), 'expected user_feature_request for 我想。');
});
it('bare "我想" without punctuation still triggers', () => {
const r = extractSignals({ ...emptyInput, userSnippet: '我想' });
assert.ok(hasSignal(r, 'user_feature_request'));
});
it('empty userSnippet does not produce feature/improvement', () => {
const r = extractSignals({ ...emptyInput, userSnippet: '' });
const hasFeat = hasSignal(r, 'user_feature_request');
const hasImp = hasSignal(r, 'user_improvement_suggestion');
assert.ok(!hasFeat && !hasImp, 'empty userSnippet should not yield feature/improvement from user input');
});
it('whitespace/punctuation only does not match', () => {
const r = extractSignals({ ...emptyInput, userSnippet: ' \n\t 。,、 \n' });
assert.ok(!hasSignal(r, 'user_feature_request'), 'whitespace/punctuation only should not match');
assert.ok(!hasSignal(r, 'user_improvement_suggestion'));
});
it('English "I want" long snippet truncated', () => {
const long = 'I want to add a feature that allows users to export data in CSV and Excel formats, with custom column mapping, date range filters, scheduled exports, email delivery, and integration with our analytics pipeline so that we can reduce manual reporting work. This is critical for Q2.';
const r = extractSignals({ ...emptyInput, userSnippet: long });
assert.ok(hasSignal(r, 'user_feature_request'));
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra === undefined || extra.length <= 200, 'snippet if present should be <= 200');
});
it('improvement snippet truncated to 200', () => {
const long = '改进一下登录流程:首先支持扫码登录、然后记住设备、然后支持多因素认证、然后审计日志、然后限流防刷、然后国际化提示、然后无障碍优化、然后性能优化、然后安全加固、然后文档补全。';
const r = extractSignals({ ...emptyInput, userSnippet: long });
assert.ok(hasSignal(r, 'user_improvement_suggestion'));
const extra = getSignalExtra(r, 'user_improvement_suggestion');
assert.ok(extra !== undefined && extra.length > 0);
assert.ok(extra.length <= 200, 'improvement snippet <= 200, got ' + extra.length);
});
it('mixed sentences: feature request detected with snippet', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '加个支付模块,要支持微信和支付宝。另外昨天那个 bug 修了吗?',
});
assert.ok(hasSignal(r, 'user_feature_request'));
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined && extra.length > 0);
});
it('newlines and tabs in text: regex matches and normalizes', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '我想\n加一个\t导出\n报表的功能。',
});
assert.ok(hasSignal(r, 'user_feature_request'));
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined);
assert.ok(!/\n/.test(extra) || extra.length <= 200, 'snippet should be normalized');
});
it('"我想" in middle of paragraph still triggers', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '前面是一些背景说明。我想加一个暗色模式开关,方便夜间使用。',
});
assert.ok(hasSignal(r, 'user_feature_request'));
const extra = getSignalExtra(r, 'user_feature_request');
assert.ok(extra !== undefined && extra.length > 0);
});
it('pure punctuation does not trigger', () => {
const r = extractSignals({ ...emptyInput, userSnippet: '。。。。' });
assert.ok(!hasSignal(r, 'user_feature_request'));
assert.ok(!hasSignal(r, 'user_improvement_suggestion'));
});
it('both feature_request and improvement_suggestion carry snippets', () => {
const r = extractSignals({
...emptyInput,
userSnippet: '加个支付模块。另外改进一下登录流程,简化步骤。',
});
assert.ok(hasSignal(r, 'user_feature_request'));
assert.ok(hasSignal(r, 'user_improvement_suggestion'));
assert.ok(getSignalExtra(r, 'user_feature_request'));
assert.ok(getSignalExtra(r, 'user_improvement_suggestion'));
});
});
+486
View File
@@ -0,0 +1,486 @@
const { describe, it, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const os = require('os');
const {
collectDistillationData,
analyzePatterns,
validateSynthesizedGene,
buildDistillationPrompt,
extractJsonFromLlmResponse,
computeDataHash,
shouldDistill,
prepareDistillation,
completeDistillation,
distillRequestPath,
readDistillerState,
writeDistillerState,
DISTILLED_ID_PREFIX,
DISTILLED_MAX_FILES,
} = require('../src/gep/skillDistiller');
// Create an isolated temp directory for each test to avoid polluting real assets.
let tmpDir;
let origGepAssetsDir;
let origEvolutionDir;
let origMemoryDir;
let origSkillDistiller;
function setupTempEnv() {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'distiller-test-'));
origGepAssetsDir = process.env.GEP_ASSETS_DIR;
origEvolutionDir = process.env.EVOLUTION_DIR;
origMemoryDir = process.env.MEMORY_DIR;
origSkillDistiller = process.env.SKILL_DISTILLER;
process.env.GEP_ASSETS_DIR = path.join(tmpDir, 'assets');
process.env.EVOLUTION_DIR = path.join(tmpDir, 'evolution');
process.env.MEMORY_DIR = path.join(tmpDir, 'memory');
process.env.MEMORY_GRAPH_PATH = path.join(tmpDir, 'evolution', 'memory_graph.jsonl');
fs.mkdirSync(process.env.GEP_ASSETS_DIR, { recursive: true });
fs.mkdirSync(process.env.EVOLUTION_DIR, { recursive: true });
fs.mkdirSync(process.env.MEMORY_DIR, { recursive: true });
}
function teardownTempEnv() {
if (origGepAssetsDir !== undefined) process.env.GEP_ASSETS_DIR = origGepAssetsDir;
else delete process.env.GEP_ASSETS_DIR;
if (origEvolutionDir !== undefined) process.env.EVOLUTION_DIR = origEvolutionDir;
else delete process.env.EVOLUTION_DIR;
if (origMemoryDir !== undefined) process.env.MEMORY_DIR = origMemoryDir;
else delete process.env.MEMORY_DIR;
if (origSkillDistiller !== undefined) process.env.SKILL_DISTILLER = origSkillDistiller;
else delete process.env.SKILL_DISTILLER;
delete process.env.MEMORY_GRAPH_PATH;
try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch (e) {}
}
function makeCapsule(id, gene, status, score, trigger, summary) {
return {
type: 'Capsule', id: id, gene: gene,
trigger: trigger || ['error', 'repair'],
summary: summary || 'Fixed a bug in module X',
outcome: { status: status, score: score },
};
}
function writeCapsules(capsules) {
fs.writeFileSync(
path.join(process.env.GEP_ASSETS_DIR, 'capsules.json'),
JSON.stringify({ version: 1, capsules: capsules }, null, 2)
);
}
function writeEvents(events) {
var lines = events.map(function (e) { return JSON.stringify(e); }).join('\n') + '\n';
fs.writeFileSync(path.join(process.env.GEP_ASSETS_DIR, 'events.jsonl'), lines);
}
function writeGenes(genes) {
fs.writeFileSync(
path.join(process.env.GEP_ASSETS_DIR, 'genes.json'),
JSON.stringify({ version: 1, genes: genes }, null, 2)
);
}
// --- Tests ---
describe('computeDataHash', () => {
it('returns stable hash for same capsule ids', () => {
var c1 = [{ id: 'a' }, { id: 'b' }];
var c2 = [{ id: 'b' }, { id: 'a' }];
assert.equal(computeDataHash(c1), computeDataHash(c2));
});
it('returns different hash for different capsule ids', () => {
var c1 = [{ id: 'a' }];
var c2 = [{ id: 'b' }];
assert.notEqual(computeDataHash(c1), computeDataHash(c2));
});
});
describe('extractJsonFromLlmResponse', () => {
it('extracts Gene JSON from clean response', () => {
var text = '{"type":"Gene","id":"gene_distilled_test","category":"repair","signals_match":["err"],"strategy":["fix it"]}';
var gene = extractJsonFromLlmResponse(text);
assert.ok(gene);
assert.equal(gene.type, 'Gene');
assert.equal(gene.id, 'gene_distilled_test');
});
it('extracts Gene JSON wrapped in markdown', () => {
var text = 'Here is the gene:\n```json\n{"type":"Gene","id":"gene_distilled_x","category":"opt","signals_match":["a"],"strategy":["b"]}\n```\n';
var gene = extractJsonFromLlmResponse(text);
assert.ok(gene);
assert.equal(gene.id, 'gene_distilled_x');
});
it('returns null when no Gene JSON present', () => {
var text = 'No JSON here, just text.';
assert.equal(extractJsonFromLlmResponse(text), null);
});
it('skips non-Gene JSON objects', () => {
var text = '{"type":"Capsule","id":"cap1"} then {"type":"Gene","id":"gene_distilled_y","category":"c","signals_match":["s"],"strategy":["do"]}';
var gene = extractJsonFromLlmResponse(text);
assert.ok(gene);
assert.equal(gene.type, 'Gene');
assert.equal(gene.id, 'gene_distilled_y');
});
});
describe('validateSynthesizedGene', () => {
it('accepts a valid gene', () => {
var gene = {
type: 'Gene', id: 'gene_distilled_test', category: 'repair',
signals_match: ['error'], strategy: ['fix the bug'],
constraints: { max_files: 8, forbidden_paths: ['.git', 'node_modules'] },
};
var result = validateSynthesizedGene(gene, []);
assert.ok(result.valid, 'Expected valid but got errors: ' + result.errors.join(', '));
});
it('auto-prefixes id if missing distilled prefix', () => {
var gene = {
type: 'Gene', id: 'gene_test_auto', category: 'opt',
signals_match: ['optimize'], strategy: ['do stuff'],
constraints: { forbidden_paths: ['.git'] },
};
var result = validateSynthesizedGene(gene, []);
assert.ok(result.gene.id.startsWith(DISTILLED_ID_PREFIX));
});
it('caps max_files to DISTILLED_MAX_FILES', () => {
var gene = {
type: 'Gene', id: 'gene_distilled_big', category: 'opt',
signals_match: ['x'], strategy: ['y'],
constraints: { max_files: 50, forbidden_paths: ['.git', 'node_modules'] },
};
var result = validateSynthesizedGene(gene, []);
assert.ok(result.gene.constraints.max_files <= DISTILLED_MAX_FILES);
});
it('rejects gene without strategy', () => {
var gene = { type: 'Gene', id: 'gene_distilled_empty', category: 'x', signals_match: ['a'] };
var result = validateSynthesizedGene(gene, []);
assert.ok(!result.valid);
assert.ok(result.errors.some(function (e) { return e.includes('strategy'); }));
});
it('rejects gene without signals_match', () => {
var gene = { type: 'Gene', id: 'gene_distilled_nosig', category: 'x', strategy: ['do'] };
var result = validateSynthesizedGene(gene, []);
assert.ok(!result.valid);
assert.ok(result.errors.some(function (e) { return e.includes('signals_match'); }));
});
it('detects full overlap with existing gene', () => {
var existing = [{ id: 'gene_existing', signals_match: ['error', 'repair'] }];
var gene = {
type: 'Gene', id: 'gene_distilled_dup', category: 'repair',
signals_match: ['error', 'repair'], strategy: ['fix'],
constraints: { forbidden_paths: ['.git', 'node_modules'] },
};
var result = validateSynthesizedGene(gene, existing);
assert.ok(!result.valid);
assert.ok(result.errors.some(function (e) { return e.includes('overlaps'); }));
});
it('deduplicates id if conflict with existing gene', () => {
var existing = [{ id: 'gene_distilled_conflict', signals_match: ['other'] }];
var gene = {
type: 'Gene', id: 'gene_distilled_conflict', category: 'opt',
signals_match: ['different'], strategy: ['do'],
constraints: { forbidden_paths: ['.git', 'node_modules'] },
};
var result = validateSynthesizedGene(gene, existing);
assert.ok(result.gene.id !== 'gene_distilled_conflict');
assert.ok(result.gene.id.startsWith('gene_distilled_conflict_'));
});
it('strips unsafe validation commands', () => {
var gene = {
type: 'Gene', id: 'gene_distilled_unsafe', category: 'opt',
signals_match: ['x'], strategy: ['do'],
constraints: { forbidden_paths: ['.git', 'node_modules'] },
validation: ['node test.js', 'rm -rf /', 'echo $(whoami)', 'npm test'],
};
var result = validateSynthesizedGene(gene, []);
assert.deepEqual(result.gene.validation, ['node test.js', 'npm test']);
});
});
describe('collectDistillationData', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('returns empty when no capsules exist', () => {
var data = collectDistillationData();
assert.equal(data.successCapsules.length, 0);
assert.equal(data.allCapsules.length, 0);
});
it('filters only successful capsules with score >= threshold', () => {
var caps = [
makeCapsule('c1', 'gene_a', 'success', 0.9),
makeCapsule('c2', 'gene_a', 'failed', 0.2),
makeCapsule('c3', 'gene_b', 'success', 0.5),
];
writeCapsules(caps);
var data = collectDistillationData();
assert.equal(data.allCapsules.length, 3);
assert.equal(data.successCapsules.length, 1);
assert.equal(data.successCapsules[0].id, 'c1');
});
it('groups capsules by gene', () => {
var caps = [
makeCapsule('c1', 'gene_a', 'success', 0.9),
makeCapsule('c2', 'gene_a', 'success', 0.8),
makeCapsule('c3', 'gene_b', 'success', 0.95),
];
writeCapsules(caps);
var data = collectDistillationData();
assert.equal(Object.keys(data.grouped).length, 2);
assert.equal(data.grouped['gene_a'].total_count, 2);
assert.equal(data.grouped['gene_b'].total_count, 1);
});
});
describe('analyzePatterns', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('identifies high-frequency groups (count >= 5)', () => {
var caps = [];
for (var i = 0; i < 6; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9, ['error', 'crash']));
}
writeCapsules(caps);
var data = collectDistillationData();
var report = analyzePatterns(data);
assert.equal(report.high_frequency.length, 1);
assert.equal(report.high_frequency[0].gene_id, 'gene_a');
assert.equal(report.high_frequency[0].count, 6);
});
it('detects strategy drift when summaries diverge', () => {
var caps = [
makeCapsule('c1', 'gene_a', 'success', 0.9, ['err'], 'Fixed crash in module A by patching function foo'),
makeCapsule('c2', 'gene_a', 'success', 0.9, ['err'], 'Fixed crash in module A by patching function foo'),
makeCapsule('c3', 'gene_a', 'success', 0.9, ['err'], 'Completely redesigned the logging infrastructure to avoid all future problems with disk IO'),
];
writeCapsules(caps);
var data = collectDistillationData();
var report = analyzePatterns(data);
assert.equal(report.strategy_drift.length, 1);
assert.ok(report.strategy_drift[0].similarity < 0.6);
});
it('identifies coverage gaps from events', () => {
writeCapsules([makeCapsule('c1', 'gene_a', 'success', 0.9, ['error'])]);
var events = [];
for (var i = 0; i < 5; i++) {
events.push({ type: 'EvolutionEvent', signals: ['memory_leak', 'performance'] });
}
writeEvents(events);
var data = collectDistillationData();
var report = analyzePatterns(data);
assert.ok(report.coverage_gaps.length > 0);
assert.ok(report.coverage_gaps.some(function (g) { return g.signal === 'memory_leak'; }));
});
});
describe('buildDistillationPrompt', () => {
it('includes key instructions in prompt', () => {
var analysis = { high_frequency: [], strategy_drift: [], coverage_gaps: [] };
var genes = [{ id: 'gene_a', signals_match: ['err'] }];
var caps = [makeCapsule('c1', 'gene_a', 'success', 0.9)];
var prompt = buildDistillationPrompt(analysis, genes, caps);
assert.ok(prompt.includes('actionable operations'));
assert.ok(prompt.includes('gene_distilled_'));
assert.ok(prompt.includes('Gene synthesis engine'));
assert.ok(prompt.includes('forbidden_paths'));
});
});
describe('shouldDistill', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('returns false when SKILL_DISTILLER=false', () => {
process.env.SKILL_DISTILLER = 'false';
assert.equal(shouldDistill(), false);
});
it('returns false when not enough successful capsules', () => {
var caps = [];
for (var i = 0; i < 10; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'failed', 0.3));
}
writeCapsules(caps);
assert.equal(shouldDistill(), false);
});
it('returns false when interval not met', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeDistillerState({ last_distillation_at: new Date().toISOString() });
assert.equal(shouldDistill(), false);
});
it('returns true when all conditions met', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeDistillerState({});
delete process.env.SKILL_DISTILLER;
assert.equal(shouldDistill(), true);
});
});
describe('distiller state persistence', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('writes and reads state correctly', () => {
var state = { last_distillation_at: '2025-01-01T00:00:00Z', last_data_hash: 'abc123', distillation_count: 3 };
writeDistillerState(state);
var loaded = readDistillerState();
assert.equal(loaded.last_data_hash, 'abc123');
assert.equal(loaded.distillation_count, 3);
});
});
describe('prepareDistillation', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('returns insufficient_data when not enough capsules', () => {
writeCapsules([makeCapsule('c1', 'gene_a', 'success', 0.9)]);
var result = prepareDistillation();
assert.equal(result.ok, false);
assert.equal(result.reason, 'insufficient_data');
});
it('writes prompt and request files when conditions met', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeDistillerState({});
writeGenes([]);
var result = prepareDistillation();
assert.equal(result.ok, true);
assert.ok(result.promptPath);
assert.ok(result.requestPath);
assert.ok(fs.existsSync(result.promptPath));
assert.ok(fs.existsSync(result.requestPath));
var prompt = fs.readFileSync(result.promptPath, 'utf8');
assert.ok(prompt.includes('Gene synthesis engine'));
var request = JSON.parse(fs.readFileSync(result.requestPath, 'utf8'));
assert.equal(request.type, 'DistillationRequest');
assert.equal(request.input_capsule_count, 12);
});
it('returns idempotent_skip after completeDistillation with same data', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeGenes([]);
writeDistillerState({});
var prep = prepareDistillation();
assert.equal(prep.ok, true);
var llmResponse = JSON.stringify({
type: 'Gene', id: 'gene_distilled_idem', category: 'repair',
signals_match: ['error'], strategy: ['fix it'],
constraints: { max_files: 5, forbidden_paths: ['.git', 'node_modules'] },
});
var complete = completeDistillation(llmResponse);
assert.equal(complete.ok, true);
var second = prepareDistillation();
assert.equal(second.ok, false);
assert.equal(second.reason, 'idempotent_skip');
});
});
describe('completeDistillation', () => {
beforeEach(setupTempEnv);
afterEach(teardownTempEnv);
it('returns no_request when no pending request', () => {
var result = completeDistillation('{"type":"Gene"}');
assert.equal(result.ok, false);
assert.equal(result.reason, 'no_request');
});
it('returns no_gene_in_response for invalid LLM output', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeDistillerState({});
writeGenes([]);
var prep = prepareDistillation();
assert.equal(prep.ok, true);
var result = completeDistillation('No valid JSON here');
assert.equal(result.ok, false);
assert.equal(result.reason, 'no_gene_in_response');
});
it('validates and saves gene from valid LLM response', () => {
var caps = [];
for (var i = 0; i < 12; i++) {
caps.push(makeCapsule('c' + i, 'gene_a', 'success', 0.9));
}
writeCapsules(caps);
writeDistillerState({});
writeGenes([]);
var prep = prepareDistillation();
assert.equal(prep.ok, true);
var llmResponse = JSON.stringify({
type: 'Gene',
id: 'gene_distilled_test_complete',
category: 'repair',
signals_match: ['error', 'crash'],
strategy: ['Identify the failing module', 'Apply targeted fix', 'Run validation'],
constraints: { max_files: 5, forbidden_paths: ['.git', 'node_modules'] },
validation: ['node test.js'],
});
var result = completeDistillation(llmResponse);
assert.equal(result.ok, true);
assert.ok(result.gene);
assert.equal(result.gene.type, 'Gene');
assert.ok(result.gene.id.startsWith('gene_distilled_'));
var state = readDistillerState();
assert.ok(state.last_distillation_at);
assert.equal(state.distillation_count, 1);
assert.ok(!fs.existsSync(distillRequestPath()));
});
});
+133
View File
@@ -0,0 +1,133 @@
const { describe, it, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const { resolveStrategy, getStrategyNames, STRATEGIES } = require('../src/gep/strategy');
describe('STRATEGIES', function () {
it('defines all expected presets', function () {
const names = getStrategyNames();
assert.ok(names.includes('balanced'));
assert.ok(names.includes('innovate'));
assert.ok(names.includes('harden'));
assert.ok(names.includes('repair-only'));
assert.ok(names.includes('early-stabilize'));
assert.ok(names.includes('steady-state'));
});
it('all strategies have required fields', function () {
for (const [name, s] of Object.entries(STRATEGIES)) {
assert.equal(typeof s.repair, 'number', `${name}.repair`);
assert.equal(typeof s.optimize, 'number', `${name}.optimize`);
assert.equal(typeof s.innovate, 'number', `${name}.innovate`);
assert.equal(typeof s.repairLoopThreshold, 'number', `${name}.repairLoopThreshold`);
assert.equal(typeof s.label, 'string', `${name}.label`);
assert.equal(typeof s.description, 'string', `${name}.description`);
}
});
it('all strategy ratios sum to approximately 1.0', function () {
for (const [name, s] of Object.entries(STRATEGIES)) {
const sum = s.repair + s.optimize + s.innovate;
assert.ok(Math.abs(sum - 1.0) < 0.01, `${name} ratios sum to ${sum}`);
}
});
});
describe('resolveStrategy', function () {
let origStrategy;
let origForceInnovation;
let origEvolveForceInnovation;
beforeEach(function () {
origStrategy = process.env.EVOLVE_STRATEGY;
origForceInnovation = process.env.FORCE_INNOVATION;
origEvolveForceInnovation = process.env.EVOLVE_FORCE_INNOVATION;
delete process.env.EVOLVE_STRATEGY;
delete process.env.FORCE_INNOVATION;
delete process.env.EVOLVE_FORCE_INNOVATION;
});
afterEach(function () {
if (origStrategy !== undefined) process.env.EVOLVE_STRATEGY = origStrategy;
else delete process.env.EVOLVE_STRATEGY;
if (origForceInnovation !== undefined) process.env.FORCE_INNOVATION = origForceInnovation;
else delete process.env.FORCE_INNOVATION;
if (origEvolveForceInnovation !== undefined) process.env.EVOLVE_FORCE_INNOVATION = origEvolveForceInnovation;
else delete process.env.EVOLVE_FORCE_INNOVATION;
});
it('defaults to balanced when no env var set', function () {
const s = resolveStrategy({});
assert.ok(['balanced', 'early-stabilize'].includes(s.name));
});
it('respects explicit EVOLVE_STRATEGY', function () {
process.env.EVOLVE_STRATEGY = 'harden';
const s = resolveStrategy({});
assert.equal(s.name, 'harden');
assert.equal(s.label, 'Hardening');
});
it('respects innovate strategy', function () {
process.env.EVOLVE_STRATEGY = 'innovate';
const s = resolveStrategy({});
assert.equal(s.name, 'innovate');
assert.ok(s.innovate >= 0.8);
});
it('respects repair-only strategy', function () {
process.env.EVOLVE_STRATEGY = 'repair-only';
const s = resolveStrategy({});
assert.equal(s.name, 'repair-only');
assert.equal(s.innovate, 0);
});
it('FORCE_INNOVATION=true maps to innovate', function () {
process.env.FORCE_INNOVATION = 'true';
const s = resolveStrategy({});
assert.equal(s.name, 'innovate');
});
it('EVOLVE_FORCE_INNOVATION=true maps to innovate', function () {
process.env.EVOLVE_FORCE_INNOVATION = 'true';
const s = resolveStrategy({});
assert.equal(s.name, 'innovate');
});
it('explicit EVOLVE_STRATEGY takes precedence over FORCE_INNOVATION', function () {
process.env.EVOLVE_STRATEGY = 'harden';
process.env.FORCE_INNOVATION = 'true';
const s = resolveStrategy({});
assert.equal(s.name, 'harden');
});
it('saturation signal triggers steady-state', function () {
const s = resolveStrategy({ signals: ['evolution_saturation'] });
assert.equal(s.name, 'steady-state');
});
it('force_steady_state signal triggers steady-state', function () {
const s = resolveStrategy({ signals: ['force_steady_state'] });
assert.equal(s.name, 'steady-state');
});
it('falls back to balanced for unknown strategy name', function () {
process.env.EVOLVE_STRATEGY = 'nonexistent';
const s = resolveStrategy({});
const fallback = STRATEGIES['balanced'];
assert.equal(s.repair, fallback.repair);
assert.equal(s.optimize, fallback.optimize);
assert.equal(s.innovate, fallback.innovate);
});
it('auto maps to balanced or heuristic', function () {
process.env.EVOLVE_STRATEGY = 'auto';
const s = resolveStrategy({});
assert.ok(['balanced', 'early-stabilize'].includes(s.name));
});
it('returned strategy has name property', function () {
process.env.EVOLVE_STRATEGY = 'harden';
const s = resolveStrategy({});
assert.equal(s.name, 'harden');
});
});
@@ -0,0 +1,148 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { buildValidationReport, isValidValidationReport } = require('../src/gep/validationReport');
describe('buildValidationReport', function () {
it('builds a valid report with minimal input', function () {
const report = buildValidationReport({
geneId: 'gene_test',
commands: ['echo hello'],
results: [{ ok: true, stdout: 'hello', stderr: '' }],
});
assert.equal(report.type, 'ValidationReport');
assert.equal(report.gene_id, 'gene_test');
assert.equal(report.overall_ok, true);
assert.equal(report.commands.length, 1);
assert.equal(report.commands[0].command, 'echo hello');
assert.equal(report.commands[0].ok, true);
assert.ok(report.id.startsWith('vr_'));
assert.ok(report.created_at);
assert.ok(report.asset_id);
assert.ok(report.env_fingerprint);
assert.ok(report.env_fingerprint_key);
});
it('marks overall_ok false when any result fails', function () {
const report = buildValidationReport({
geneId: 'gene_fail',
commands: ['cmd1', 'cmd2'],
results: [
{ ok: true, stdout: 'ok' },
{ ok: false, stderr: 'error' },
],
});
assert.equal(report.overall_ok, false);
});
it('marks overall_ok false when results is empty', function () {
const report = buildValidationReport({
geneId: 'gene_empty',
commands: [],
results: [],
});
assert.equal(report.overall_ok, false);
});
it('handles null geneId', function () {
const report = buildValidationReport({
commands: ['test'],
results: [{ ok: true }],
});
assert.equal(report.gene_id, null);
});
it('computes duration_ms from timestamps', function () {
const report = buildValidationReport({
geneId: 'gene_dur',
commands: ['test'],
results: [{ ok: true }],
startedAt: 1000,
finishedAt: 2500,
});
assert.equal(report.duration_ms, 1500);
});
it('duration_ms is null when timestamps missing', function () {
const report = buildValidationReport({
geneId: 'gene_nodur',
commands: ['test'],
results: [{ ok: true }],
});
assert.equal(report.duration_ms, null);
});
it('truncates stdout/stderr to 4000 chars', function () {
const longOutput = 'x'.repeat(5000);
const report = buildValidationReport({
geneId: 'gene_long',
commands: ['test'],
results: [{ ok: true, stdout: longOutput, stderr: longOutput }],
});
assert.equal(report.commands[0].stdout.length, 4000);
assert.equal(report.commands[0].stderr.length, 4000);
});
it('supports both out/stdout and err/stderr field names', function () {
const report = buildValidationReport({
geneId: 'gene_compat',
commands: ['test'],
results: [{ ok: true, out: 'output_via_out', err: 'error_via_err' }],
});
assert.equal(report.commands[0].stdout, 'output_via_out');
assert.equal(report.commands[0].stderr, 'error_via_err');
});
it('infers commands from results when commands not provided', function () {
const report = buildValidationReport({
geneId: 'gene_infer',
results: [{ ok: true, cmd: 'inferred_cmd' }],
});
assert.equal(report.commands[0].command, 'inferred_cmd');
});
it('uses provided envFp instead of capturing', function () {
const customFp = { device_id: 'custom', platform: 'test' };
const report = buildValidationReport({
geneId: 'gene_fp',
commands: ['test'],
results: [{ ok: true }],
envFp: customFp,
});
assert.equal(report.env_fingerprint.device_id, 'custom');
});
});
describe('isValidValidationReport', function () {
it('returns true for a valid report', function () {
const report = buildValidationReport({
geneId: 'gene_valid',
commands: ['test'],
results: [{ ok: true }],
});
assert.equal(isValidValidationReport(report), true);
});
it('returns false for null', function () {
assert.equal(isValidValidationReport(null), false);
});
it('returns false for non-object', function () {
assert.equal(isValidValidationReport('string'), false);
});
it('returns false for wrong type field', function () {
assert.equal(isValidValidationReport({ type: 'Other', id: 'x', commands: [], overall_ok: true }), false);
});
it('returns false for missing id', function () {
assert.equal(isValidValidationReport({ type: 'ValidationReport', commands: [], overall_ok: true }), false);
});
it('returns false for missing commands', function () {
assert.equal(isValidValidationReport({ type: 'ValidationReport', id: 'x', overall_ok: true }), false);
});
it('returns false for missing overall_ok', function () {
assert.equal(isValidValidationReport({ type: 'ValidationReport', id: 'x', commands: [] }), false);
});
});