@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 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 computeSpecialization(store, opts) {
1378
- const records = gatherOutcomesWithTaskType(store);
1379
- if (records.length === 0) return [];
1380
- const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
1381
- const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
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 (opts?.persona && record.persona !== opts.persona) continue;
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
- const first = records2[0];
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 computeSpecialization(store, opts) {
1311
- const records = gatherOutcomesWithTaskType(store);
1312
- if (records.length === 0) return [];
1313
- const temporal = opts?.temporal ?? { halfLifeDays: DEFAULT_HALF_LIFE };
1314
- const minSamples = opts?.minSamples ?? DEFAULT_MIN_SAMPLES;
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 (opts?.persona && record.persona !== opts.persona) continue;
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
- const first = records2[0];
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.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.39.0",
41
- "openai": "^4.0.0",
40
+ "@anthropic-ai/sdk": "^0.91.0",
41
+ "openai": "^6.0.0",
42
42
  "zod": "^3.25.76",
43
- "@harness-engineering/types": "0.10.0",
44
- "@harness-engineering/graph": "0.4.3"
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.2",
48
+ "@vitest/coverage-v8": "^4.1.5",
49
49
  "tsup": "^8.5.1",
50
- "vitest": "^4.1.2"
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",