@harness-engineering/intelligence 0.1.1 → 0.1.2
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/dist/index.js +48 -34
- package/dist/index.mjs +48 -34
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1374,16 +1374,19 @@ function computeVolumeBonus(sampleSize) {
|
|
|
1374
1374
|
function bucketKey(persona, systemNodeId, taskType) {
|
|
1375
1375
|
return `${persona}|${systemNodeId}|${taskType}`;
|
|
1376
1376
|
}
|
|
1377
|
-
function
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1377
|
+
function matchesFilter(record, opts) {
|
|
1378
|
+
if (!opts) return true;
|
|
1379
|
+
const filters = [
|
|
1380
|
+
[opts.persona, record.persona],
|
|
1381
|
+
[opts.systemNodeId, record.systemNodeId],
|
|
1382
|
+
[opts.taskType, record.taskType]
|
|
1383
|
+
];
|
|
1384
|
+
return filters.every(([filter, value]) => !filter || filter === value);
|
|
1385
|
+
}
|
|
1386
|
+
function groupIntoBuckets(records, opts) {
|
|
1382
1387
|
const buckets = /* @__PURE__ */ new Map();
|
|
1383
1388
|
for (const record of records) {
|
|
1384
|
-
if (
|
|
1385
|
-
if (opts?.systemNodeId && record.systemNodeId !== opts.systemNodeId) continue;
|
|
1386
|
-
if (opts?.taskType && record.taskType !== opts.taskType) continue;
|
|
1389
|
+
if (!matchesFilter(record, opts)) continue;
|
|
1387
1390
|
const key = bucketKey(record.persona, record.systemNodeId, record.taskType);
|
|
1388
1391
|
let arr = buckets.get(key);
|
|
1389
1392
|
if (!arr) {
|
|
@@ -1392,35 +1395,46 @@ function computeSpecialization(store, opts) {
|
|
|
1392
1395
|
}
|
|
1393
1396
|
arr.push(record);
|
|
1394
1397
|
}
|
|
1398
|
+
return buckets;
|
|
1399
|
+
}
|
|
1400
|
+
function computeEntryFromBucket(records, temporal) {
|
|
1401
|
+
const first = records[0];
|
|
1402
|
+
const { persona, systemNodeId, taskType } = first;
|
|
1403
|
+
const sorted = [...records].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1404
|
+
const tsr = temporalSuccessRate(
|
|
1405
|
+
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1406
|
+
temporal
|
|
1407
|
+
);
|
|
1408
|
+
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1409
|
+
const volume = computeVolumeBonus(sorted.length);
|
|
1410
|
+
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1411
|
+
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1412
|
+
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1413
|
+
return {
|
|
1414
|
+
persona,
|
|
1415
|
+
systemNodeId,
|
|
1416
|
+
taskType,
|
|
1417
|
+
score: {
|
|
1418
|
+
temporalSuccessRate: tsr,
|
|
1419
|
+
consistencyScore: consistency,
|
|
1420
|
+
volumeBonus: volume,
|
|
1421
|
+
composite
|
|
1422
|
+
},
|
|
1423
|
+
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1424
|
+
sampleSize: sorted.length,
|
|
1425
|
+
lastOutcome
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
function computeSpecialization(store, opts) {
|
|
1429
|
+
const records = gatherOutcomesWithTaskType(store);
|
|
1430
|
+
if (records.length === 0) return [];
|
|
1431
|
+
const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
|
|
1432
|
+
const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
|
|
1433
|
+
const buckets = groupIntoBuckets(records, opts);
|
|
1395
1434
|
const entries = [];
|
|
1396
1435
|
for (const [, records2] of buckets) {
|
|
1397
1436
|
if (records2.length < minSamples) continue;
|
|
1398
|
-
|
|
1399
|
-
const { persona, systemNodeId, taskType } = first;
|
|
1400
|
-
const sorted = [...records2].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1401
|
-
const tsr = temporalSuccessRate(
|
|
1402
|
-
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1403
|
-
temporal
|
|
1404
|
-
);
|
|
1405
|
-
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1406
|
-
const volume = computeVolumeBonus(sorted.length);
|
|
1407
|
-
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1408
|
-
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1409
|
-
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1410
|
-
entries.push({
|
|
1411
|
-
persona,
|
|
1412
|
-
systemNodeId,
|
|
1413
|
-
taskType,
|
|
1414
|
-
score: {
|
|
1415
|
-
temporalSuccessRate: tsr,
|
|
1416
|
-
consistencyScore: consistency,
|
|
1417
|
-
volumeBonus: volume,
|
|
1418
|
-
composite
|
|
1419
|
-
},
|
|
1420
|
-
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1421
|
-
sampleSize: sorted.length,
|
|
1422
|
-
lastOutcome
|
|
1423
|
-
});
|
|
1437
|
+
entries.push(computeEntryFromBucket(records2, temporal));
|
|
1424
1438
|
}
|
|
1425
1439
|
entries.sort((a, b) => b.score.composite - a.score.composite);
|
|
1426
1440
|
return entries;
|
package/dist/index.mjs
CHANGED
|
@@ -1307,16 +1307,19 @@ function computeVolumeBonus(sampleSize) {
|
|
|
1307
1307
|
function bucketKey(persona, systemNodeId, taskType) {
|
|
1308
1308
|
return `${persona}|${systemNodeId}|${taskType}`;
|
|
1309
1309
|
}
|
|
1310
|
-
function
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1310
|
+
function matchesFilter(record, opts) {
|
|
1311
|
+
if (!opts) return true;
|
|
1312
|
+
const filters = [
|
|
1313
|
+
[opts.persona, record.persona],
|
|
1314
|
+
[opts.systemNodeId, record.systemNodeId],
|
|
1315
|
+
[opts.taskType, record.taskType]
|
|
1316
|
+
];
|
|
1317
|
+
return filters.every(([filter, value]) => !filter || filter === value);
|
|
1318
|
+
}
|
|
1319
|
+
function groupIntoBuckets(records, opts) {
|
|
1315
1320
|
const buckets = /* @__PURE__ */ new Map();
|
|
1316
1321
|
for (const record of records) {
|
|
1317
|
-
if (
|
|
1318
|
-
if (opts?.systemNodeId && record.systemNodeId !== opts.systemNodeId) continue;
|
|
1319
|
-
if (opts?.taskType && record.taskType !== opts.taskType) continue;
|
|
1322
|
+
if (!matchesFilter(record, opts)) continue;
|
|
1320
1323
|
const key = bucketKey(record.persona, record.systemNodeId, record.taskType);
|
|
1321
1324
|
let arr = buckets.get(key);
|
|
1322
1325
|
if (!arr) {
|
|
@@ -1325,35 +1328,46 @@ function computeSpecialization(store, opts) {
|
|
|
1325
1328
|
}
|
|
1326
1329
|
arr.push(record);
|
|
1327
1330
|
}
|
|
1331
|
+
return buckets;
|
|
1332
|
+
}
|
|
1333
|
+
function computeEntryFromBucket(records, temporal) {
|
|
1334
|
+
const first = records[0];
|
|
1335
|
+
const { persona, systemNodeId, taskType } = first;
|
|
1336
|
+
const sorted = [...records].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1337
|
+
const tsr = temporalSuccessRate(
|
|
1338
|
+
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1339
|
+
temporal
|
|
1340
|
+
);
|
|
1341
|
+
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1342
|
+
const volume = computeVolumeBonus(sorted.length);
|
|
1343
|
+
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1344
|
+
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1345
|
+
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1346
|
+
return {
|
|
1347
|
+
persona,
|
|
1348
|
+
systemNodeId,
|
|
1349
|
+
taskType,
|
|
1350
|
+
score: {
|
|
1351
|
+
temporalSuccessRate: tsr,
|
|
1352
|
+
consistencyScore: consistency,
|
|
1353
|
+
volumeBonus: volume,
|
|
1354
|
+
composite
|
|
1355
|
+
},
|
|
1356
|
+
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1357
|
+
sampleSize: sorted.length,
|
|
1358
|
+
lastOutcome
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function computeSpecialization(store, opts) {
|
|
1362
|
+
const records = gatherOutcomesWithTaskType(store);
|
|
1363
|
+
if (records.length === 0) return [];
|
|
1364
|
+
const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
|
|
1365
|
+
const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
|
|
1366
|
+
const buckets = groupIntoBuckets(records, opts);
|
|
1328
1367
|
const entries = [];
|
|
1329
1368
|
for (const [, records2] of buckets) {
|
|
1330
1369
|
if (records2.length < minSamples) continue;
|
|
1331
|
-
|
|
1332
|
-
const { persona, systemNodeId, taskType } = first;
|
|
1333
|
-
const sorted = [...records2].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1334
|
-
const tsr = temporalSuccessRate(
|
|
1335
|
-
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1336
|
-
temporal
|
|
1337
|
-
);
|
|
1338
|
-
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1339
|
-
const volume = computeVolumeBonus(sorted.length);
|
|
1340
|
-
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1341
|
-
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1342
|
-
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1343
|
-
entries.push({
|
|
1344
|
-
persona,
|
|
1345
|
-
systemNodeId,
|
|
1346
|
-
taskType,
|
|
1347
|
-
score: {
|
|
1348
|
-
temporalSuccessRate: tsr,
|
|
1349
|
-
consistencyScore: consistency,
|
|
1350
|
-
volumeBonus: volume,
|
|
1351
|
-
composite
|
|
1352
|
-
},
|
|
1353
|
-
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1354
|
-
sampleSize: sorted.length,
|
|
1355
|
-
lastOutcome
|
|
1356
|
-
});
|
|
1370
|
+
entries.push(computeEntryFromBucket(records2, temporal));
|
|
1357
1371
|
}
|
|
1358
1372
|
entries.sort((a, b) => b.score.composite - a.score.composite);
|
|
1359
1373
|
return entries;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harness-engineering/intelligence",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Intelligence pipeline for spec enrichment, complexity modeling, and pre-execution simulation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -37,17 +37,17 @@
|
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://github.com/Intense-Visions/harness-engineering/tree/main/packages/intelligence#readme",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@anthropic-ai/sdk": "^0.
|
|
41
|
-
"openai": "^
|
|
40
|
+
"@anthropic-ai/sdk": "^0.91.0",
|
|
41
|
+
"openai": "^6.0.0",
|
|
42
42
|
"zod": "^3.25.76",
|
|
43
|
-
"@harness-engineering/
|
|
44
|
-
"@harness-engineering/
|
|
43
|
+
"@harness-engineering/graph": "0.5.0",
|
|
44
|
+
"@harness-engineering/types": "0.10.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^22.19.15",
|
|
48
|
-
"@vitest/coverage-v8": "^4.1.
|
|
48
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
49
49
|
"tsup": "^8.5.1",
|
|
50
|
-
"vitest": "^4.1.
|
|
50
|
+
"vitest": "^4.1.5"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsup src/index.ts --format cjs,esm --dts --tsconfig tsconfig.build.json",
|