agentfootprint 9.94.1 → 9.94.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,7 +5,98 @@ 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
- ## [Unreleased]
8
+ ## [9.94.3] - 2026-09-12
9
+
10
+ ### Fixed — two behaviours that moved with footprintjs 9.22.0+ and 9.24.0, found by running the suite on them
11
+
12
+ The lockfile had held footprintjs at 9.21.1, so nothing here had run on the
13
+ 9.22–9.23 line. Running the suite on the 9.24.0 build found two defects on
14
+ OUR side; both are fixed so that agentfootprint is correct on every
15
+ footprintjs the range admits (`^9.21.1`).
16
+
17
+ - **`skill.step_advanced` named the step AFTER the one that completed** on
18
+ footprintjs ≥ 9.22.0 (and `skip_step`'s pointer moved one too far). The
19
+ step boundary read `pointerOf(scope.stepPointer)` — since 9.22.0 an array
20
+ element read through the scope is a handle that reads LIVE by path — then
21
+ replaced the pointer and only then emitted `ptr.step`, which by then was
22
+ the new value. It reads the pointer as a VALUE now
23
+ (`scope.$getValue('stepPointer')`, the committed object, which never
24
+ changes once replaced). Three `skill-steps` tests were red on 9.22.0,
25
+ 9.22.1, 9.23.0 and 9.23.3 (bisected); green on all of them now.
26
+ - **A phantom skill churn switched caching off.** `detectSkillChurn`
27
+ counted every slot that was not `undefined`. The parent writes
28
+ `skillHistory` with `undefined` for "no skill yet"; footprintjs < 9.24.0
29
+ round-tripped that array through JSON on the scope write, so the gate saw
30
+ `null`, counted it as a third skill, and took the `skip-caching` branch on
31
+ the first turn after two real skills — every run with two skills read in
32
+ sequence lost its cache markers from iteration 4. The gate counts only
33
+ strings now. One byte-identity reference (`agent-shared-tool-reference`)
34
+ had recorded the phantom (`cacheMarkers: []` at the iteration-4
35
+ merge-back) and is regenerated with the delta on record in the test
36
+ header; it is green on both the lockfile's 9.21.1 and on 9.24.0, so what
37
+ it pins is the gate, not the substrate. Pinned:
38
+ `test/cache/CacheGateDecider.test.ts` ("a `null` slot is no skill too").
39
+
40
+ ### Changed — the suite runs on the footprintjs consumers get
41
+
42
+ - The dev pin moves to footprintjs `^9.24.0` (the lockfile had held 9.21.1
43
+ since 9.85; the peer range stays `^9.21.1`, and the two fixes above make
44
+ this library correct across it). 10,541 tests green on 9.24.0.
45
+
46
+ ### Tests — recorded-not-built entry 10, the quantifier half, for its three named clauses
47
+
48
+ - `gap-sentences.test.ts`: `no-fold-base`'s "reads as empty rather than as
49
+ unknown" walks the catalogue's whole field list (a reading table; a field
50
+ the table cannot read fails by name — the list also names `epoch`, never
51
+ touched before); `cache-transform`'s "that gap is the stronger claim" is
52
+ measured for every (gap, shared field) pairing that occurs beside it on
53
+ every fixture view, intact and damaged, against that gap's own claim (an
54
+ unmeasured kind fails by name; "stronger" is *may be short*, ≤ — on a fresh
55
+ run with its base stripped the rebuild recovers everything);
56
+ `forced-tool-schema`'s "the tool list is complete" runs on both chart
57
+ shapes. The design page marks the three built; the general statement — a
58
+ clause not named there has its quantifier read by a person — stands.
59
+
60
+ ## [9.94.2] - 2026-09-12
61
+
62
+ ### Fixed
63
+
64
+ - **The docs site now runs the lens it documents, on ONE footprintjs.** Docs
65
+ only — nothing under `src/` moved. `docs-next/package.json` had pinned
66
+ `agentfootprint-lens ^0.31.1`, `footprint-explainable-ui ^0.28.0` and
67
+ `footprintjs ^9.10.0` since the 9.x door renames — twenty lens releases
68
+ behind — so the site's live demos had never shown the Served tab, the
69
+ Served graph, Bookmarks or the tag picker (lens 0.47–0.52), and every demo
70
+ bundle carried TWO footprintjs engines: the root's 9.21.1 (the library's
71
+ peer, reached through `agentfootprint: file:..`) beside docs-next's own
72
+ 9.10.0, because two node_modules directories are two module paths whatever
73
+ the two versions say. Two engines is not only bytes: a trace the library
74
+ writes with one and the lens reads with the other shares no class, symbol
75
+ or WeakMap. Pins now: lens `^0.52.2`, explainable-ui `^0.38.0` (the lens's
76
+ peer range wants `>=0.28.0 <1.0.0`; ≥0.34 lights the replay chart),
77
+ footprintjs `^9.21.1` — the root's own range. Matching ranges cannot merge
78
+ two directories, and a `file:` link to the root's copy is refused by npm
79
+ (it runs the published package's `prepare` script), so the one-engine rule
80
+ is `next.config.mjs` · `footprintjsAliases`: every browser request for
81
+ `footprintjs` or one of its doors is pointed at the root's copy, the doors
82
+ read from the package's own `exports`. No demo prop moved across
83
+ 0.31→0.52; the demos typecheck and run unchanged, and the Lens demo now
84
+ shows the rail (What happened · Served · Bookmarks), with every receipt
85
+ reading Verified — the one-engine identity proof in itself. Measured, same
86
+ build, three ways: 382.4 KB gzip on the old Lens with two engines; 514.0 KB
87
+ on the current Lens as first pinned — the dedupe itself was −3.8 KB and the
88
+ rest was two LENS defects the measurement exposed (no `sideEffects` flag,
89
+ so a page mounting one component carried the whole Lens; and a bug-report
90
+ button that imported the entire `agentfootprint/observe` door as a
91
+ namespace object); agentfootprint-lens 0.52.2 fixed both the same day
92
+ (audited flag, door opened on click), and the site re-measured on it at
93
+ 413.8 KB across 15 assets, one engine. So the whole Served tab, Served
94
+ graph, bookmarks and tag picker the site now shows cost 31 KB over the old
95
+ baseline. The deferred-demo ceiling is set at 422 KB (~2% over) with the
96
+ three-way story beside it. Also fixed: the webpack stats
97
+ the module-breakdown tool reads (`DOCS_WEBPACK_STATS=1`) omitted every
98
+ cached module, so a second build in a row reported 0 modules —
99
+ `cachedModules: true`.
9
100
 
10
101
  ## [9.94.1] - 2026-09-11
11
102
 
@@ -61,7 +61,13 @@ function detectSkillChurn(history, windowSize = exports.SKILL_CHURN_WINDOW, thre
61
61
  const recent = history.slice(-windowSize);
62
62
  const uniqueSkills = new Set();
63
63
  for (const s of recent) {
64
- if (s !== undefined)
64
+ // A skill id is a string; anything else is "no skill on this turn". The
65
+ // slot is `undefined` when the run had no skill yet — and it was `null`
66
+ // in every record written before footprintjs 9.24.0, whose scope
67
+ // round-tripped the array through JSON. That `null` counted here as a
68
+ // skill and turned caching OFF on the first turn after two real skills
69
+ // (a phantom churn; found by the 9.24.0 byte-identity run).
70
+ if (typeof s === 'string')
65
71
  uniqueSkills.add(s);
66
72
  }
67
73
  return uniqueSkills.size >= threshold;
@@ -1 +1 @@
1
- {"version":3,"file":"CacheGateDecider.js","sourceRoot":"","sources":["../../src/cache/CacheGateDecider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;AAEH,6CAA2E;AA6B3E;;;;;;;;;;;;GAYG;AACU,QAAA,cAAc,GAAG,GAAG,CAAC;AAElC;;;GAGG;AACU,QAAA,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,OAAwC,EACxC,aAAqB,0BAAkB,EACvC,YAAoB,6BAAqB;IAEzC,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,yBAAyB;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,SAAS;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,IAAI,SAAS,CAAC;AACxC,CAAC;AAZD,4CAYC;AAQD;;;;;;;;;;;GAWG;AACH,SAAgB,eAAe,CAAC,KAAiC;IAC/D,OAAO,IAAA,oBAAM,EACX,KAAK,EACL;QACE;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI;YACvC,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,uDAAuD;SAC/D;QACD;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,CAAC,aAAa,GAAG,sBAAc;YAC9E,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,cAAc,sBAAc,GAAG,GAAG,kBAAkB;SAC5D;QACD;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC;YAC7C,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,iBAAiB,6BAAqB,0BAA0B,0BAAkB,SAAS;SACnG;KACF,EACD,eAAe,CAChB,CAAC;AACJ,CAAC;AAtBD,0CAsBC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,kBAAkB,CAChC,KAGE;IAEF,MAAM,GAAG,GAAG,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,+DAA+D;IAC/D,mDAAmD;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,0BAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,0BAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClG,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC;AAC/B,CAAC;AAdD,gDAcC"}
1
+ {"version":3,"file":"CacheGateDecider.js","sourceRoot":"","sources":["../../src/cache/CacheGateDecider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;AAEH,6CAA2E;AA6B3E;;;;;;;;;;;;GAYG;AACU,QAAA,cAAc,GAAG,GAAG,CAAC;AAElC;;;GAGG;AACU,QAAA,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,OAAwC,EACxC,aAAqB,0BAAkB,EACvC,YAAoB,6BAAqB;IAEzC,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,yBAAyB;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,wEAAwE;QACxE,wEAAwE;QACxE,iEAAiE;QACjE,sEAAsE;QACtE,uEAAuE;QACvE,4DAA4D;QAC5D,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,IAAI,SAAS,CAAC;AACxC,CAAC;AAlBD,4CAkBC;AAQD;;;;;;;;;;;GAWG;AACH,SAAgB,eAAe,CAAC,KAAiC;IAC/D,OAAO,IAAA,oBAAM,EACX,KAAK,EACL;QACE;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI;YACvC,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,uDAAuD;SAC/D;QACD;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,CAAC,aAAa,GAAG,sBAAc;YAC9E,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,cAAc,sBAAc,GAAG,GAAG,kBAAkB;SAC5D;QACD;YACE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC;YAC7C,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,iBAAiB,6BAAqB,0BAA0B,0BAAkB,SAAS;SACnG;KACF,EACD,eAAe,CAChB,CAAC;AACJ,CAAC;AAtBD,0CAsBC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,kBAAkB,CAChC,KAGE;IAEF,MAAM,GAAG,GAAG,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,+DAA+D;IAC/D,mDAAmD;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,0BAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,0BAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClG,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC;AAC/B,CAAC;AAdD,gDAcC"}
@@ -830,7 +830,13 @@ function buildToolCallsHandler(deps) {
830
830
  const stepStateOf = (scope) => {
831
831
  if (!deps.stepPlanFor)
832
832
  return undefined;
833
- const ptr = (0, skillSteps_js_1.pointerOf)(scope.stepPointer);
833
+ // A VALUE, not a handle: `scope.stepPointer[0]` is a proxy that reads
834
+ // live by path (footprintjs 9.22.0), so after `scope.stepPointer = [next]`
835
+ // below it would already answer with `next` — and the event that names
836
+ // the step just completed would name the one after it. `$getValue`
837
+ // hands back the committed/staged object itself, which never changes
838
+ // once the pointer is replaced (committed state is immutable-after-swap).
839
+ const ptr = (0, skillSteps_js_1.pointerOf)(scope.$getValue('stepPointer'));
834
840
  if (!(0, skillSteps_js_1.stepInProgress)(ptr))
835
841
  return undefined;
836
842
  const plan = deps.stepPlanFor(ptr.skillId);