@harness-engineering/intelligence 0.1.1 → 0.1.3
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 +64 -35
- package/dist/index.mjs +64 -35
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -197,7 +197,22 @@ function convertNullable(def) {
|
|
|
197
197
|
}
|
|
198
198
|
var ZOD_CONVERTERS = {
|
|
199
199
|
ZodString: () => ({ type: "string" }),
|
|
200
|
-
ZodNumber: () =>
|
|
200
|
+
ZodNumber: (def) => {
|
|
201
|
+
const result = { type: "number" };
|
|
202
|
+
const checks = def["checks"];
|
|
203
|
+
if (checks) {
|
|
204
|
+
for (const check of checks) {
|
|
205
|
+
if (check.kind === "min") {
|
|
206
|
+
result[check.inclusive === false ? "exclusiveMinimum" : "minimum"] = check.value;
|
|
207
|
+
}
|
|
208
|
+
if (check.kind === "max") {
|
|
209
|
+
result[check.inclusive === false ? "exclusiveMaximum" : "maximum"] = check.value;
|
|
210
|
+
}
|
|
211
|
+
if (check.kind === "int") result["type"] = "integer";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
},
|
|
201
216
|
ZodBoolean: () => ({ type: "boolean" }),
|
|
202
217
|
ZodLiteral: (def) => ({ type: typeof def["value"], const: def["value"] }),
|
|
203
218
|
ZodEnum: (def) => ({ type: "string", enum: def["values"] }),
|
|
@@ -1374,16 +1389,19 @@ function computeVolumeBonus(sampleSize) {
|
|
|
1374
1389
|
function bucketKey(persona, systemNodeId, taskType) {
|
|
1375
1390
|
return `${persona}|${systemNodeId}|${taskType}`;
|
|
1376
1391
|
}
|
|
1377
|
-
function
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1392
|
+
function matchesFilter(record, opts) {
|
|
1393
|
+
if (!opts) return true;
|
|
1394
|
+
const filters = [
|
|
1395
|
+
[opts.persona, record.persona],
|
|
1396
|
+
[opts.systemNodeId, record.systemNodeId],
|
|
1397
|
+
[opts.taskType, record.taskType]
|
|
1398
|
+
];
|
|
1399
|
+
return filters.every(([filter, value]) => !filter || filter === value);
|
|
1400
|
+
}
|
|
1401
|
+
function groupIntoBuckets(records, opts) {
|
|
1382
1402
|
const buckets = /* @__PURE__ */ new Map();
|
|
1383
1403
|
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;
|
|
1404
|
+
if (!matchesFilter(record, opts)) continue;
|
|
1387
1405
|
const key = bucketKey(record.persona, record.systemNodeId, record.taskType);
|
|
1388
1406
|
let arr = buckets.get(key);
|
|
1389
1407
|
if (!arr) {
|
|
@@ -1392,35 +1410,46 @@ function computeSpecialization(store, opts) {
|
|
|
1392
1410
|
}
|
|
1393
1411
|
arr.push(record);
|
|
1394
1412
|
}
|
|
1413
|
+
return buckets;
|
|
1414
|
+
}
|
|
1415
|
+
function computeEntryFromBucket(records, temporal) {
|
|
1416
|
+
const first = records[0];
|
|
1417
|
+
const { persona, systemNodeId, taskType } = first;
|
|
1418
|
+
const sorted = [...records].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1419
|
+
const tsr = temporalSuccessRate(
|
|
1420
|
+
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1421
|
+
temporal
|
|
1422
|
+
);
|
|
1423
|
+
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1424
|
+
const volume = computeVolumeBonus(sorted.length);
|
|
1425
|
+
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1426
|
+
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1427
|
+
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1428
|
+
return {
|
|
1429
|
+
persona,
|
|
1430
|
+
systemNodeId,
|
|
1431
|
+
taskType,
|
|
1432
|
+
score: {
|
|
1433
|
+
temporalSuccessRate: tsr,
|
|
1434
|
+
consistencyScore: consistency,
|
|
1435
|
+
volumeBonus: volume,
|
|
1436
|
+
composite
|
|
1437
|
+
},
|
|
1438
|
+
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1439
|
+
sampleSize: sorted.length,
|
|
1440
|
+
lastOutcome
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
function computeSpecialization(store, opts) {
|
|
1444
|
+
const records = gatherOutcomesWithTaskType(store);
|
|
1445
|
+
if (records.length === 0) return [];
|
|
1446
|
+
const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
|
|
1447
|
+
const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
|
|
1448
|
+
const buckets = groupIntoBuckets(records, opts);
|
|
1395
1449
|
const entries = [];
|
|
1396
1450
|
for (const [, records2] of buckets) {
|
|
1397
1451
|
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
|
-
});
|
|
1452
|
+
entries.push(computeEntryFromBucket(records2, temporal));
|
|
1424
1453
|
}
|
|
1425
1454
|
entries.sort((a, b) => b.score.composite - a.score.composite);
|
|
1426
1455
|
return entries;
|
package/dist/index.mjs
CHANGED
|
@@ -130,7 +130,22 @@ function convertNullable(def) {
|
|
|
130
130
|
}
|
|
131
131
|
var ZOD_CONVERTERS = {
|
|
132
132
|
ZodString: () => ({ type: "string" }),
|
|
133
|
-
ZodNumber: () =>
|
|
133
|
+
ZodNumber: (def) => {
|
|
134
|
+
const result = { type: "number" };
|
|
135
|
+
const checks = def["checks"];
|
|
136
|
+
if (checks) {
|
|
137
|
+
for (const check of checks) {
|
|
138
|
+
if (check.kind === "min") {
|
|
139
|
+
result[check.inclusive === false ? "exclusiveMinimum" : "minimum"] = check.value;
|
|
140
|
+
}
|
|
141
|
+
if (check.kind === "max") {
|
|
142
|
+
result[check.inclusive === false ? "exclusiveMaximum" : "maximum"] = check.value;
|
|
143
|
+
}
|
|
144
|
+
if (check.kind === "int") result["type"] = "integer";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
},
|
|
134
149
|
ZodBoolean: () => ({ type: "boolean" }),
|
|
135
150
|
ZodLiteral: (def) => ({ type: typeof def["value"], const: def["value"] }),
|
|
136
151
|
ZodEnum: (def) => ({ type: "string", enum: def["values"] }),
|
|
@@ -1307,16 +1322,19 @@ function computeVolumeBonus(sampleSize) {
|
|
|
1307
1322
|
function bucketKey(persona, systemNodeId, taskType) {
|
|
1308
1323
|
return `${persona}|${systemNodeId}|${taskType}`;
|
|
1309
1324
|
}
|
|
1310
|
-
function
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1325
|
+
function matchesFilter(record, opts) {
|
|
1326
|
+
if (!opts) return true;
|
|
1327
|
+
const filters = [
|
|
1328
|
+
[opts.persona, record.persona],
|
|
1329
|
+
[opts.systemNodeId, record.systemNodeId],
|
|
1330
|
+
[opts.taskType, record.taskType]
|
|
1331
|
+
];
|
|
1332
|
+
return filters.every(([filter, value]) => !filter || filter === value);
|
|
1333
|
+
}
|
|
1334
|
+
function groupIntoBuckets(records, opts) {
|
|
1315
1335
|
const buckets = /* @__PURE__ */ new Map();
|
|
1316
1336
|
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;
|
|
1337
|
+
if (!matchesFilter(record, opts)) continue;
|
|
1320
1338
|
const key = bucketKey(record.persona, record.systemNodeId, record.taskType);
|
|
1321
1339
|
let arr = buckets.get(key);
|
|
1322
1340
|
if (!arr) {
|
|
@@ -1325,35 +1343,46 @@ function computeSpecialization(store, opts) {
|
|
|
1325
1343
|
}
|
|
1326
1344
|
arr.push(record);
|
|
1327
1345
|
}
|
|
1346
|
+
return buckets;
|
|
1347
|
+
}
|
|
1348
|
+
function computeEntryFromBucket(records, temporal) {
|
|
1349
|
+
const first = records[0];
|
|
1350
|
+
const { persona, systemNodeId, taskType } = first;
|
|
1351
|
+
const sorted = [...records].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1352
|
+
const tsr = temporalSuccessRate(
|
|
1353
|
+
sorted.map((r) => ({ result: r.result, timestamp: r.timestamp })),
|
|
1354
|
+
temporal
|
|
1355
|
+
);
|
|
1356
|
+
const consistency = computeConsistency(sorted.map((r) => r.result));
|
|
1357
|
+
const volume = computeVolumeBonus(sorted.length);
|
|
1358
|
+
const composite = W_TEMPORAL * tsr + W_CONSISTENCY * consistency + W_VOLUME * volume;
|
|
1359
|
+
const lastOutcome = sorted[sorted.length - 1].timestamp;
|
|
1360
|
+
const rawSuccessRate = sorted.filter((r) => r.result === "success").length / sorted.length;
|
|
1361
|
+
return {
|
|
1362
|
+
persona,
|
|
1363
|
+
systemNodeId,
|
|
1364
|
+
taskType,
|
|
1365
|
+
score: {
|
|
1366
|
+
temporalSuccessRate: tsr,
|
|
1367
|
+
consistencyScore: consistency,
|
|
1368
|
+
volumeBonus: volume,
|
|
1369
|
+
composite
|
|
1370
|
+
},
|
|
1371
|
+
expertiseLevel: computeExpertiseLevel(sorted.length, rawSuccessRate),
|
|
1372
|
+
sampleSize: sorted.length,
|
|
1373
|
+
lastOutcome
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
function computeSpecialization(store, opts) {
|
|
1377
|
+
const records = gatherOutcomesWithTaskType(store);
|
|
1378
|
+
if (records.length === 0) return [];
|
|
1379
|
+
const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
|
|
1380
|
+
const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
|
|
1381
|
+
const buckets = groupIntoBuckets(records, opts);
|
|
1328
1382
|
const entries = [];
|
|
1329
1383
|
for (const [, records2] of buckets) {
|
|
1330
1384
|
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
|
-
});
|
|
1385
|
+
entries.push(computeEntryFromBucket(records2, temporal));
|
|
1357
1386
|
}
|
|
1358
1387
|
entries.sort((a, b) => b.score.composite - a.score.composite);
|
|
1359
1388
|
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.3",
|
|
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.6.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",
|