agentfootprint 9.105.0 → 9.106.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/AGENTS.md +1 -1
- package/CHANGELOG.md +64 -0
- package/CLAUDE.md +4 -2
- package/README.md +1 -0
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/core/Agent.js +53 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +100 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +7 -0
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/stages/callLLM.js +37 -9
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/seed.js +9 -0
- package/dist/core/agent/stages/seed.js.map +1 -1
- package/dist/doors/ontology.js +52 -0
- package/dist/doors/ontology.js.map +1 -0
- package/dist/esm/core/Agent.d.ts +8 -0
- package/dist/esm/core/Agent.js +53 -0
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +57 -0
- package/dist/esm/core/agent/AgentBuilder.js +100 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.d.ts +9 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +7 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/stages/callLLM.d.ts +12 -0
- package/dist/esm/core/agent/stages/callLLM.js +37 -9
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/seed.d.ts +11 -0
- package/dist/esm/core/agent/stages/seed.js +9 -0
- package/dist/esm/core/agent/stages/seed.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +41 -0
- package/dist/esm/doors/ontology.d.ts +35 -0
- package/dist/esm/doors/ontology.js +36 -0
- package/dist/esm/doors/ontology.js.map +1 -0
- package/dist/esm/events/dispatcher.d.ts +1 -1
- package/dist/esm/events/dispatcher.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +18 -0
- package/dist/esm/events/registry.d.ts +5 -1
- package/dist/esm/events/registry.js +4 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/events/types.d.ts +1 -1
- package/dist/esm/lib/time-travel/servedView.js +36 -4
- package/dist/esm/lib/time-travel/servedView.js.map +1 -1
- package/dist/esm/ontology/define.d.ts +60 -0
- package/dist/esm/ontology/define.js +268 -0
- package/dist/esm/ontology/define.js.map +1 -0
- package/dist/esm/ontology/index.d.ts +14 -0
- package/dist/esm/ontology/index.js +14 -0
- package/dist/esm/ontology/index.js.map +1 -0
- package/dist/esm/ontology/instruction.d.ts +23 -0
- package/dist/esm/ontology/instruction.js +34 -0
- package/dist/esm/ontology/instruction.js.map +1 -0
- package/dist/esm/ontology/serve.d.ts +63 -0
- package/dist/esm/ontology/serve.js +147 -0
- package/dist/esm/ontology/serve.js.map +1 -0
- package/dist/esm/ontology/types.d.ts +83 -0
- package/dist/esm/ontology/types.js +20 -0
- package/dist/esm/ontology/types.js.map +1 -0
- package/dist/events/dispatcher.js.map +1 -1
- package/dist/events/registry.js +4 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/lib/time-travel/servedView.js +36 -4
- package/dist/lib/time-travel/servedView.js.map +1 -1
- package/dist/ontology/define.js +273 -0
- package/dist/ontology/define.js.map +1 -0
- package/dist/ontology/index.js +24 -0
- package/dist/ontology/index.js.map +1 -0
- package/dist/ontology/instruction.js +37 -0
- package/dist/ontology/instruction.js.map +1 -0
- package/dist/ontology/serve.js +151 -0
- package/dist/ontology/serve.js.map +1 -0
- package/dist/ontology/types.js +21 -0
- package/dist/ontology/types.js.map +1 -0
- package/dist/types/core/Agent.d.ts +8 -0
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +57 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +9 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/stages/callLLM.d.ts +12 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/seed.d.ts +11 -0
- package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +41 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/doors/ontology.d.ts +36 -0
- package/dist/types/doors/ontology.d.ts.map +1 -0
- package/dist/types/events/dispatcher.d.ts +1 -1
- package/dist/types/events/dispatcher.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +18 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +5 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/events/types.d.ts +1 -1
- package/dist/types/events/types.d.ts.map +1 -1
- package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
- package/dist/types/ontology/define.d.ts +61 -0
- package/dist/types/ontology/define.d.ts.map +1 -0
- package/dist/types/ontology/index.d.ts +15 -0
- package/dist/types/ontology/index.d.ts.map +1 -0
- package/dist/types/ontology/instruction.d.ts +24 -0
- package/dist/types/ontology/instruction.d.ts.map +1 -0
- package/dist/types/ontology/serve.d.ts +64 -0
- package/dist/types/ontology/serve.d.ts.map +1 -0
- package/dist/types/ontology/types.d.ts +84 -0
- package/dist/types/ontology/types.d.ts.map +1 -0
- package/package.json +14 -1
package/AGENTS.md
CHANGED
|
@@ -544,7 +544,7 @@ files `agentfootprint.tools.coverage_declared`; with
|
|
|
544
544
|
to the final answer, which is how a limit survives a model that would rather not
|
|
545
545
|
mention it.
|
|
546
546
|
|
|
547
|
-
### Observability —
|
|
547
|
+
### Observability — 119 typed events across 27 domains
|
|
548
548
|
|
|
549
549
|
```typescript
|
|
550
550
|
agent.on('agentfootprint.context.injected', (e) =>
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,70 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [9.106.0] - 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Added — the ontology: a declared map of what exists and where, never a way to fetch it
|
|
11
|
+
|
|
12
|
+
- **`agentfootprint/ontology`** — a new door (the seventeenth): `defineOntology(spec)`
|
|
13
|
+
takes an `OntologySpec` — `nodes` (an `OntologyNode` per term: `meaning`,
|
|
14
|
+
`unit`, `aliases`, and the `sources` that hold it, each an
|
|
15
|
+
`OntologyNodeSource` with the registered tools that read it from there
|
|
16
|
+
(`via`) and the author's `coverage` sentence), `sources` (an
|
|
17
|
+
`OntologySource` per place data is held: `meaning`, `coverage`,
|
|
18
|
+
`configured` — a boolean the author wrote, or absent, which means unknown
|
|
19
|
+
and is never assumed) and `edges` (an `OntologyEdge`: `from`, `to`, the
|
|
20
|
+
author's `relation` word, `meaning`) — and returns an `Ontology`:
|
|
21
|
+
validated, detached, deep-frozen, with a `hash`. Every fault is refused
|
|
22
|
+
by name (an id that is not identifier-safe, an edge to a node nobody
|
|
23
|
+
declared, a node held by a source nobody declared, an empty or over-long
|
|
24
|
+
text, a repeated alias / `via` / edge, a count past `ONTOLOGY_LIMITS`). A
|
|
25
|
+
node with no source is legal: known, nowhere collected here.
|
|
26
|
+
`ontologyHash` fingerprints the five declared fields through the
|
|
27
|
+
receipt's own `stableJson` (key-order independent; edge order is part of
|
|
28
|
+
the identity).
|
|
29
|
+
- **`.ontology(map)`** (`AgentOptions.ontology`, `AgentBuilder.ontology`;
|
|
30
|
+
once per agent, the option form goes through the same door). At
|
|
31
|
+
`.build()` every `via` tool name is checked against the agent's tool
|
|
32
|
+
registry — a name no registry carries is refused, naming the ontology,
|
|
33
|
+
the tool, the node and the source. At run `seed` writes the whole map
|
|
34
|
+
ONCE as the run constant `AgentState.ontology` (`OntologyRecord`: `id`,
|
|
35
|
+
`version`, `hash`, `spec`), so the wire, the rebuild and a lens need
|
|
36
|
+
nothing but the record.
|
|
37
|
+
- **The served piece.** Every model call is served ONE request-only system
|
|
38
|
+
piece composed by the pure `ontologyPiece` (`OntologyPiece`, `source:
|
|
39
|
+
'ontology'` — a new `ContextSource`): a constant header quoting the
|
|
40
|
+
context contract's `domainDefinitions`, `limitations` and `evidenceRefs`
|
|
41
|
+
meanings, then `nodes:`, `sources:`, `held by:`, `relations:` and `known,
|
|
42
|
+
not held here:` — every line the declaration's, nodes and sources sorted
|
|
43
|
+
by id, edges in declaration order, `ONTOLOGY_PIECE_LIMITS` lines per
|
|
44
|
+
section with the overflow stated, an empty section omitted, no per-call
|
|
45
|
+
byte (an unchanged map reuses the cached system prefix). Joined after the
|
|
46
|
+
recovery piece and before the findings piece — injections → recovery →
|
|
47
|
+
ontology → findings, fixed — never as an injection; hashed on the receipt
|
|
48
|
+
and rebuilt byte-equal by `servedAt` in both chart shapes (the grouped
|
|
49
|
+
chart crosses the key into `sf-llm-call` under the arm).
|
|
50
|
+
- **The ask.** `ONTOLOGY_INSTRUCTION` (`ONTOLOGY_INSTRUCTION_ID`), an
|
|
51
|
+
always-on instruction the `outputSchema()` way: say which declared
|
|
52
|
+
source, tool or neighbouring node the map names for a need the results
|
|
53
|
+
did not meet — as a proposal, never as a claim that data exists there;
|
|
54
|
+
never invent a value from the map; report a node listed as known but not
|
|
55
|
+
held here as declared. Judged by `unprovable` in the model-facing
|
|
56
|
+
inventory, beside the piece.
|
|
57
|
+
- **`agentfootprint.ontology.served`** `{ iteration, id, version, hash,
|
|
58
|
+
nodes, sources, edges }` — once per call that served the piece;
|
|
59
|
+
identities and numbers only. A new domain, `ontology`, with its
|
|
60
|
+
wildcard: 26 → 27 domains, 118 → 119 events.
|
|
61
|
+
- **The law.** The library never decides that a node "has no data": absence
|
|
62
|
+
is the model's or the tool's to report; the map only lets the model SAY
|
|
63
|
+
where a need would be met. Nothing is executed or fetched through it;
|
|
64
|
+
nothing is inferred from it. An agent without `.ontology()` is
|
|
65
|
+
byte-identical to one built before the map existed — no key, no piece,
|
|
66
|
+
no instruction, no event (the 19 byte-identity references untouched; one
|
|
67
|
+
new reference `agent-ontology`). What the map is measured on — tool calls
|
|
68
|
+
before the honest answer on questions whose data is not collected, and
|
|
69
|
+
whether that answer names the source — is a bench on the first host after
|
|
70
|
+
the release, not here (`docs/design/2026-09-ontology.md`).
|
|
71
|
+
|
|
8
72
|
## [9.105.0] - 2026-09-17
|
|
9
73
|
|
|
10
74
|
### Added — tool choice by classifier: a second reading beside the model's call, and a narrowing dial
|
package/CLAUDE.md
CHANGED
|
@@ -69,6 +69,7 @@ not in this table, search `src/index.ts` for the nearest noun before writing cod
|
|
|
69
69
|
| pausing a run for a person and resuming it later | `checkInApproved` / `checkInDeclined` (`{ by, note?, value? }`; a decline is NOT an abort — the model gets a "declined by human" tool result and adapts in-loop) | `src/core/checkin.ts` | 7.5.0 |
|
|
70
70
|
| a SECOND source judging every tool result — a calibrated classifier asked what a result is worth for the declared proposition (never why the tool was called), its distribution and cost on the record beside the model's own standing, never merged, never served in its place (policy A) | `.findings({ judge })` + `Classifier` / `typesafe` / `mockClassifier` (`agentfootprint/classify`) + `JudgmentRow` / `JudgmentErrorRow` + `classifierScorer` (the scored entry choice, `agentfootprint/skill-graph`) | `src/classify/` | 9.104.0 |
|
|
71
71
|
| a classifier's reading of WHICH TOOL beside every model call — the ranking, the pick and the cost on the record before the call, the model's call and the agreement after it; optionally the served list narrowed to the top-N plus the doors, on the committed record the receipt hashes and the served view rebuilds; a miss recorded and the full wire served next call, never a refusal, never an override | `.toolChoice({ classifier, serve, alwaysServe })` + `ToolChoiceRow` + `ToolChoiceOutcomeRow` + `ToolChoiceErrorRow` + `ALWAYS_SERVED_TOOLS` + `recordToolChoice` + `narrowServed` (events `agentfootprint.tool_choice.*`, bench `npm run bench:tool-choice`) | `src/core/agent/toolChoice/` | 9.105.0 |
|
|
72
|
+
| a MAP of the domain the model can reason over when a result holds nothing — what each term IS (meaning, unit), how terms RELATE, which SOURCE holds a term (with the author's coverage sentence) and which registered TOOL reads it from there; declared once, validated against the tool registry at build, on the record as one run constant, served as one request-only system piece per call, never a fetch path and never inferred from | `defineOntology` + `.ontology(map)` (`AgentOptions.ontology`) + `AgentState.ontology` + `ontologyPiece` / `ONTOLOGY_INSTRUCTION` (`agentfootprint/ontology`) + `agentfootprint.ontology.served` | `src/ontology/` | 9.106.0 |
|
|
72
73
|
|
|
73
74
|
**One law before you add a mapping.** Any function turning caller data into a KEY,
|
|
74
75
|
a namespace, a filename or an index entry must be injective, and its collision
|
|
@@ -85,7 +86,7 @@ does not exist, so the table can go out of date by OMISSION but can never lie
|
|
|
85
86
|
about what it names.
|
|
86
87
|
|
|
87
88
|
## Module map
|
|
88
|
-
Entry points —
|
|
89
|
+
Entry points — SEVENTEEN doors, and `package.json` `exports` is exhaustive, so a path not on this list does not resolve at all: `.` core API · `/providers` everything you plug a backend into (mock/anthropic/openai/bedrock/browser*, embedders, staticTools/gatedTools/skillScopedTools/mcpClient, thinking handlers, code runners) · `/memory` (defineMemory, MEMORY_TYPES, InMemoryStore, mockEmbedder, redis/agentcore/bedrockAgentMemory stores) · `/rag` index-time loaders/splitters/indexCorpus · `/cache` prompt caching (+ registerCacheStrategy; side-effectful, hence its own door) · `/observe` the whole watching story (recorders, recordRun, strategies + attach*, vendor sinks, run-autopsy finders, toSSE, status, locales) · `/events` typed event system · `/context` the injection engine (defineInjection/Skill/Fact/Instruction/Steering, decideSkill) · `/resilience` provider decorators + the reliability RULES · `/hosting` nodeHost/httpHost/standingAgent + session stores · `/security` permissions + tool credentials (it absorbed the old identity door) · `/reliability` the retained alias, kept ONLY because it is the sole home of the gate's `CircuitOpenError` · `/skill-graph` the framework-neutral routing layer · `/recipes` the declared unit of agent CONFIGURATION (defineAgentRecipe → `.recipe()`; authoring-time vocabulary, so it stays off the main barrel) · `/maps` the mount kernel's vocabulary (9.58.0: Claim<T> + the engagement lease machine + its renewal feed — pure data and pure functions, no run entry point; mounted via `.maps()`) · `/classify` the calibrated-classifier port (9.104.0: `Classifier`, `typesafe`, `mockClassifier`, `ClassifierError` — a backend that SCORES declared candidates; spent by `.findings({ judge })` and by `classifierScorer` on `/skill-graph`) · `/ontology` the declared map (9.106.0: `defineOntology`, `ontologyHash`, `ontologyPiece`, `ONTOLOGY_INSTRUCTION`, the shapes — what each term IS, how terms RELATE, which SOURCE holds a term and which registered TOOL reads it; pure data and pure functions, no run entry point, no fetch path; mounted via `.ontology()`, served as one request-only system piece per call). 9.0.0 removed sixteen older paths (`/llm-providers`, `/injection-engine`, `/tool-providers`, `/strategies`, `/observability-providers`, `/identity`, `/stream`, `/thinking`, `/status`, `/locales`, `/debug`, `/debug/finders`, `/memory-providers`, `/embedders`, `/hosting-providers`, `/observability/contextError/finders`) — it removed PATHS, not code; each name still ships through the door that absorbed it. This list is pinned against `package.json` by test/api-conformance/documented-doors.test.ts, and the removed sixteen by subpath-exports.test.ts. **Main barrel does NOT export** mock/browser*/defineMemory/defineSkill/skillGraph/mcpClient/InMemoryStore — import from the doors above.
|
|
89
90
|
|
|
90
91
|
| src/ | one job |
|
|
91
92
|
|---|---|
|
|
@@ -101,6 +102,7 @@ Entry points — SIXTEEN doors, and `package.json` `exports` is exhaustive, so a
|
|
|
101
102
|
| recorders/core/ | bridges footprintjs events → typed EventDispatcher (ContextRecorder, EmitBridge, typedEmit) — auto-attached by Agent.createExecutor; most factories also exported via `/observe` for manual wiring (EmitBridge itself stays internal) |
|
|
102
103
|
| recorders/observability/ | consumer recorders over the typed stream (RunStepRecorder, FlowchartRecorder, Status, Trace replay) + `recordRun` — THE producer of a recording `{snapshot, events, structure}` (the shape lens's `observeRecording` consumes; `structure` = `getSpec().buildTimeStructure`, which no snapshot carries). Anything that saves a run goes through it |
|
|
103
104
|
| rag/ | (8.10.0, door `/rag`) index-TIME: `DocumentLoader` adapters (text/markdown/html zero-dep, pdf via lazy `unpdf`) + `Splitter` factories + `indexCorpus` — a REAL footprintjs chart whose commit log IS the indexing report. `defineRAG` deliberately stays on the MAIN barrel (run-time wiring); this door is the half that runs once, before any agent exists |
|
|
105
|
+
| ontology/ | (9.106.0) the declared map — `defineOntology` (validate, detach, freeze, `ontologyHash` through the receipt's `stableJson`) + `serve.ts · ontologyPiece` (the ONE composer, called by `callLLM` and by `servedView.viewOf`; every line quotes the declaration under a constant header that quotes the context contract's three meanings) + `instruction.ts` (the always-on ask). Behind the `/ontology` door; `Agent.buildChart` checks every `via` tool name against `registryByName` at build; `seed` writes `AgentState.ontology` once; the grouped chart crosses the key into `sf-llm-call` under `hasOntology` |
|
|
104
106
|
| lib/ | first-party sub-libraries: injection-engine/, context-bisect/ (localizeContextBug, toBacktrackTrace + sliceToBacktrackTrace — the atui board serializers), influence-core/, trace-toolpack/ (selfExplain; 6 tools incl. variable-first `backtrack(variable, element?)`), context-ledger/ (which pieces EARNED their tokens — post-run offers/uses/outcomes bookkeeping + demote-never-starve gates `ledgerToolGate`/`ledgerEntryScorer`/`ledgerGated`; grouped-mode folds sf-llm-call inner logs, unmeterable runs → undefined; /observe), mcp/, rag/, tool-lint/ |
|
|
105
107
|
| memory/ | store/ (MemoryStore port) + pipeline presets + stages + beats/facts + causal/ (dev-only, TOP_K+search()-only) + wire/mountMemoryPipeline + retrieval/ (8.8.0: the `RetrievalStrategy` seam + `RetrievalEvidence`, the record a retrieval leaves — `topK()` is what every earlier release did unnamed) |
|
|
106
108
|
| maps/ | (9.58.0, door `/maps`) the mount kernel: claim/ (`Claim<T>` honesty primitive) + engagement/ (lease machine `advanceEngagement` + renewal feed `renewalEvidenceOf` + vocabulary). Pure data/functions; the ONE framework hook is `ctx.parkedIds` in the evaluator (the `leaseActiveIds` mirror), fed by the Evaluate stage; state rides `AgentState.mapEngagement` as a TOP-LEVEL array (the StepPointerCarrier law) |
|
|
@@ -159,7 +161,7 @@ Traps: `src/observability/` holds the finder IMPLEMENTATIONS (canonical home; `d
|
|
|
159
161
|
- **Embedder fingerprint** (8.9.0) → `Embedder.id` (optional; every shipped embedder sets one, and NONE include dims — the store appends `@<dims>` itself, so an id carrying its own size double-stamps) + `indexDocuments` defaulting `embedderId` to it + `SqliteVectorStore.reconcileFingerprint` (the only comparison site). Rule: dimensions ALWAYS decide, model ids decide only when BOTH sides named themselves — refusing on an absent name would block the majority of callers who never pass `embedderId`.
|
|
160
162
|
- **Retrieval record** (8.8.0) → FOUR stages write one object in sequence: `loadRelevant` (candidates+scores+threshold verdicts) → `pickByBudget` (re-marks admitted→over-budget/over-max-entries) → `formatDefault` (`promptFragment` + `promptPosition`) → the read mount's outputMapper lifts it to root as `retrievalEvidence_<id>`. `memoryRecallInjections` then splits ONE recall into one ActiveInjection PER CHUNK — guarded by a byte-equality check (`fragments.join('\n\n') === systemContent`) that falls back to the single injection rather than change the prompt. `rank` (score order) and `promptPosition` (picker order) are DIFFERENT and both load-bearing: joining fragments in rank order reproduces the right bytes in a sequence the model never saw.
|
|
161
163
|
- **AgentState** → all 8 stages/ files, both builders' mappers, memory-wire STRING-TYPED keys ('runIdentity'/'turnNumber'/… buildAgentChart.ts:177-180 — not refactor-safe), finalizeResult's `reliabilityFail*`/`policyHalt*` reads (rename silently kills the typed errors).
|
|
162
|
-
- **events/** →
|
|
164
|
+
- **events/** → 119 typed events across 27 domains (counts anti-drift-tested against this file — update BOTH when adding events): ALL_EVENT_TYPES exhaustiveness tests, DomainWildcard hand-list, ~42 importers (recorders, strategies, stream, commentary).
|
|
163
165
|
- **Run-configuration manifest (9.41.0)** → `agentfootprint.agent.run_configured`, the JOIN KEY that turns N runs into N labelled ARMS: one event naming the adapters/strategies in play (provider+model, reactMode, each memory's declared strategy/retrieval/embedder, window, graph posture+classifier, evidence posture, artifacts-present). Composed by the PURE `core/agent/runManifest.ts`, dispatched from `Agent.emitRunManifest()` at the END of `createExecutor` — the ONE funnel `run()` AND `resume()` share, both of which mint a fresh runId. Direct `dispatcher.dispatch` with a STATED pseudo-stage (`run-configured#0`), the `emitToolSessionReport` precedent — there is no stage yet, and `minimalMeta()` would make the one joinable-by-design event unjoinable. TWO laws, both tested: NAMES ONLY (a store is reported PRESENT and unnamed rather than identified by a directory/endpoint — `MemoryStore` and `ArtifactStore` declare no id), and ABSENT means "not configured", never a guessed `'default'`. Graph presence is read off `skillGraphNextSkill`, NOT `skillGraphCascade` (a 9.16-style mount sets no cascade and would read as "no graph"). `MemoryDefinition` gained `strategy`/`retrieval`/`embedderId` for it — declared names the compiled pipeline had closed over, the `store`-in-the-open precedent.
|
|
164
166
|
- **adapters/types.ts LLMMessage/LLMRequest** → 62 importers: tool_use round-trip (toolCalls.ts:115-135), wire assembly (callLLM.ts:150-160), providers, cache strategies, security/extractSequence, reliability loop.
|
|
165
167
|
- **Cache** → strategy registration is a MODULE SIDE EFFECT (src/index.ts:15-17); an entry point skipping that import silently falls back to NoOp. Resolved once per Agent at construction (Agent.ts:347).
|
package/README.md
CHANGED
|
@@ -933,6 +933,7 @@ The flowchart, recorders, and tests don't change between dev and prod.
|
|
|
933
933
|
- Context Integrity — deterministic checks at the seams where a run contradicts ITSELF: a tool parked but still on the wire, a tool offered after the results grounding it were evicted, an answer field that disagrees with the fact it claims to report (`.claims()`, requires `.outputSchema()`). Nothing is blocked or rewritten — each defect is one typed finding, and every run files a disposition ledger so "no findings" and "no check ran" stay different states. `integrityPosture: 'dev'` adds the liveness proofs (a start-of-run canary; `CheckerDeadError` instead of a green report from a checker that never ran). Read it back with `find_context_errors` over a recording — [Context Integrity](https://agentfootprint.dev/docs/monitor/context-integrity/)
|
|
934
934
|
- Findings ledger — `.findings()` adds one reserved optional argument, `_findings`, to every served tool schema: the model declares why it makes each call (`basis`: `direct` or `exploratory`) and, on its next call or as a top-level key of a JSON answer, the standing of each earlier result by its tool_result id (`fact` with the assertions it stands on, `open`, `ruled-out`, `noise`). Zero extra model calls. The argument is peeled off before the tool, the middleware or the validator sees the call; the rows land as one append-only `findingsLedger` on the run's state (`agent.findings()`), with a `conflict` row whenever two stood-on readings disagree. Nothing is inferred — a call that declares nothing files nothing — and nothing is served differently yet: the ledger is a record. An agent that never calls `.findings()` is byte-identical to one built before it existed
|
|
935
935
|
- Tool choice by classifier — `.toolChoice({ classifier, serve })` asks a calibrated classifier (`agentfootprint/classify`) at every model call which of the tools about to be served answers the current step, and files its ranking, its pick and its cost as a `pick` row beside the model's own call, then an `outcome` row after the reply (`firstAgrees`, any `miss`). The model's call is never overridden. `serve: { top: N }` narrows the served list to the classifier's top-N plus the doors (`read_skill`, `skip_step`, `present`, your `alwaysServe`), on the committed record the receipt hashes and `servedAt` rebuilds; a failed classifier serves the full set, a miss serves the full set on the next call. `npm run bench:tool-choice` measures agreement, misses and tools-slot bytes from the record. An agent without `.toolChoice()` is byte-identical
|
|
936
|
+
- The ontology — `.ontology(map)` mounts a declared map of the domain (`defineOntology` on `agentfootprint/ontology`): what each term IS (meaning, unit), how terms RELATE, which SOURCE holds a term with the author's coverage sentence, and which registered TOOL reads it from there. A map, not a door — it provides no way to get data, nothing is fetched through it and the library infers nothing from it; it is on the record once as `AgentState.ontology`, served as one request-only system piece per call (every line the declaration's; a node nobody holds is `known, not held here`), hashed on the receipt and rebuilt by `servedAt`, and the model is asked to name the source or neighbouring node a need points at — as a proposal. `via` tool names are checked against the registry at build. An agent without `.ontology()` is byte-identical
|
|
936
937
|
- 60+ typed observability events — `agent` · `composition` · `context` · `stream` · `tools` · `skill` · `memory` · `cache` · `cost` · `permission` · `eval` · `embedding` · `pause` · `error` · `fallback` · `resilience` · `reliability` · `risk`
|
|
937
938
|
|
|
938
939
|
**Debugging & compliance** (`agentfootprint/observe`)
|
|
@@ -252,7 +252,7 @@ const agent = Agent.create({ provider, model })
|
|
|
252
252
|
agent.on('agentfootprint.context.evaluated', (e) => console.log(e.payload.activeIds));
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
-
**
|
|
255
|
+
**119 typed events across 27 domains.** Two subscription shapes and no third:
|
|
256
256
|
`'*'` (every event) and `'agentfootprint.<domain>.*'` (one domain). **`'agentfootprint.*'`
|
|
257
257
|
is not a pattern** — TypeScript rejects it, and at runtime it would match nothing.
|
|
258
258
|
|
package/dist/core/Agent.js
CHANGED
|
@@ -294,6 +294,14 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
294
294
|
* armed agent only — an unarmed agent hands each stage exactly the deps it
|
|
295
295
|
* always did. */
|
|
296
296
|
toolChoiceOptions;
|
|
297
|
+
/** The declared ontology (9.106.0, `.ontology()`): the frozen map. Threaded
|
|
298
|
+
* to seed (the whole map, written once as the run constant `ontology`),
|
|
299
|
+
* to call-llm (`ontology: true`, the gate on every read of that key) and
|
|
300
|
+
* to both chart builders (`hasOntology`, the grouped boundary's crossing)
|
|
301
|
+
* on an armed agent only — an unarmed agent hands each stage exactly the
|
|
302
|
+
* deps it always did. The tool names its `via` edges name are checked
|
|
303
|
+
* against the registry in `buildChart`, beside `buildToolRegistry`. */
|
|
304
|
+
ontology;
|
|
297
305
|
/** The opt-in tool-result ceiling in characters (9.11.0). Absent → results
|
|
298
306
|
* are never measured. See {@link AgentOptions.maxToolResultChars}. */
|
|
299
307
|
maxToolResultChars;
|
|
@@ -670,6 +678,8 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
670
678
|
this.findingsOptions = opts.findings;
|
|
671
679
|
if (opts.toolChoice !== undefined)
|
|
672
680
|
this.toolChoiceOptions = opts.toolChoice;
|
|
681
|
+
if (opts.ontology !== undefined)
|
|
682
|
+
this.ontology = opts.ontology;
|
|
673
683
|
// The tool-result ceiling (9.11.0). Refused HERE, naming the value, rather
|
|
674
684
|
// than at the first tool call of the first run — a dial that cannot cap
|
|
675
685
|
// anything is a configuration mistake, not a runtime condition.
|
|
@@ -2615,6 +2625,17 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
2615
2625
|
getRunContext: getRunCtx,
|
|
2616
2626
|
}));
|
|
2617
2627
|
}
|
|
2628
|
+
// Same wiring for `agentfootprint.ontology.*` (9.106.0) — the one event
|
|
2629
|
+
// `callLLM` emits when the declared map is served. Attached only under
|
|
2630
|
+
// `.ontology()`, for the same reason.
|
|
2631
|
+
if (this.ontology !== undefined) {
|
|
2632
|
+
attachObserver(new EmitBridge_js_1.EmitBridge({
|
|
2633
|
+
id: 'agentfootprint.ontology-bridge',
|
|
2634
|
+
prefix: 'agentfootprint.ontology.',
|
|
2635
|
+
dispatcher,
|
|
2636
|
+
getRunContext: getRunCtx,
|
|
2637
|
+
}));
|
|
2638
|
+
}
|
|
2618
2639
|
for (const r of this.attachedRecorders) {
|
|
2619
2640
|
// A recorder's OWN `delivery` field is more specific than the
|
|
2620
2641
|
// agent-level default — footprintjs's options bag would override the
|
|
@@ -3251,6 +3272,11 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3251
3272
|
return l;
|
|
3252
3273
|
},
|
|
3253
3274
|
}),
|
|
3275
|
+
// The declared ontology (9.106.0): the whole frozen map, which seed
|
|
3276
|
+
// writes ONCE as the run constant `ontology` — the `findingsServe`
|
|
3277
|
+
// precedent, a build-time fact the rebuild reads from the RECORD. An
|
|
3278
|
+
// unarmed agent hands seed exactly the deps object it always did.
|
|
3279
|
+
...(this.ontology !== undefined && { ontology: this.ontology }),
|
|
3254
3280
|
// The conversation's inherited skill cursor (SG-C). Consumed (cleared)
|
|
3255
3281
|
// on every run; HONORED only when the mounted graph declared
|
|
3256
3282
|
// `continuity: 'conversation'` — the same one-option-one-behavior gate
|
|
@@ -3315,6 +3341,26 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3315
3341
|
// armed may a registry tool's own `_findings` be refused.
|
|
3316
3342
|
...(this.findingsOptions !== undefined && { findings: true }),
|
|
3317
3343
|
});
|
|
3344
|
+
// The declared ontology's tool edges (9.106.0): every name a node's `via`
|
|
3345
|
+
// names must be a tool this registry can dispatch — the static registry,
|
|
3346
|
+
// the framework's doors and every skill's tools, `registryByName` being
|
|
3347
|
+
// the ONE map that holds all of them. Refused at BUILD, naming the
|
|
3348
|
+
// ontology and the tool: a map that points a need at a tool nobody can
|
|
3349
|
+
// call is a map that lies, and only the operator can fix it. Provider-
|
|
3350
|
+
// served tools are only met at dispatch and cannot be named here.
|
|
3351
|
+
if (this.ontology !== undefined) {
|
|
3352
|
+
for (const [nodeId, node] of Object.entries(this.ontology.nodes)) {
|
|
3353
|
+
for (const held of node.sources ?? []) {
|
|
3354
|
+
for (const toolName of held.via ?? []) {
|
|
3355
|
+
if (!registryByName.has(toolName)) {
|
|
3356
|
+
throw new Error(`Agent: ontology '${this.ontology.id}' names tool '${toolName}' that is not ` +
|
|
3357
|
+
`registered (node '${nodeId}', source '${held.source}'). Register the tool ` +
|
|
3358
|
+
`with .tool() or on a skill, or drop it from the node's \`via\`.`);
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3318
3364
|
// A statically registered tool that declares `wants` on an agent with no
|
|
3319
3365
|
// store is configuration that lies: every call would be refused at
|
|
3320
3366
|
// dispatch for a gap only the operator can close. Refused at BUILD,
|
|
@@ -3620,6 +3666,10 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3620
3666
|
...(this.answerValidationConfig !== undefined && { suppressDraftTokens: true }),
|
|
3621
3667
|
// Tool choice by classifier (9.105.0): the outcome row after the reply.
|
|
3622
3668
|
...(this.toolChoiceOptions !== undefined && { toolChoice: true }),
|
|
3669
|
+
// The declared ontology (9.106.0): the piece served from the run
|
|
3670
|
+
// constant on every call, under the one gate — an unarmed agent reads
|
|
3671
|
+
// no new key.
|
|
3672
|
+
...(this.ontology !== undefined && { ontology: true }),
|
|
3623
3673
|
// The receipt's salt (9.88.0) — read per call, like seed's own accessor.
|
|
3624
3674
|
getRunId: () => this.currentRunContext?.runId,
|
|
3625
3675
|
// …and its off switch. Value-conditional, so an agent on the default
|
|
@@ -3989,6 +4039,9 @@ class Agent extends RunnerBase_js_1.RunnerBase {
|
|
|
3989
4039
|
// Tool choice by classifier (9.105.0): the mount args on the Tools
|
|
3990
4040
|
// branch and the key across the sf-llm-call boundary, under the arm.
|
|
3991
4041
|
...(this.toolChoiceOptions !== undefined && { hasToolChoice: true }),
|
|
4042
|
+
// The declared ontology (9.106.0): the grouped chart carries the run
|
|
4043
|
+
// constant across the sf-llm-call boundary, under the arm.
|
|
4044
|
+
...(this.ontology !== undefined && { hasOntology: true }),
|
|
3992
4045
|
// `.limitsTravelWithTheAnswer()` (this release) — value-conditional, the
|
|
3993
4046
|
// `resolvedModel` precedent: absent from the deps object entirely for an
|
|
3994
4047
|
// agent that did not ask, so both builders mount the final-branch stage
|