agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
1,726 lines • 64.7 kB
JavaScript
/**
* auditShapes — WHAT the audit chain's bounded mode keeps of each event: one
* shape per registered event type, every field of its payload ruled.
*
* Pattern: a declarative table, total over the registry
* (`{ [T in keyof AgentfootprintEventMap]-?: BoundRule }`), built from
* the combinators in `auditBounding.ts`.
* Role: the bounding layer's data. `audit.ts` asks it for every event in
* `payloadMode: 'bounded'`; an event type it does not know is
* `unknownEventShape` — every field a marker.
* Emits: N/A.
*
* A new event type, or a new field on a payload, does not compile until it is
* classified here. Content (what a person, the model, a tool or the data
* wrote, or a message composed from it) is a marker; structure (ids, names,
* kinds, codes, verdicts, counts, the library's own sentences, the words the
* app declared up front) is kept — and every kept value is CHECKED at runtime
* as the kind its type declares: `num`, `bool`, `str` (an open string: an id,
* a name, a label), `oneOf` (a closed union: exactly its words). No container
* is kept whole; each is spelled out field by field, so a child its type does
* not declare is a marker. The type walker
* (`test/type-regressions/AuditBoundingDepth.test.ts`) holds every rule here
* to the type beneath it; the runtime sweep
* (`test/observability-providers/audit-bounded-sweep.test.ts`) hands every rule
* what its kind forbids.
*
* The positions a record keeps although their value may come from the run —
* meta's who, decision evidence, a policy's tag, an app's reason word, a seen
* tool's name — are the rules `auditKeptByContract.ts` names, placed here.
*
* `audit.ts` looks an event's shape up in `eventShapeTable` — a `Map`, so an
* event NAME is never a key into a plain object (`constructor`, `__proto__`).
*/
import { blocksMarker, bool, charsMarker, either, keysMarker, listOf, messagesMarker, nullOr, num, oneOf, orList, recordOf, shapeOf, str, summariesMarker, typeMarker, } from './auditBounding.js';
import { appReasonWord, decisionSummary, declaredValue, metaIdentity, policyReasonTag, routeEvidence, seenToolName, } from './auditKeptByContract.js';
const SCRIPT_LABELS = [
'submitted',
'returned',
'reported-success',
'reported-failure',
'completed',
'completed-with-failure',
'outcome-unknown',
];
/** A submitted program's attached record: only its text is content. */
const boundShownScript = shapeOf({
toolCallId: str,
dispatch: num,
tool: str,
language: str,
label: oneOf(...SCRIPT_LABELS),
exitCode: num,
resultWithheld: oneOf('over-ceiling'),
rewritten: oneOf(true),
bytes: num,
lines: num,
truncated: shapeOf({ shownBytes: num }),
text: charsMarker,
});
/** Attachment summary: preserve every declared field, check every runtime child. */
export const boundScripts = shapeOf({
shown: listOf(boundShownScript),
omitted: num,
closedFence: shapeOf({
char: oneOf('backtick', 'tilde'),
length: num,
}),
withheldFromText: oneOf(true),
});
/** Match verdicts contain labels and references, never the program. */
const boundScriptsVerdict = shapeOf({
blocks: listOf(shapeOf({
block: num,
label: oneOf(...SCRIPT_LABELS, 'unmatched'),
exitCode: num,
toolCallId: str,
tool: str,
dispatch: num,
alsoMatches: num,
reason: oneOf('no-submission-this-turn', 'over-size', 'kept-out'),
})),
earlierTurnRows: num,
regionsDropped: num,
scriptsDropped: num,
});
// ─── Shared pieces: coverage, periods, witnesses ─────────────────────
/** One coverage item: the tool author's prose (`what`, `why`, `short`), and its `kind`. */
const boundCoverageItem = shapeOf({
what: charsMarker,
why: charsMarker,
short: charsMarker,
kind: oneOf('existence', 'scope'),
});
/** What a read found still running: the tool author's prose, and how many things it stands for. */
const boundInProgressItem = shapeOf({
what: charsMarker,
why: charsMarker,
short: charsMarker,
count: num,
});
/** A declared window: both instants are the tool's own values. */
const boundInstants = shapeOf({
from: charsMarker,
to: charsMarker,
});
/** What the store holds — a window, or the library's word `'unknown'` (the tool
* said it cannot vouch for the store), which stays. */
const boundHeld = either(oneOf('unknown'), boundInstants);
/** A declared period: its instants are the tool's values. */
const boundPeriod = shapeOf({
queried: boundInstants,
held: boundHeld,
readAt: charsMarker,
});
/** An absence's source and its clock, as the tool declared them. */
const boundProvenance = shapeOf({
measuredAt: charsMarker,
source: charsMarker,
ageSeconds: num,
sourceExportDate: charsMarker,
});
/**
* What the library composed for a `search` tool. Kept: facets ride BY
* REFERENCE, and a gap's words name arguments and verdicts, never a value
* (`CoverageGapPayload`'s contract) — a `'prose'` gap's words are the ones
* the search declaration states up front.
*/
/** What a gap bears on: a facet word, or the filter and values the search declaration states. */
const boundBearsFilter = shapeOf({
filter: str,
values: listOf(either(str, num, bool)),
});
const boundBears = either(oneOf('completeness', 'period', 'population', 'source'), boundBearsFilter);
const boundComposition = shapeOf({
origin: oneOf('local', 'remote'),
resultId: str,
complete: bool,
facets: listOf(shapeOf({
facet: oneOf('filter', 'names', 'period', 'population', 'source', 'subject'),
from: oneOf('call', 'default', 'host', 'result'),
ref: shapeOf({ resultId: str, argument: str }),
any: bool,
})),
gaps: listOf(shapeOf({
kind: oneOf('argument-unsent', 'cap-reached', 'credential-limited', 'match', 'paged', 'partial', 'period', 'prose', 'ranking', 'scope'),
what: str,
why: str,
bears: boundBears,
argument: str,
})),
});
/**
* A skill guard's evaluation: the edge, the call, the verdict, and per
* condition the key, operator and value the app DECLARED — and the engine's
* summary of the value it read (`actualSummary`), the decision evidence the
* chain keeps by contract (redaction-aware).
*/
const boundGuard = shapeOf({
from: str,
to: str,
toolName: str,
toolCallId: str,
verdict: bool,
conditions: listOf(shapeOf({
key: str,
op: str,
value: orList(declaredValue),
// The engine's decision evidence: a summary of the value a guard read.
actualSummary: decisionSummary,
passed: bool,
})),
});
/** What an integrity finding is about: a kind and an id. */
const boundSubject = shapeOf({ kind: str, id: str });
/** What a message said that won a routing match: the text is the person's; the
* keyword is the app's declared vocabulary. */
const boundWitness = shapeOf({
text: charsMarker,
keyword: str,
});
/**
* A typed answer's limits: the three lists, the declared periods, what a read
* found still running and the values an `assume` rule filled. Every sentence
* and value is a marker; the tool and argument NAMES, the call ids, counts,
* kinds and the library's `'unknown'` stay.
*/
export const boundAnswerCoverage = shapeOf({
checked: listOf(boundCoverageItem),
notChecked: listOf(boundCoverageItem),
cannotCover: listOf(boundCoverageItem),
periods: listOf(shapeOf({
toolName: str,
toolCallId: str,
queried: boundInstants,
held: boundHeld,
readAt: charsMarker,
})),
inProgress: listOf(shapeOf({
toolName: str,
toolCallId: str,
items: listOf(boundInProgressItem),
})),
assumed: listOf(shapeOf({
toolName: str,
argument: str,
value: charsMarker,
hidden: bool,
})),
});
/**
* A typed answer's negatives: each statement and the population it is about
* are markers; the answer field's declared name, the codes, verdicts, ids,
* tool names and counts stay.
*/
export const boundAnswerNegatives = shapeOf({
field: str,
version: str,
delivery: oneOf('as-checked', 'fallback', 'recorded'),
claims: listOf(shapeOf({
kind: oneOf('complete', 'none', 'not-found', 'unknown'),
about: charsMarker,
restsOn: listOf(str),
statement: charsMarker,
delivery: oneOf('record-composed'),
version: str,
})),
checks: listOf(shapeOf({
id: str,
path: str,
index: num,
kind: oneOf('complete', 'none', 'not-found', 'unknown'),
notes: listOf(oneOf('absence-kind-normalized')),
// The payload declares any string: a checker's code.
code: str,
disposition: oneOf('checked-fail', 'not-applicable', 'unreachable'),
tools: listOf(str),
results: listOf(str),
staleSince: shapeOf({
turn: num,
readAt: str,
}),
})),
coverage: listOf(shapeOf({ tool: str, checked: num })),
actions: listOf(shapeOf({
tool: str,
outcome: oneOf('error', 'not-run', 'ok'),
})),
});
/** A shape for one event's whole payload, exhaustive over that event's payload type. */
const eventShape = (rules) => shapeOf(rules);
/** The pause reason the library writes itself — its own words, kept. */
const FIXED_PAUSE_REASON = 'stage requested pause';
/** Why a turn's answer stands where it does — the assessment's own words. */
const boundAssessmentReasons = listOf(oneOf('answer-check-failed', 'argument-asked', 'argument-assumed', 'argument-read', 'argument-unverified', 'asked', 'check-unreachable', 'claim-exceeds-search', 'coverage-gap', 'declaration-overclaimed', 'declared-absent', 'derived-from-reading', 'empty-undeclared', 'negative-prose-unverified', 'period-beyond-retention', 'period-differs-from-asked', 'period-not-held', 'period-partly-held', 'period-undeclared', 'period-unknown', 'script-unmatched', 'sources-conflict', 'steps-unfinished', 'stopped-early', 'value-contingent', 'value-survived-revision', 'value-unsupported'));
/** Which honesty checks ran, and over how much. */
const boundAssessmentChecks = listOf(shapeOf({
layer: oneOf(1, 2, 3, 4),
check: oneOf('answer-checks', 'argument-rules', 'argument-sources', 'names-and-numbers', 'result-period', 'result-shape', 'script-match', 'tool-coverage'),
ran: num,
of: num,
}));
/** A turn's answer assessment: verdict words, reason codes and check counts. */
const boundAnswerAssessment = shapeOf({
assessment: oneOf('known', 'not-applicable', 'unknown', 'unrefuted'),
standing: oneOf('ask', 'consistent', 'known', 'not-assessed', 'not-sure'),
reasons: boundAssessmentReasons,
checked: boundAssessmentChecks,
});
/** One context source's share of a slot: characters and pieces. */
const boundSourceShare = shapeOf({ chars: num, count: num });
/** A slot's share by context source — every source the library declares, by name. */
const boundSourceBreakdown = shapeOf({
assistant: boundSourceShare,
base: boundSourceShare,
custom: boundSourceShare,
'evidence-recovery': boundSourceShare,
fact: boundSourceShare,
findings: boundSourceShare,
instructions: boundSourceShare,
memory: boundSourceShare,
ontology: boundSourceShare,
rag: boundSourceShare,
registry: boundSourceShare,
skill: boundSourceShare,
steering: boundSourceShare,
'tool-result': boundSourceShare,
user: boundSourceShare,
});
const requestReason = oneOf('answered', 'cancelled', 'changes-without-key', 'exhausted', 'no-time-left', 'not-permitted', 'not-replayable', 'not-retryable', 'retryable', 'wait-limit');
const requestFailure = oneOf('auth', 'network', 'permanent', 'rate-limited', 'server', 'timeout', 'unknown');
const requestRefusalKind = oneOf('session-busy', 'throttle');
const requestEffect = oneOf('applied', 'none', 'unknown');
/** A request's error: one of the library's two fixed sentences, and a category — never the error itself. */
const requestError = shapeOf({
message: oneOf('The call ran out of time before an answer arrived.', 'The request failed before an answer arrived. Its error is not kept.'),
code: requestFailure,
});
/** One try of a tool's request: outcome, reason, timing and the library's categories. */
const boundRequestAttempt = shapeOf({
attempt: num,
outcome: oneOf('answered', 'cut', 'failed', 'refused', 'timed-out'),
reason: requestReason,
status: num,
kind: requestRefusalKind,
failure: requestFailure,
waitMs: num,
retryAfterMs: num,
error: requestError,
remote: oneOf('unknown'),
effect: requestEffect,
permission: shapeOf({
by: oneOf('adapter', 'compatibility', 'declaration'),
on: oneOf('network', 'throttle'),
assumes: oneOf('refused-before-execution'),
deduplicated: bool,
}),
durationMs: num,
});
/** How a tool's request ended. */
const boundRequestEnd = shapeOf({
outcome: oneOf('answered', 'cancelled', 'cut', 'failed', 'refused', 'timed-out'),
reason: requestReason,
status: num,
kind: requestRefusalKind,
failure: requestFailure,
during: oneOf('request', 'wait'),
error: requestError,
remote: oneOf('unknown'),
attempts: num,
effect: requestEffect,
mayHaveRun: bool,
});
/**
* Each record's meta: the run and stage ids, paths, indices and engine
* coordinates the dispatcher stamps — and the who the caller named
* (`sessionId`, `principal`, `tenant`), kept by contract. A field `EventMeta`
* does not declare, or a value of another kind, is a marker. (`wallClockMs` is
* the record's `timestamp`; `runId` its run anchor — `audit.ts` lifts both.)
*/
export const boundMeta = shapeOf({
wallClockMs: num,
runOffsetMs: num,
sourcePosition: shapeOf({
engineRunId: str,
logRunId: str,
drillPath: listOf(str),
committedThroughIdx: num,
}),
runtimeStageId: str,
subflowPath: listOf(str),
compositionPath: listOf(str),
turnIndex: num,
iterIndex: num,
traceId: str,
spanId: str,
correlationId: str,
runId: str,
sessionId: metaIdentity,
principal: metaIdentity,
tenant: metaIdentity,
});
/** What a tool returned, as `describedResult()` declared it: the data is content;
* its kinds, field and column names, counts and the library's static note stay. */
const boundSemantics = shapeOf({
af_semantics: bool,
series: listOf(shapeOf({
t: charsMarker,
entity: charsMarker,
metric: str,
value: charsMarker,
})),
// An open record: `entity` and every other value is the data; the keys stay.
facts: listOf(shapeOf({ entity: charsMarker })),
edges: listOf(shapeOf({ from: charsMarker, to: charsMarker, kind: str })),
grain: shapeOf({
interval: str,
aggregation: str,
is_counter: bool,
collapsed: charsMarker,
}),
provenance: shapeOf({
measured_at: charsMarker,
age_seconds: num,
source: charsMarker,
source_export_date: charsMarker,
}),
period: shapeOf({ queried: boundInstants, held: boundHeld, read_at: charsMarker }),
resolved: listOf(shapeOf({
argument: str,
id: charsMarker,
name: charsMarker,
aliases: listOf(charsMarker),
})),
// `null` says there is no next page; a cursor or page number is a value.
paging: shapeOf({ next: nullOr(charsMarker) }),
coverage: shapeOf({
checked: listOf(boundCoverageItem),
not_checked: listOf(boundCoverageItem),
cannot_cover: listOf(boundCoverageItem),
}),
not_covered: listOf(charsMarker),
clarify: nullOr(shapeOf({ question: charsMarker, candidates: listOf(charsMarker) })),
render: shapeOf({
default: str,
columns: listOf(str),
sort: str,
filter_note: charsMarker,
chart_hint: charsMarker,
}),
// "The static sentence. Never interpolated."
note: str,
});
/**
* The whole-event shapes as a `Map`, by event type — what `audit.ts` looks an
* event up in. An event's name is the emitter's to choose (`agent.emit()`
* takes any string), so it is never a key into a plain object: a name
* `Object.prototype` holds (`constructor`, `toString`, `__proto__`) finds no
* shape here, and that event is bounded as unknown — every field a marker.
*/
export function eventShapeTable(toolRan) {
return new Map(Object.entries(eventShapes(toolRan)));
}
/**
* The whole-event shapes, by event type. `toolRan` answers whether this
* strategy has seen a tool of that name run (`createToolRunTracker`): a
* `tryInsteadTool` names another tool, and that name is kept only then —
* otherwise it is the tool author's word for a tool this agent may not hold
* (`otel.ts` · `coverageAttrs`, the same rule).
*/
export function eventShapes(toolRan) {
return {
// ── The seven a tool, the model or the person writes into ──────────
'agentfootprint.tools.absent': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
lookedFor: charsMarker,
checked: listOf(boundCoverageItem),
notChecked: listOf(boundCoverageItem),
cannotCover: listOf(boundCoverageItem),
tryInstead: charsMarker,
tryInsteadTool: shapeOf({
tool: seenToolName(toolRan),
why: charsMarker,
}),
provenance: boundProvenance,
period: boundPeriod,
composition: boundComposition,
lookedForRef: shapeOf({
resultId: str,
field: oneOf('lookedFor'),
}),
}),
'agentfootprint.tools.coverage_declared': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
checked: listOf(boundCoverageItem),
notChecked: listOf(boundCoverageItem),
cannotCover: listOf(boundCoverageItem),
period: boundPeriod,
inProgress: listOf(boundInProgressItem),
composition: boundComposition,
}),
'agentfootprint.tools.semantics_declared': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
semantics: boundSemantics,
}),
'agentfootprint.agent.evidence_checked': eventShape({
iteration: num,
posture: oneOf('assist', 'guard', 'rails'),
candidates: num,
lookedUp: num,
unsupported: listOf(shapeOf({
value: charsMarker,
shape: str,
region: oneOf('prose', 'code'),
})),
action: oneOf('flagged', 'grounded', 'refused', 'revision-asked'),
afterRevision: bool,
evidenceTruncated: bool,
carriedBy: listOf(shapeOf({
toolCallId: str,
values: num,
only: num,
})),
stagedRefs: listOf(shapeOf({
ref: str,
kind: str,
})),
spenderTools: listOf(str),
// `from` names the operands — and a unit-scaled figure's source value.
computed: listOf(shapeOf({
value: charsMarker,
shape: str,
derivation: str,
from: charsMarker,
})),
scripts: boundScriptsVerdict,
}),
'agentfootprint.integrity.external_ground_used': eventShape({
toolName: str,
toolCallId: str,
path: str,
value: charsMarker,
source: str,
iteration: num,
}),
'agentfootprint.map.engaged': eventShape({
mapId: str,
iteration: num,
by: oneOf('assumed', 'explicit', 'lexical', 'semantic', 'structural'),
witness: charsMarker,
reengaged: bool,
upgraded: bool,
foundedBy: oneOf('assumed', 'explicit', 'lexical', 'semantic', 'structural'),
tenantChanged: bool,
at: str,
}),
'agentfootprint.skill.turn_routed': eventShape({
by: oneOf('continuity', 'decider', 'entry', 'intent', 'menu', 'none'),
from: str,
to: str,
scorer: str,
scores: listOf(shapeOf({
id: str,
score: num,
relevance: num,
})),
runnerUp: shapeOf({
id: str,
gap: num,
}),
decisive: bool,
witness: boundWitness,
offered: listOf(str),
stayOffered: bool,
policy: shapeOf({
nearTieMargin: num,
menuSize: num,
floor: num,
}),
window: num,
droppedResume: shapeOf({
id: str,
reason: oneOf('unknown-skill'),
}),
decider: shapeOf({
provider: str,
model: str,
picked: str,
}),
}),
// ── The same rule, everywhere else the run's words ride ────────────
'agentfootprint.map.parked': eventShape({
mapId: str,
iteration: num,
by: oneOf('assumed', 'explicit', 'lexical', 'semantic', 'structural'),
idleCalls: num,
witness: charsMarker,
}),
// A guard's conditions are the engine's decision evidence (kept, see audit.ts).
'agentfootprint.context.evaluated': eventShape({
iteration: num,
activeCount: num,
skippedCount: num,
evaluatedTotal: num,
activeIds: listOf(str),
skippedDetails: listOf(shapeOf({
id: str,
reason: oneOf('hidden', 'parked', 'predicate-threw', 'unknown-fact', 'unknown-trigger-kind'),
error: charsMarker,
})),
triggerKindCounts: recordOf(num),
// The catalog and the routing provenance are what the app declared.
skillCatalog: listOf(shapeOf({
id: str,
description: str,
})),
routing: listOf(shapeOf({
injectionId: str,
flavor: str,
via: str,
path: listOf(shapeOf({ label: str, branch: str })),
label: str,
from: str,
triggerKind: str,
tools: listOf(str),
})),
cursorMove: shapeOf({
from: str,
to: str,
by: str,
offered: listOf(str),
declinedOffer: bool,
witness: boundWitness,
guard: boundGuard,
guardsClosed: listOf(boundGuard),
reachable: listOf(str),
}),
supersededIds: listOf(str),
}),
'agentfootprint.validation.args_invalid': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
issues: listOf(shapeOf({
path: str,
expected: str,
got: str,
value: charsMarker,
hint: str,
})),
enforced: bool,
}),
'agentfootprint.agent.output_schema_validation_failed': eventShape({
message: charsMarker,
stage: oneOf('json-parse', 'schema-validate'),
path: str,
rawOutput: charsMarker,
draftWithheld: bool,
attempt: num,
cumulativeRetries: num,
}),
'agentfootprint.resilience.output_fallback_triggered': eventShape({
stage: oneOf('json-parse', 'schema-validate'),
rawOutputPreview: charsMarker,
primaryErrorMessage: charsMarker,
retriesSpent: num,
}),
'agentfootprint.resilience.output_canned_used': eventShape({
rawOutputPreview: charsMarker,
fallbackErrorMessage: charsMarker,
retriesSpent: num,
}),
'agentfootprint.stream.tool_progress': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
payload: keysMarker,
}),
'agentfootprint.checkin.request': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
request: keysMarker,
}),
'agentfootprint.checkin.decision': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
requestId: str,
approved: bool,
by: str,
note: charsMarker,
componentId: str,
}),
'agentfootprint.middleware.decision': eventShape({
middleware: str,
moment: oneOf('after-tool', 'before-tool', 'input', 'output', 'window'),
at: oneOf('message', 'tool'),
phase: oneOf('input', 'output'),
toolName: str,
toolCallId: str,
iteration: num,
outcome: oneOf('allow', 'ask', 'deny'),
changed: bool,
why: charsMarker,
componentId: str,
}),
'agentfootprint.skill.step_skipped': eventShape({
skillId: str,
// The step the app declared — its tool and note.
step: shapeOf({
index: num,
total: num,
tool: str,
note: str,
}),
reason: charsMarker,
policy: oneOf('advance', 'hold'),
iteration: num,
toolCallId: str,
}),
'agentfootprint.stream.llm_start': eventShape({
iteration: num,
provider: str,
model: str,
systemPromptChars: num,
systemPromptText: charsMarker,
messagesCount: num,
toolsCount: num,
// The catalog the model saw: names and the descriptions the tools declared.
tools: listOf(shapeOf({
name: str,
description: str,
})),
estimatedPromptTokens: num,
temperature: num,
providerRequestRef: str,
brain: shapeOf({
via: oneOf('escalation', 'skill'),
skillId: str,
}),
}),
'agentfootprint.credential.failed': eventShape({
service: str,
reason: charsMarker,
tool: str,
errorClass: str,
toolCallId: str,
iteration: num,
}),
'agentfootprint.fallback.triggered': eventShape({
kind: oneOf('provider', 'skill', 'tool'),
primary: str,
fallback: str,
reason: charsMarker,
}),
'agentfootprint.memory.retrieved': eventShape({
strategy: str,
queryHash: str,
k: num,
threshold: num,
maxChars: num,
charsUsed: num,
embedderId: str,
dimensions: num,
consideredCount: num,
admittedCount: num,
rejectedCount: num,
candidates: listOf(shapeOf({
id: str,
score: num,
rank: num,
admitted: bool,
reason: oneOf('below-threshold', 'over-budget', 'over-char-budget', 'over-max-entries'),
docUri: str,
page: num,
heading: charsMarker,
})),
candidatesComplete: bool,
candidatesOmittedReason: str,
corpusEmpty: bool,
namespace: str,
}),
'agentfootprint.integrity.context_error': eventShape({
kind: oneOf('column-type-mismatch', 'dangling-reference', 'duplicate-execution', 'empty-lookup', 'invariant-violation', 'missing-column', 'prior-turn-evidence', 'unsupported-argument', 'unsupported-claim'),
seam: oneOf('choice', 'claim', 'compose', 'wire', 'write'),
subjects: listOf(boundSubject),
witnesses: listOf(shapeOf({
subject: boundSubject,
predicate: str,
value: charsMarker,
epoch: num,
stratum: oneOf('asserted', 'quoted'),
provenance: charsMarker,
runtimeStageId: str,
synthetic: bool,
})),
predicate: str,
epoch: num,
synthetic: bool,
advisory: bool,
message: charsMarker,
iteration: num,
}),
'agentfootprint.tools.effect': eventShape({
kind: oneOf('propose-transition', 'require-instruction'),
outcome: oneOf('accepted', 'refused', 'superseded'),
stay: bool,
toolName: str,
toolCallId: str,
iteration: num,
targetSkillId: str,
reason: charsMarker,
instructionId: str,
deliveryLease: oneOf('next-call', 'until-skill-exit'),
refusalReason: str,
supersededBy: oneOf('earlier-proposal'),
}),
// `reason` is `pauseData.reason` — the same words `questionPayload` hides.
'agentfootprint.pause.request': eventShape({
// The library's own pause sentence stays; a pause's own reason is its data.
reason: oneOf(FIXED_PAUSE_REASON),
questionPayload: keysMarker,
}),
'agentfootprint.artifacts.minted': eventShape({
ref: str,
kind: str,
mediaType: str,
bytes: num,
label: charsMarker,
digest: str,
expiresAt: num,
origin: shapeOf({
runId: str,
toolCallId: str,
}),
parentRefs: listOf(str),
// The column, zone and interval the rows declare.
timeAxis: shapeOf({
column: str,
unit: oneOf('epoch-ms', 'epoch-s', 'iso'),
zone: str,
interval: str,
// One aggregate for every column, or one per column.
aggregate: either(oneOf('avg', 'count', 'last', 'max', 'min', 'raw', 'sum'), recordOf(oneOf('avg', 'count', 'last', 'max', 'min', 'sum'))),
}),
tool: str,
}),
'agentfootprint.artifacts.presented': eventShape({
ref: str,
as: str,
snapshot: shapeOf({
kind: str,
mediaType: str,
bytes: num,
label: charsMarker,
}),
toolCallId: str,
iteration: num,
}),
'agentfootprint.artifacts.refused': eventShape({
op: oneOf('delete', 'dispatch', 'get', 'head', 'list', 'put'),
reason: oneOf('digest-mismatch', 'invalid-input', 'kind-mismatch', 'missing-or-expired', 'no-store', 'unknown-parent'),
ref: str,
detail: charsMarker,
tool: str,
}),
'agentfootprint.reliability.fail_fast': eventShape({
phase: oneOf('post-decide', 'pre-check'),
kind: str,
attempt: num,
label: str,
reason: charsMarker,
providerUsed: str,
errorKind: str,
errorMessage: charsMarker,
}),
'agentfootprint.agent.handoff': eventShape({
fromAgentId: str,
toAgentId: str,
reason: charsMarker,
viaProtocol: oneOf('http', 'mcp', 'native'),
}),
// A policy's `reason` is its telemetry tag; its `rationale` is prose per decision.
'agentfootprint.permission.check': eventShape({
capability: oneOf('external_net', 'memory_read', 'memory_write', 'skill_read', 'tool_call', 'user_data'),
actor: str,
target: str,
result: oneOf('allow', 'deny', 'gate_open', 'halt'),
policyEngine: oneOf('cerbos', 'custom', 'opa'),
policyRuleId: str,
rationale: charsMarker,
reason: policyReasonTag,
toolCallId: str,
iteration: num,
}),
// `tellLLM` is the tool result the model read in place of the call.
'agentfootprint.permission.halt': eventShape({
checkerId: str,
target: str,
reason: policyReasonTag,
tellLLM: charsMarker,
iteration: num,
sequenceLength: num,
toolCallId: str,
}),
// A router's `{ reason }` is the routing model's own words; `decide()`
// evidence is the engine's, kept (see audit.ts).
'agentfootprint.composition.route_decided': eventShape({
conditionalId: str,
chosen: str,
rationale: str,
evidence: routeEvidence,
}),
// ── Every other event: structure, and the fields bounded whole ─────
'agentfootprint.composition.enter': eventShape({
kind: oneOf('Conditional', 'Loop', 'Parallel', 'Sequence'),
id: str,
name: str,
childCount: num,
}),
'agentfootprint.composition.exit': eventShape({
kind: oneOf('Conditional', 'Loop', 'Parallel', 'Sequence'),
id: str,
name: str,
status: oneOf('break', 'budget_exhausted', 'err', 'ok'),
durationMs: num,
}),
'agentfootprint.composition.fork_start': eventShape({
parentId: str,
branches: listOf(shapeOf({
id: str,
name: str,
})),
}),
'agentfootprint.composition.branch_complete': eventShape({
parentId: str,
branchId: str,
status: oneOf('err', 'ok'),
durationMs: num,
}),
'agentfootprint.composition.merge_end': eventShape({
parentId: str,
strategy: oneOf('fn', 'llm', 'outcomes-fn'),
resultSummary: charsMarker,
mergedBranchCount: num,
totalBranchCount: num,
}),
'agentfootprint.composition.iteration_start': eventShape({
loopId: str,
iteration: num,
}),
'agentfootprint.composition.iteration_exit': eventShape({
loopId: str,
iteration: num,
reason: oneOf('body_complete', 'break', 'budget', 'guard_false'),
}),
'agentfootprint.agent.turn_start': eventShape({
turnIndex: num,
userPrompt: charsMarker,
}),
'agentfootprint.agent.turn_end': eventShape({
turnIndex: num,
finalContent: charsMarker,
totalInputTokens: num,
totalOutputTokens: num,
iterationCount: num,
durationMs: num,
stoppedEarly: shapeOf({
reason: oneOf('cost-budget', 'max-iterations'),
iteration: num,
pendingToolCalls: num,
wrappedUp: bool,
}),
answerCoverage: boundAnswerCoverage,
answerAssessment: boundAnswerAssessment,
standingLineNames: recordOf(str),
answerNegatives: boundAnswerNegatives,
scripts: boundScripts,
refused: shapeOf({
by: oneOf('evidence-rails'),
}),
}),
'agentfootprint.agent.iteration_start': eventShape({
turnIndex: num,
iterIndex: num,
}),
'agentfootprint.agent.iteration_end': eventShape({
turnIndex: num,
iterIndex: num,
toolCallCount: num,
history: messagesMarker,
}),
'agentfootprint.agent.route_decided': eventShape({
turnIndex: num,
iterIndex: num,
chosen: oneOf('evidence-recheck', 'final', 'negative-recheck', 'output-retry', 'step-nudge', 'tool-calls', 'wrap-up'),
// A fixed sentence, or one the library composes (a count, a skill's name).
rationale: str,
}),
'agentfootprint.agent.output_contract_unmet': eventShape({
stage: oneOf('json-parse', 'schema-validate'),
error: charsMarker,
path: str,
attempts: num,
retriesSpent: num,
fallbackConfigured: bool,
iteration: num,
brokenBy: str,
}),
'agentfootprint.agent.output_schema_retry': eventShape({
attempt: num,
retriesRemaining: num,
iteration: num,
stage: oneOf('json-parse', 'schema-validate'),
error: charsMarker,
path: str,
correctiveMessageHash: str,
}),
'agentfootprint.agent.grounding_nudged': eventShape({
iteration: num,
refs: listOf(shapeOf({
ref: str,
kind: str,
})),
refsOmitted: num,
tools: listOf(str),
}),
'agentfootprint.agent.run_configured': eventShape({
agentId: str,
llm: shapeOf({
provider: str,
model: str,
modelOverrides: listOf(oneOf('configure', 'skill-brains')),
}),
cache: shapeOf({
requested: oneOf('default', 'explicit'),
strategy: oneOf('none'),
status: oneOf('not-applicable'),
}),
reactMode: oneOf('classic', 'dynamic', 'dynamic-grouped'),
memories: listOf(shapeOf({
id: str,
type: oneOf('causal', 'episodic', 'narrative', 'semantic'),
strategy: oneOf('budget', 'decay', 'extract', 'hybrid', 'summarize', 'topK', 'window'),
retrieval: str,
embedderId: str,
flavor: oneOf('memory', 'rag'),
})),
window: str,
skillGraph: shapeOf({
routing: oneOf('assist', 'guard', 'rails'),
continuity: oneOf('conversation', 'turn'),
scorer: str,
}),
evidenceGate: oneOf('assist', 'guard', 'rails'),
artifacts: shapeOf({
placement: bool,
recordings: bool,
}),
recipes: listOf(shapeOf({
id: str,
version: str,
})),
}),
'agentfootprint.agent.thinking_parse_failed': eventShape({
providerName: str,
subflowId: str,
error: charsMarker,
errorName: str,
iteration: num,
}),
'agentfootprint.agent.thinking_omitted': eventShape({
providerName: str,
model: str,
messageIndex: num,
blockIndex: num,
reason: oneOf('content-changed', 'missing-signature', 'prefix-changed', 'sequence-changed', 'thinking-retired'),
phase: oneOf('prepared'),
}),
'agentfootprint.agent.budget_exhausted': eventShape({
reason: oneOf('cost-budget', 'max-iterations'),
iteration: num,
limit: num,
pendingToolCalls: num,
action: oneOf('cut-short', 'wrapped-up'),
}),
'agentfootprint.stream.llm_end': eventShape({
iteration: num,
content: charsMarker,
contentWithheld: bool,
toolCallCount: num,
// A provider's counts. Its usage object can carry more than these (structural
// typing lets it): a child the type does not declare is a marker.
usage: shapeOf({
input: num,
output: num,
cacheRead: num,
cacheWrite: num,
thinking: num,
}),
stopReason: str,
durationMs: num,
providerResponseRef: str,
}),
'agentfootprint.stream.token': eventShape({
iteration: num,
tokenIndex: num,
content: charsMarker,
}),
'agentfootprint.stream.tool_start': eventShape({
toolName: str,
toolCallId: str,
args: keysMarker,
parallelCount: num,
protocol: oneOf('http', 'mcp', 'native', 'python-fn'),
notDispatched: shapeOf({
pausedCall: shapeOf({
toolCallId: str,
toolName: str,
}),
}),
}),
'agentfootprint.stream.tool_end': eventShape({
toolCallId: str,
result: typeMarker,
error: bool,
durationMs: num,
status: oneOf('absent', 'denied', 'failure', 'invalid', 'partial', 'pending', 'success'),
notDispatched: shapeOf({
pausedCall: shapeOf({
toolCallId: str,
toolName: str,
}),
}),
modelResult: typeMarker,
changedArgKeys: listOf(str),
notExecuted: bool,
}),
'agentfootprint.stream.thinking_delta': eventShape({
iteration: num,
tokenIndex: num,
content: charsMarker,
}),
'agentfootprint.stream.thinking_end': eventShape({
iteration: num,
blockCount: num,
totalChars: num,
tokens: num,
blocks: blocksMarker,
}),
'agentfootprint.context.injected': eventShape({
contentSummary: charsMarker,
contentHash: str,
rawContent: charsMarker,
slot: oneOf('messages', 'system-prompt', 'tools'),
asRole: oneOf('assistant', 'system', 'tool', 'user'),
asRecency: oneOf('earlier', 'latest'),
position: num,
sectionTag: str,
source: oneOf('assistant', 'base', 'custom', 'evidence-recovery', 'fact', 'findings', 'instructions', 'memory', 'ontology', 'rag', 'registry', 'skill', 'steering', 'tool-result', 'user'),
sourceId: str,
upstreamRef: str,
reason: str,
retrievalScore: num,
rankPosition: num,
threshold: num,
budgetSpent: shapeOf({
tokens: num,
fractionOfCap: num,
}),
expiresAfter: oneOf('iteration', 'persistent', 'run', 'turn'),
}),
'agentfootprint.context.evicted': eventShape({
slot: oneOf('messages', 'system-prompt', 'tools'),
contentHash: str,
reason: oneOf('budget', 'low_score', 'policy', 'stale', 'user_revoked'),
survivalMs: num,
}),
'agentfootprint.context.slot_composed': eventShape({
slot: oneOf('messages', 'system-prompt', 'tools'),
iteration: num,
budget: shapeOf({
cap: num,
used: num,
headroomChars: num,
}),
sourceBreakdown: boundSourceBreakdown,
orderingStrategy: str,
droppedCount: num,
droppedSummaries: summariesMarker,
}),
'agentfootprint.context.budget_pressure': eventShape({
slot: oneOf('messages', 'system-prompt', 'tools'),
overflowBy: num,
planAction: oneOf('abort', 'evict', 'none', 'summarize'),
unit: oneOf('chars', 'tokens'),
cap: num,
projected: num,
}),
'agentfootprint.memory.strategy_applied': eventShape({
strategyId: str,
strategyKind: oneOf('fact-extraction', 'hybrid', 'semantic', 'sliding-window', 'summarizing'),
reason: str,
scoreEvidence: keysMarker,
inputMemoryCount: num,
outputMemoryCount: num,
droppedIds: listOf(str),
addedIds: listOf(str),
}),
'agentfootprint.memory.attached': eventShape({
memoryId: str,
contentSummary: charsMarker,
score: num,
rank: num,
source: oneOf('auto-extract', 'manual', 'store'),
retriever: oneOf('chroma', 'custom', 'pinecone', 'qdrant', 'weaviate'),
}),
'agentfootprint.memory.detached': eventShape({
memoryId: str,
reason: oneOf('budget', 'policy', 'score_low', 'stale'),
}),
'agentfootprint.memory.written': eventShape({
memoryId: str,
contentSummary: charsMarker,
source: oneOf('auto', 'manual'),
actor: str,
}),
'agentfootprint.tools.offered': eventShape({
availableIds: listOf(str),
withheldIds: listOf(str),
withheldReasons: recordOf(oneOf('cost_guard', 'gated', 'permission', 'skill_inactive')),
reason: appReasonWord,
}),
'agentfootprint.tools.activated': eventShape({
toolId: str,
reason: oneOf('autoActivate', 'permission_granted', 'skill_activated'),
source: str,
}),
'agentfootprint.tools.deactivated': eventShape({
toolId: str,
reason: oneOf('permission_revoked', 'skill_deactivated'),
}),
'agentfootprint.tools.discovery_started': eventShape({
providerId: str,
iteration: num,
}),
'agentfootprint.tools.discovery_completed': eventShape({
providerId: str,
iteration: num,
durationMs: num,
toolCount: num,
}),
'agentfootprint.tools.discovery_failed': eventShape({
providerId: str,
error: charsMarker,
errorName: str,
iteration: num,
durationMs: num,
}),
'agentfootprint.tools.shadowed': eventShape({
toolName: str,
iteration: num,
schemaFrom: oneOf('framework', 'provider', 'registry', 'skill'),
schemaFromId: str,
dispatchTo: oneOf('framework', 'provider', 'registry', 'skill'),
dispatchToId: str,
}),
'agentfootprint.tools.claim_swallowed': eventShape({
toolName: str,
iteration: num,
lostBy: oneOf('framework', 'provider', 'registry', 'skill'),
lostById: str,
wonBy: oneOf('framework', 'provider', 'registry', 'skill'),
wonById: str,
}),
'agentfootprint.tools.answered_off_wire': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
answeredBy: oneOf('framework', 'provider', 'registry', 'skill'),
answeredById: str,
}),
'agentfootprint.tools.session_started': eventShape({
tool: str,
scope: oneOf('call', 'run', 'session', 'shutdown'),
keyHash: str,
runnerId: str,
label: str,
}),
'agentfootprint.tools.session_reused': eventShape({
calls: num,
tool: str,
scope: oneOf('call', 'run', 'session', 'shutdown'),
keyHash: str,
runnerId: str,
label: str,
}),
'agentfootprint.tools.session_closed': eventShape({
reason: oneOf('call-end', 'evicted', 'idle', 'run-end', 'session-end', 'shutdown'),
durationMs: num,
tool: str,
scope: oneOf('call', 'run', 'session', 'shutdown'),
keyHash: str,
runnerId: str,
label: str,
}),
'agentfootprint.tools.result_refused': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
sizeChars: num,
maxChars: num,
narrowBy: listOf(str),
declaredStatus: oneOf('absent', 'denied', 'failure', 'invalid', 'partial', 'pending', 'success'),
}),
'agentfootprint.tools.repeated_call': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
occurrences: num,
argsFingerprint: str,
resultFingerprint: str,
mode: oneOf('arguments'),
}),
'agentfootprint.tools.code_run': eventShape({
tool: str,
language: str,
stagedInputs: num,
outputChars: num,
truncated: bool,
ok: bool,
exitCode: num,
serviceError: bool,
terminatedBy: str,
shapeHash: str,
}),
// One use of an MCP client pool: "ids, digests, evidence and outcomes only" —
// never an identity value, a session handle, an argument, a result or a server's text.
'agentfootprint.tools.mcp_client': eventShape({
server: str,
at: oneOf('call', 'list'),
toolCallId: str,
keyHash: str,
clientId: str,
generation: num,
client: oneOf('expired', 'handle-lost', 'joined', 'not-needed', 'opened', 'refused', 'reused'),
previous: oneOf('evicted', 'expired', 'handle-lost', 'idle', 'terminated'),
evidence: oneOf('server-404', 'transport-forgot-handle'),
refusal: oneOf('binding-changed', 'closed', 'ending-full', 'identity-mismatch', 'incomplete-identity', 'init-failed', 'init-timeout', 'lease-expired', 'no-identity', 'operations-full', 'pool-full', 'principal-full', 'request-unmatched', 'stale-tools'),
initMs: num,
definitions: oneOf('listed', 'shared'),
definitionsAgeMs: num,
revalidated: oneOf('kept', 'refused'),
}),
'agentfootprint.tools.request_attempts': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
endpoint: str,
origin: str,
attempts: listOf(boundRequestAttempt),
omitted: num,
end: boundRequestEnd,
}),
'agentfootprint.tools.session_close_failed': eventShape({
reason: oneOf('call-end', 'evicted', 'idle', 'run-end', 'session-end', 'shutdown'),
durationMs: num,
error: charsMarker,
errorClass: str,
tool: str,
scope: oneOf('call', 'run', 'session', 'shutdown'),
keyHash: str,
runnerId: str,
label: str,
}),
'agentfootprint.skill.activated': eventShape({
skillId: str,
reason: oneOf('autoActivate', 'manual', 'read_skill_result'),
injectedTools: listOf(str),
injectedSystemPromptChars: num,
}),
'agentfootprint.skill.graph_declared': eventShape({
nodes: listOf(shapeOf({
id: str,
kind: str,
description: str,
label: str,
title: str,
})),
edges: listOf(shapeOf({
from: nullOr(str),
to: str,
kind: str,
label: str,
guard: shapeOf({
conditions: listOf(shapeOf({
key: str,
op: str,
// The value the app declared to compare against: one, or a list.
value: orList(declaredValue),
})),
}),
})),
}),
'agentfootprint.skill.deactivated': eventShape({
skillId: str,
reason: appReasonWord,
}),
'agentfootprint.skill.rejected': eventShape({
requestedId: str,
currentSkillId: str,
allowed: listOf(str),
iteration: num,
posture: oneOf('guard', 'rails'),
reason: oneOf('posture', 'self-call', 'unreachable'),
}),
'agentfootprint.skill.reroute_superseded': eventShape({
volunteeredId: str,
wonId: str,
fromSkillId: str,
iteration: num,
source: oneOf('tool-proposal'),
}),
'agentfootprint.skill.route_conflict': eventShape({
iteration: num,
fromSkillId: str,
winner: shapeOf({
toolCallId: str,
toolName: str,
target: str,
}),
losers: listOf(shapeOf({
toolCallId: str,
toolName: str,
target: str,
})),
source: oneOf('tool-proposal'),
}),
'agentfootprint.skill.step_advanced': eventShape({
skillId: str,
step: shapeOf({
index: num,
total: num,
tool: str,
note: str,
}),
iteration: num,
toolCallId: str,
completed: bool,
}),
'agentfootprint.skill.steps_unfinished': eventShape({
skillId: str,
remaining: listOf(shapeOf({
index: num,
tool: str,
note: str,
})),
total: num,
action: oneOf('accepted', 'cut-short', 'nudged'),
iteration: num,
}),
'agentfootprint.skill.escalated': eventShape({
iteration: num,
afterRefusals: num,
refusals: num,
from: shapeOf({
provider: str,
model: str,
}),
to: shapeOf({
provider: str,
model: str,
}),
}),
'agentfootprint.permission.gate_opened': eventShape({
gateId: str,
openedBy: str,
expiresAt: num,
}),
'agentfootprint.permission.gate_closed': eventShape({
gateId: str,
reason: appReasonWord,
}),
'agentfootprint.credential.requested': eventShape({
service: str,
mode: oneOf('machine', 'user'),
toolCallId: str,
iteration: num,
}),
'agentfootprint.credential.acquired': eventShape({
service: str,
kind: str,
expiresAt: num,
toolCallId: str,
iteration: num,
}),
'agentfootprint.credential.authorization_required': eventShape({
service: str,
sessionId: str,
toolCallId: str,
iteration: num,
}),
'agentfootprint.cost.tick': eventShape({
scope: oneOf('iteration', 'run', 'turn'),
model: str,
provider: str,
tokensInput: num,
tokensOutput: num,
estimatedUsd: num,
cumulative: shapeOf({
tokensInput: num,
tokensOutput: num,
estimatedUsd: num,
}),
}),
'agentfootprint.cost.limit_hit': eventShape({
kind: oneOf('max_cost', 'max_iterations', 'max_tokens', 'max_wallclock'),
limit: num,
actual: num,
action: oneOf('abort', 'degrade', 'warn'),
}),
'agentfootprint.eval.score': eventShape({
metricId: str,
value: num,
threshold: num,
target: oneOf('iteration', 'run', 'toolCall', 'turn'),
targetRef: str,
evaluator: oneOf('fn', 'heuristic', 'llm'),
evidence: keysMarker,
label: str,
explanation: charsMarker,
}),
'agentfootprint.eval.threshold_crossed': eventShape({
metricId: str,
direction: oneOf('above', 'below'),
value: num,
threshold: num,
actionTaken: str,
}),
'agentfootprint.error.retried': eventShape({
attempt: num,
maxAttempts: num,
lastError: charsMarker,
backoffMs: num,
reason: str,
statedWaitMs: num,
}),
'agentfootprint.error.recovered': eventShape({
attempt: num,
totalDurationMs: num,
}),
'agentfootprint.error.fatal': eventShape({
error: charsMarker,
stage: str,
scope: str,
}),
'agentfootprint.error.circuit_changed': eventShape({
state: oneOf('closed', 'half-open', 'open'),
reason: str,
providerName: str,
}),
'agentfootprint.reliability.retried': eventShape({
attempt: num,
action: oneOf('retry', 'retry-other'),
errorKind: str,
errorMessage: charsMarker,
fromProvider: str,
toProvider: str,
}),
'agentfootprint.reliability.recovered': eventShape({
attempt: num,
recoveredVia: oneOf('fallback', 'retry', 'retry-other'),
priorFailures: num,
errorKind: str,
}),
'agentfootprint.pause.resume': eventShape({
resumeInput: keysMarker,
pausedDurationMs: num,
componentId: str,
}),
'agentfootprint.findings.declared': eventShape({
toolName: str,
toolCallId: str,
iteration: num,
basis: oneOf('direct', 'exploratory'),
expect: oneOf('high', 'low', 'medium'),
hasProposition: bool,
malformed: num,
}),
'agentfootprint.findings.standing': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
standing: oneOf('fact', 'noise', 'open', 'ruled-out'),
declaredOn: oneOf('answer', 'tool-call'),
assertionCount: num,
conflictKeys: listOf(str),
unknownId: bool,
agrees: bool,
}),
'agentfootprint.findings.judged': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
against: oneOf('proposition', 'question'),
standing: oneOf('fact', 'noise', 'open', 'ruled-out'),
confidence: num,
latencyMs: num,
inputTokens: num,
outputTokens: num,
}),
'agentfootprint.findings.judge_failed': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
status: num,
latencyMs: num,
}),
'agentfootprint.findings.contingent': eventShape({
iteration: num,
declaredOn: oneOf('answer', 'tool-call'),
toolCallId: str,
carriers: num,
standings: listOf(oneOf('fact', 'noise', 'open', 'ruled-out')),
valueChars: num,
}),
'agentfootprint.findings.argument': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
turn: num,
argument: str,
rule: oneOf('ask', 'assume'),
period: bool,
source: oneOf('answered', 'app', 'default', 'model', 'result', 'said'),
asked: oneOf('invalid-answer', 'missing', 'unverified'),
claimed: oneOf('app', 'assumed', 'none', 'result', 'turn', 'user'),
matched: oneOf('mention', 'phrase', 'quote', 'spelling'),
reading: bool,
earlier: bool,
setAside: oneOf('noise', 'open', 'ruled-out'),
argumentsFrom: oneOf('listed', 'unlisted'),
coincides: oneOf('app', 'person', 'result'),
free: bool,
failed: oneOf('composed-message', 'no-earlier-turn', 'not-in-app-text', 'not-in-earlier-turns', 'not-in-result', 'only-in-model-answer', 'placed-result', 'quote-not-found', 'uncheckable', 'unknown-result'),
malformed: num,
valueChars: num,
}),
'agentfootprint.findings.period': eventShape({
toolCallId: str,
toolName: str,
iteration: num,
turn: num,
verdict: oneOf('covered', 'not-held', 'partly-held', 'undeclared', 'unknown'),
timeChecks: listOf(oneOf('partly-beyond-retention', 'period-beyond-retention', 'period-differs-from-asked', 'period-shifted')),
}),
'agentfootprint.findings.negative_claim': eventShape({
iteration: num,
turn: num,
field: str,
span: shapeOf({
start: num,
end: num,
}),
packVersion: str,
phraseId: str,
truncated: bool,
kind: oneOf('negative-claim', 'negative-claim-note'),
// A claim row's checker codes and native result ids; a note row's code.
claim: oneOf('complete', 'none'),
notes: listOf(str),
results: listOf(str),
code: str,
}),
'agentfootprint.tool_choice.picked': eventShape({
iteration: num,
chosen: str,
confidence: num,
offered: num,
served: num,
narrowed: bool,
narrowedSkipped: oneOf('after-miss', 'evidence-revision', 'too-few', 'unavailable', 'wrap-up'),
latencyMs: num,
inputTokens: num,
outputTokens: num,
}),
'agentfootprint.tool_choice.outcome': eventShape({
iteration: num,
called: listOf(str),
firstAgrees: bool,
missed: listOf(str),
}),
'agentfootprint.tool_choice.failed': eventShape({
iteration: num,
status: num,
latencyMs: num,
}),
'agentfootprint.ontology.served': eventShape({
iteration: num,
id: str,
version: str,
hash: str,
nodes: num,
sources: num,
edges: num,
}),
'agentfootprint.answer.assessed': eventShape({
turn: num,
iteration: num,
assessment: oneOf('known', 'not-applicable', 'unknown', 'unrefuted'),
standing: oneOf('ask', 'consistent', 'known', 'not-assessed', 'not-sure'),
reasons: boundAssessmentReasons,
checked: boundAssessmentChecks,
}),
'agentfootprint.embedding.generated': eventShape({
model: str,
provider: oneOf('cohere', 'custom', 'local', 'openai', 'voyage'),
inputKind: oneOf('document', 'query'),
dimension: num,
count: num,
durationMs: num,
tokensSpent: num,
}),
'agentfootprint.artifacts.resolved': eventShape({
ref: str,
via: oneOf('get', 'head'),
kind: str,
bytes: num,
tool: str,
}),
'agentfootprint.artifacts.expired': eventShape({
ref: str,
reason: oneOf('max-bytes', 'max-count', 'ttl'),
kind: str,
bytes: num,
tool: str,
}),
'agentfootprint.artifacts.hand_over_failed': eventShape({
cause: oneOf('abort', 'expired', 'hook', 'operation', 'timeout'),
op: oneOf('delete', 'dispatch', 'get', 'head', 'list', 'put'),
errorClass: str,
errorCode: str,
}),
'agentfootprint.integrity.disposition': eventShape({
posture: oneOf('dev', 'observe'),
workExisted: bool,
rows: listOf(shapeOf({
check: str,
seam: oneOf('choice', 'claim', 'compose', 'wire', 'write'),
checked: num,
findings: num,
notApplicable: num,
unreachable: num,
lastFiredAt: num,
synthetic: num,
})),
}),
};
}
//# sourceMappingURL=auditShapes.js.map