agentfootprint 9.76.1 → 9.78.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/CHANGELOG.md +188 -0
- package/CLAUDE.md +2 -0
- package/dist/core/Agent.js +86 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/integrityFindings.js +47 -0
- package/dist/core/agent/integrityFindings.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +28 -29
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +184 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/tools.js +9 -1
- package/dist/core/tools.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +10 -0
- package/dist/esm/core/Agent.js +86 -0
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/integrityFindings.d.ts +27 -0
- package/dist/esm/core/agent/integrityFindings.js +43 -0
- package/dist/esm/core/agent/integrityFindings.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.d.ts +25 -0
- package/dist/esm/core/agent/stages/callLLM.js +25 -26
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +43 -0
- package/dist/esm/core/agent/stages/toolCalls.js +185 -1
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +112 -0
- package/dist/esm/core/tools.d.ts +63 -0
- package/dist/esm/core/tools.js +17 -0
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/integrity/argumentLeaves.d.ts +33 -0
- package/dist/esm/integrity/argumentLeaves.js +49 -0
- package/dist/esm/integrity/argumentLeaves.js.map +1 -0
- package/dist/esm/integrity/column-types/check.d.ts +156 -0
- package/dist/esm/integrity/column-types/check.js +363 -0
- package/dist/esm/integrity/column-types/check.js.map +1 -0
- package/dist/esm/integrity/column-types/types.d.ts +121 -0
- package/dist/esm/integrity/column-types/types.js +107 -0
- package/dist/esm/integrity/column-types/types.js.map +1 -0
- package/dist/esm/integrity/disposition/lifecycle.d.ts +31 -1
- package/dist/esm/integrity/disposition/lifecycle.js +54 -1
- package/dist/esm/integrity/disposition/lifecycle.js.map +1 -1
- package/dist/esm/integrity/empty-lookup/check.d.ts +140 -0
- package/dist/esm/integrity/empty-lookup/check.js +212 -0
- package/dist/esm/integrity/empty-lookup/check.js.map +1 -0
- package/dist/esm/integrity/finding/types.d.ts +23 -2
- package/dist/esm/integrity/finding/types.js.map +1 -1
- package/dist/esm/integrity/unsupported-argument/check.js +11 -27
- package/dist/esm/integrity/unsupported-argument/check.js.map +1 -1
- package/dist/esm/lib/mcp/toolExtras.d.ts +17 -2
- package/dist/esm/lib/mcp/toolExtras.js +5 -2
- package/dist/esm/lib/mcp/toolExtras.js.map +1 -1
- package/dist/esm/lib/trace-toolpack/traceToolpack.js +8 -4
- package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/integrity/argumentLeaves.js +54 -0
- package/dist/integrity/argumentLeaves.js.map +1 -0
- package/dist/integrity/column-types/check.js +368 -0
- package/dist/integrity/column-types/check.js.map +1 -0
- package/dist/integrity/column-types/types.js +112 -0
- package/dist/integrity/column-types/types.js.map +1 -0
- package/dist/integrity/disposition/lifecycle.js +54 -1
- package/dist/integrity/disposition/lifecycle.js.map +1 -1
- package/dist/integrity/empty-lookup/check.js +217 -0
- package/dist/integrity/empty-lookup/check.js.map +1 -0
- package/dist/integrity/finding/types.js.map +1 -1
- package/dist/integrity/unsupported-argument/check.js +13 -29
- package/dist/integrity/unsupported-argument/check.js.map +1 -1
- package/dist/lib/mcp/toolExtras.js +4 -1
- package/dist/lib/mcp/toolExtras.js.map +1 -1
- package/dist/lib/trace-toolpack/traceToolpack.js +8 -4
- package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/types/core/Agent.d.ts +10 -0
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/integrityFindings.d.ts +28 -0
- package/dist/types/core/agent/integrityFindings.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts +25 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +43 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +112 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/tools.d.ts +63 -0
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/integrity/argumentLeaves.d.ts +34 -0
- package/dist/types/integrity/argumentLeaves.d.ts.map +1 -0
- package/dist/types/integrity/column-types/check.d.ts +157 -0
- package/dist/types/integrity/column-types/check.d.ts.map +1 -0
- package/dist/types/integrity/column-types/types.d.ts +122 -0
- package/dist/types/integrity/column-types/types.d.ts.map +1 -0
- package/dist/types/integrity/disposition/lifecycle.d.ts +31 -1
- package/dist/types/integrity/disposition/lifecycle.d.ts.map +1 -1
- package/dist/types/integrity/empty-lookup/check.d.ts +141 -0
- package/dist/types/integrity/empty-lookup/check.d.ts.map +1 -0
- package/dist/types/integrity/finding/types.d.ts +23 -2
- package/dist/types/integrity/finding/types.d.ts.map +1 -1
- package/dist/types/integrity/unsupported-argument/check.d.ts.map +1 -1
- package/dist/types/lib/mcp/toolExtras.d.ts +17 -2
- package/dist/types/lib/mcp/toolExtras.d.ts.map +1 -1
- package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -73,6 +73,9 @@ const resultCeiling_js_1 = require("../resultCeiling.js");
|
|
|
73
73
|
const skillSteps_js_1 = require("../../../lib/injection-engine/skillSteps.js");
|
|
74
74
|
const envelope_js_1 = require("../../../lib/semantics/envelope.js");
|
|
75
75
|
const ledger_js_2 = require("../../../integrity/unsupported-claim/ledger.js");
|
|
76
|
+
const check_js_1 = require("../../../integrity/empty-lookup/check.js");
|
|
77
|
+
const check_js_2 = require("../../../integrity/column-types/check.js");
|
|
78
|
+
const integrityFindings_js_1 = require("../integrityFindings.js");
|
|
76
79
|
const index_js_1 = require("../coverage/index.js");
|
|
77
80
|
const toolEffects_js_1 = require("../toolEffects.js");
|
|
78
81
|
/** Declaration order preserved, ids de-duplicated — the shape the gate's re-prompt
|
|
@@ -315,6 +318,73 @@ function buildToolCallsHandler(deps) {
|
|
|
315
318
|
});
|
|
316
319
|
return verdict.refusal;
|
|
317
320
|
};
|
|
321
|
+
/**
|
|
322
|
+
* THE COLUMN-TYPE CONTRACT (9.78.0) — the tool declared what its rows
|
|
323
|
+
* contain, and this is where the rows are.
|
|
324
|
+
*
|
|
325
|
+
* Placed at the SAME execute boundaries as `refuseOverCeiling` and for the
|
|
326
|
+
* same reason: `resultColumns` is the TOOL AUTHOR's contract on the tool's
|
|
327
|
+
* OWN return, so it is judged the moment the handler's value lands, before
|
|
328
|
+
* governance, before placement, before the cap — and a resumed call is
|
|
329
|
+
* judged exactly as an inline one.
|
|
330
|
+
*
|
|
331
|
+
* AFTER the ceiling, deliberately. A payload the model will never read has
|
|
332
|
+
* no columns worth arguing about, and judging one that was already refused
|
|
333
|
+
* would file findings about rows nobody was ever served.
|
|
334
|
+
*
|
|
335
|
+
* `undefined` = nothing declared, nothing to refuse, or `'warn'` — the
|
|
336
|
+
* caller keeps today's path byte for byte. A string is the teaching
|
|
337
|
+
* refusal, which under `'enforce'` replaces the payload on every channel,
|
|
338
|
+
* exactly as the ceiling's does.
|
|
339
|
+
*
|
|
340
|
+
* The three field failures this exists for: LUN 0 stored as an empty string
|
|
341
|
+
* on 2,094 mappings; an 8 MiB disk rendered `0.0 GB`; a whole tool family
|
|
342
|
+
* returning its numbers as quoted strings. This catches the first and the
|
|
343
|
+
* third. It cannot catch the second — that is MEANING, and the ceiling
|
|
344
|
+
* sentence in every finding says so.
|
|
345
|
+
*/
|
|
346
|
+
const judgeColumns = (scope, call, value) => {
|
|
347
|
+
const declarations = deps.columnDeclarations;
|
|
348
|
+
if (declarations === undefined)
|
|
349
|
+
return undefined;
|
|
350
|
+
const columns = declarations.get(call.toolName);
|
|
351
|
+
if (columns === undefined)
|
|
352
|
+
return undefined;
|
|
353
|
+
const { findings, disposition, refusal } = (0, check_js_2.columnTypesOf)({
|
|
354
|
+
toolName: call.toolName,
|
|
355
|
+
toolCallId: call.toolCallId,
|
|
356
|
+
columns,
|
|
357
|
+
reading: (0, check_js_2.readRowset)(value),
|
|
358
|
+
mode: deps.columnCheckMode ?? 'warn',
|
|
359
|
+
}, call.iteration);
|
|
360
|
+
// ONE encounter, TWO rows. The declaration arms both checks and a call
|
|
361
|
+
// meets both at once, so both must answer for it — a shape that is not a
|
|
362
|
+
// rowset is `not-applicable` to each, and a clean rowset is a
|
|
363
|
+
// `checked-pass` for each. Filing one row would leave the other check
|
|
364
|
+
// looking untouched, which is the rot signal, not the truth.
|
|
365
|
+
const ledger = deps.integrityLedger?.current;
|
|
366
|
+
for (const kind of ['column-type-mismatch', 'missing-column']) {
|
|
367
|
+
const kindFired = findings.some((f) => f.kind === kind);
|
|
368
|
+
// A rowset this check could read, where THIS kind found nothing, is a
|
|
369
|
+
// pass for THIS kind even when its sibling failed: the columns really
|
|
370
|
+
// were all present, or really did all hold their declared type.
|
|
371
|
+
const row = disposition === 'not-applicable'
|
|
372
|
+
? 'not-applicable'
|
|
373
|
+
: kindFired
|
|
374
|
+
? 'checked-fail'
|
|
375
|
+
: 'checked-pass';
|
|
376
|
+
ledger?.note(kind, 'write', row, kindFired ? Date.now() : undefined);
|
|
377
|
+
}
|
|
378
|
+
// The findings ARE the record of a refusal: each one names what was
|
|
379
|
+
// refused, which column, how many rows, and — through `outcomeClause` —
|
|
380
|
+
// that the model read a sentence instead of the rows. Deliberately NOT
|
|
381
|
+
// `tools.result_refused`: that event's whole vocabulary is a SIZE
|
|
382
|
+
// (`sizeChars`, `maxChars`), and reusing it here would put a fabricated
|
|
383
|
+
// ceiling on the record to describe a refusal that had nothing to do
|
|
384
|
+
// with size.
|
|
385
|
+
(0, integrityFindings_js_1.fileIntegrityFindings)(scope, findings, call.iteration);
|
|
386
|
+
return refusal;
|
|
387
|
+
};
|
|
318
388
|
/**
|
|
319
389
|
* Coverage declarations — `absent(…)` and `coverage(…)`, recognized at the
|
|
320
390
|
* SAME execute boundaries the ceiling is measured at (one implementation,
|
|
@@ -385,6 +455,75 @@ function buildToolCallsHandler(deps) {
|
|
|
385
455
|
scope.coverageDeclared = [...(scope.coverageDeclared ?? []), ...rows];
|
|
386
456
|
return reading.status;
|
|
387
457
|
};
|
|
458
|
+
/**
|
|
459
|
+
* THE WRITE SEAM (9.77.0) — `empty-lookup`, at the one moment a lookup's
|
|
460
|
+
* answer becomes a fact in the conversation.
|
|
461
|
+
*
|
|
462
|
+
* The recorded failure this exists for: a reverse-lookup tool filtered a
|
|
463
|
+
* column before a pivot, so EVERY lookup returned an empty result, for
|
|
464
|
+
* every identifier, always — and the agent reported, with confidence and in
|
|
465
|
+
* a table, that the device was logged in nowhere. It was logged in the
|
|
466
|
+
* whole time. An empty result from a broken filter is byte-identical to an
|
|
467
|
+
* empty result from a genuine absence, so nothing anywhere could notice.
|
|
468
|
+
*
|
|
469
|
+
* What CAN be noticed is the pair: the run itself produced this identifier
|
|
470
|
+
* (it came out of a result from a tool this one's author named in
|
|
471
|
+
* `argumentsFrom`), and the lookup keyed on it came back empty. The finding
|
|
472
|
+
* is an ADVISORY and says so — an empty answer can be perfectly true, and
|
|
473
|
+
* this cannot tell which one it is looking at.
|
|
474
|
+
*
|
|
475
|
+
* Judged on the TOOL'S OWN answer, before the after-tool chain rewrites it
|
|
476
|
+
* for the model: whether the lookup found anything is a fact about the
|
|
477
|
+
* tool, not about what a governance rule then did with it. A refused,
|
|
478
|
+
* placed or capped result reads as bespoke anyway — a claim ticket has no
|
|
479
|
+
* rows to count.
|
|
480
|
+
*/
|
|
481
|
+
const noticeEmptyLookup = (scope, call, args, result, history,
|
|
482
|
+
/** The call produced a real result to read (ran, no error, nothing refused it). */
|
|
483
|
+
answered) => {
|
|
484
|
+
const grounding = deps.emptyLookupGrounding;
|
|
485
|
+
if (grounding === undefined)
|
|
486
|
+
return;
|
|
487
|
+
const argumentsFrom = grounding.get(call.toolName);
|
|
488
|
+
if (argumentsFrom === undefined)
|
|
489
|
+
return;
|
|
490
|
+
const ledger = deps.integrityLedger?.current;
|
|
491
|
+
// A call that never ran, was denied, errored or had its payload refused
|
|
492
|
+
// produced no lookup result to read. Not a pass, not a fail — the check
|
|
493
|
+
// met its subject and the subject is out of scope BY RULE, which is what
|
|
494
|
+
// `not-applicable` is for. Stated, never silence.
|
|
495
|
+
if (!answered) {
|
|
496
|
+
ledger?.note('empty-lookup', 'write', 'not-applicable');
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// The producer corpus: every earlier `role: 'tool'` message from a tool
|
|
500
|
+
// THIS tool declares as one of its grounds. `history` here excludes the
|
|
501
|
+
// call being judged (it is pushed after), and a producer called earlier
|
|
502
|
+
// in the same batch is already in it — which is right: the model can only
|
|
503
|
+
// have taken a value from a result it had already been served.
|
|
504
|
+
const produced = [];
|
|
505
|
+
for (const message of history) {
|
|
506
|
+
if (message.role !== 'tool')
|
|
507
|
+
continue;
|
|
508
|
+
const name = message.toolName;
|
|
509
|
+
if (typeof name !== 'string' || !argumentsFrom.includes(name))
|
|
510
|
+
continue;
|
|
511
|
+
produced.push({ toolName: name, text: message.content });
|
|
512
|
+
}
|
|
513
|
+
const { findings, disposition } = (0, check_js_1.emptyLookupOf)({
|
|
514
|
+
toolName: call.toolName,
|
|
515
|
+
toolCallId: call.toolCallId,
|
|
516
|
+
args,
|
|
517
|
+
argumentsFrom,
|
|
518
|
+
// `readAbsence` is the ONE owner of the `af_absent` marker; the pure
|
|
519
|
+
// check is handed its verdict rather than re-deriving it, so
|
|
520
|
+
// `src/integrity/` stays a leaf and the reserved word keeps one
|
|
521
|
+
// spelling.
|
|
522
|
+
reading: (0, check_js_1.readLookupResult)(result, (0, index_js_1.readAbsence)(result) !== undefined),
|
|
523
|
+
}, produced, call.iteration);
|
|
524
|
+
ledger?.note('empty-lookup', 'write', disposition, disposition === 'checked-fail' ? Date.now() : undefined);
|
|
525
|
+
(0, integrityFindings_js_1.fileIntegrityFindings)(scope, findings, call.iteration);
|
|
526
|
+
};
|
|
388
527
|
/**
|
|
389
528
|
* The semantic envelope (9.53.0) — recognized at the SAME execute
|
|
390
529
|
* boundaries as coverage and the ceiling (one implementation, every door),
|
|
@@ -1465,6 +1604,22 @@ function buildToolCallsHandler(deps) {
|
|
|
1465
1604
|
envelope: { ...envelope, content: refusal, status: 'invalid' },
|
|
1466
1605
|
};
|
|
1467
1606
|
}
|
|
1607
|
+
// The column-type contract (9.78.0), at the same door and one step
|
|
1608
|
+
// after the ceiling. `'warn'` files and returns undefined — this
|
|
1609
|
+
// path keeps every byte it had.
|
|
1610
|
+
const columnRefusal = judgeColumns(scope, { toolName, toolCallId, iteration }, content);
|
|
1611
|
+
if (columnRefusal !== undefined) {
|
|
1612
|
+
return {
|
|
1613
|
+
result: columnRefusal,
|
|
1614
|
+
executed: true,
|
|
1615
|
+
// The ceiling's flag, reused for the ceiling's reason: a refused
|
|
1616
|
+
// payload must not advance the step pointer on any path, and
|
|
1617
|
+
// there is exactly one fact here — the model did not get the
|
|
1618
|
+
// result — not two spellings of it.
|
|
1619
|
+
ceilingRefused: true,
|
|
1620
|
+
envelope: { ...envelope, content: columnRefusal, status: 'invalid' },
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1468
1623
|
return {
|
|
1469
1624
|
result: content,
|
|
1470
1625
|
executed: true,
|
|
@@ -1496,6 +1651,17 @@ function buildToolCallsHandler(deps) {
|
|
|
1496
1651
|
envelope: { content: refusal, effects: [], status: 'invalid', malformed: [] },
|
|
1497
1652
|
};
|
|
1498
1653
|
}
|
|
1654
|
+
// The column-type contract on this path's own execute boundary — a
|
|
1655
|
+
// resumed call's rows are judged exactly as an inline one's.
|
|
1656
|
+
const columnRefusal = judgeColumns(scope, { toolName, toolCallId, iteration }, result);
|
|
1657
|
+
if (columnRefusal !== undefined) {
|
|
1658
|
+
return {
|
|
1659
|
+
result: columnRefusal,
|
|
1660
|
+
executed: true,
|
|
1661
|
+
ceilingRefused: true,
|
|
1662
|
+
envelope: { content: columnRefusal, effects: [], status: 'invalid', malformed: [] },
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1499
1665
|
// A status-only shape missing its `effects: []` marker is DATA (bytes
|
|
1500
1666
|
// unchanged) — but never silently: name the dropped marker in dev mode.
|
|
1501
1667
|
const nearMiss = (0, toolEffects_js_1.explainStatusOnlyNearMiss)(result);
|
|
@@ -2234,6 +2400,18 @@ function buildToolCallsHandler(deps) {
|
|
|
2234
2400
|
result = overflowRefusal;
|
|
2235
2401
|
toolStatus = 'invalid';
|
|
2236
2402
|
}
|
|
2403
|
+
else {
|
|
2404
|
+
// The column-type contract (9.78.0) — the main batch-loop
|
|
2405
|
+
// door, one step after the ceiling. Only when the payload
|
|
2406
|
+
// survived it: rows nobody will read have no columns worth
|
|
2407
|
+
// arguing about.
|
|
2408
|
+
const columnRefusal = judgeColumns(scope, { toolName: tc.name, toolCallId: tc.id, iteration }, result);
|
|
2409
|
+
if (columnRefusal !== undefined) {
|
|
2410
|
+
ceilingRefused = true;
|
|
2411
|
+
result = columnRefusal;
|
|
2412
|
+
toolStatus = 'invalid';
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2237
2415
|
await endCall(tc.id);
|
|
2238
2416
|
}
|
|
2239
2417
|
catch (err) {
|
|
@@ -2426,6 +2604,12 @@ function buildToolCallsHandler(deps) {
|
|
|
2426
2604
|
// placed: a refusal is already short, and 'tool-result/<name>' must
|
|
2427
2605
|
// never claim an error is the tool's result.
|
|
2428
2606
|
const placedValues = await placeResults(scope, { toolName: tc.name, toolCallId: tc.id, iteration }, { result, modelResult: rawModelResult }, executed && !error && !denied && !ceilingRefused);
|
|
2607
|
+
// The write seam (9.77.0) — judged on `result`, the tool's own answer,
|
|
2608
|
+
// and on `newHistory`, which at this point holds every earlier tool
|
|
2609
|
+
// result and not yet this one. Same guard the placement decision uses:
|
|
2610
|
+
// a call that did not run, errored, was denied or had its payload
|
|
2611
|
+
// refused has no lookup answer to read.
|
|
2612
|
+
noticeEmptyLookup(scope, { toolName: tc.name, toolCallId: tc.id, iteration }, callArgs, result, newHistory, executed && !error && !denied && !ceilingRefused);
|
|
2429
2613
|
// The ceiling, last — after the tool, after the chain. A rule that
|
|
2430
2614
|
// already summarized a huge result is measured on what it produced, so
|
|
2431
2615
|
// the cap composes with governance rather than pre-empting it.
|