@pond-ts/react 0.67.0 → 0.68.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 ADDED
@@ -0,0 +1,244 @@
1
+ # Using pond from a coding agent
2
+
3
+ You are reading this because a project depends on `pond-ts` or one of the
4
+ `@pond-ts/*` packages, or because you are deciding whether it should. This
5
+ file is the shortest route to correct code. It ships inside every pond
6
+ tarball as `AGENTS.md`, next to `API.md` (every public export, one line
7
+ each, with its source file) and `CHANGELOG.md`.
8
+
9
+ Docs: <https://pond-ts.org> · index for agents: <https://pond-ts.org/llms.txt>
10
+ · source: <https://github.com/pond-ts/pond>.
11
+
12
+ ## What pond is, in three lines
13
+
14
+ - A **typed, immutable time series** (`TimeSeries`) whose schema is declared
15
+ once `as const` and narrows every downstream transform — no casts.
16
+ - The **same operator vocabulary on a streaming buffer** (`LiveSeries`):
17
+ push events in, subscribe to incremental `rolling` / `aggregate` views,
18
+ bounded by retention.
19
+ - **Domain packages on top**: React hooks, canvas charts that read a series
20
+ directly, financial studies + trading calendars, fitness analytics, and an
21
+ experimental processing-graph runtime.
22
+
23
+ ## Which package
24
+
25
+ | You need to… | Install | Import from |
26
+ | ----------------------------------------------------------------------- | ------------------------------------ | ----------------------------------------------------- |
27
+ | Load timestamped rows; bucket, regrid, roll, fill, join, partition them | `pond-ts` | `'pond-ts'` |
28
+ | Ingest a live feed and keep rolling stats over the last N minutes | `pond-ts` | `'pond-ts'` (`LiveSeries`) |
29
+ | Share a series' type across a wire boundary with zero runtime | `pond-ts` | `'pond-ts/types'` |
30
+ | Own / subscribe to a series inside React | `@pond-ts/react` | `'@pond-ts/react'` |
31
+ | Draw it (line, area, band, bar, scatter, box, candlestick, heat map) | `@pond-ts/charts` (+ react, pond-ts) | `'@pond-ts/charts'` |
32
+ | OHLCV bars, SMA/EMA/RSI/MACD/Bollinger/ATR/VWAP…, market-hours calendar | `@pond-ts/financial` | `'@pond-ts/financial'`, `'@pond-ts/financial/fluent'` |
33
+ | GPS / power / heart-rate activity analytics | `@pond-ts/fit` | `'@pond-ts/fit'` |
34
+ | Computations as JSON plans with caching + provenance (experimental) | `@pond-ts/process` | `'@pond-ts/process'` |
35
+
36
+ All six release together under one version and release often. Install with
37
+ `@latest` rather than a version written from memory (a cold-start agent once
38
+ wrote `^0.3.0` and spent turns on a 2024 API); keep their ranges in step — a
39
+ pre-1.0 caret (`^0.67.0`) does **not** span minors.
40
+
41
+ ## The idioms that cover most jobs
42
+
43
+ ### 1. Declare the schema, build the series
44
+
45
+ ```ts
46
+ import { TimeSeries, Sequence } from 'pond-ts';
47
+
48
+ const schema = [
49
+ { name: 'time', kind: 'time' },
50
+ { name: 'host', kind: 'string' },
51
+ { name: 'latencyMs', kind: 'number' },
52
+ ] as const; // ← load-bearing. Without it every column widens to string.
53
+
54
+ const s = TimeSeries.fromJSON({
55
+ name: 'latency',
56
+ schema,
57
+ rows, // positional tuples [time, host, latencyMs] or objects { time, host, latencyMs }
58
+ sort: true, // input not already time-ordered? sort on construction (stable)
59
+ });
60
+ ```
61
+
62
+ Time cells accept ms-since-epoch numbers, `Date`s, or ISO strings **with an
63
+ offset** (`…Z`, `…+01:00`). A wall-clock string with no offset throws unless
64
+ you pass `parse: { timeZone: 'America/New_York' }`.
65
+
66
+ Other doors: `TimeSeries.fromPoints(points)` for wide `{ ts, a, b }` rows,
67
+ `fromColumns` for struct-of-arrays / `Float64Array`, `fromArrow` for an Arrow
68
+ table, `fromEvents`. `toJSON()` round-trips.
69
+
70
+ ### 2. Downsample, regrid, slide — three different verbs
71
+
72
+ ```ts
73
+ // Fewer rows out than in: one row per bucket.
74
+ const perMin = s.aggregate(Sequence.every('1m'), {
75
+ latencyMs: 'avg', // reducer by column …
76
+ p95: { from: 'latencyMs', using: 'p95' }, // … or a named output; reducers: sum avg min max count first last median stdev pNN
77
+ host: 'last',
78
+ });
79
+
80
+ // Same information, on a regular grid (hold / interpolate). No reduction.
81
+ const gridded = s.align(Sequence.every('10s'), { method: 'hold' });
82
+
83
+ // One output per input event, looking back over a window.
84
+ const rolled = s.rolling('5m', {
85
+ latencyMs: 'avg',
86
+ sd: { from: 'latencyMs', using: 'stdev' },
87
+ });
88
+ ```
89
+
90
+ `Sequence.every()` takes fixed durations only (`'10s'`, `'5m'`, `'1h'`,
91
+ `'1d'`). Months, weeks-in-a-zone, calendar days: `Sequence.calendar('month',
92
+ { timeZone })`. Common shortcuts: `s.baseline('latencyMs', { window: '1h',
93
+ sigma: 2 })` appends avg / sd / upper / lower in one pass;
94
+ `s.outliers(col, { window, sigma })` keeps only the rows outside the band.
95
+
96
+ ### 3. Per-entity, then flatten
97
+
98
+ ```ts
99
+ const perHost = s
100
+ .partitionBy('host') // every stateful operator below runs per host
101
+ .rolling('5m', { latencyMs: 'avg' })
102
+ .collect(); // one flat TimeSeries, `host` carried through (type and runtime)
103
+ // or .toMap() → Map<host, TimeSeries>
104
+ ```
105
+
106
+ `aggregate` and `rolling` under `partitionBy` carry the partition column
107
+ through in both the runtime **and** the static type (since 0.68), so
108
+ `e.get('host')` works on the collected result without naming it. On 0.67 or
109
+ older, name it in the mapping — `{ host: 'first', … }`.
110
+
111
+ ### 4. Clean, fill, join, read out
112
+
113
+ ```ts
114
+ const clean = s.dedupe().fill({ latencyMs: 'hold' }); // also 'linear', 'zero', gap caps
115
+ const joined = a.join(b); // on the time key; see API.md for options
116
+ clean.toPoints(); // [{ ts, host, latencyMs }, …] — chart-library friendly
117
+ clean.toRows(); // positional tuples
118
+ clean.column('latencyMs').mean(); // typed column: min/max/sum/mean/stdev/median/percentile
119
+ clean.column('latencyMs').toFloat64Array(); // zero-copy for canvas / WebGL loops
120
+ ```
121
+
122
+ Everything returns a **new** series. There is no `push` on a `TimeSeries`;
123
+ if you are appending, you want a `LiveSeries`.
124
+
125
+ ### 5. Streaming
126
+
127
+ ```ts
128
+ import { LiveSeries, Sequence } from 'pond-ts';
129
+
130
+ const live = new LiveSeries({
131
+ name: 'latency',
132
+ schema,
133
+ retention: { maxAge: '15m' }, // or { maxEvents: 10_000 }
134
+ ordering: 'reorder', // tolerate late rows …
135
+ graceWindow: '5s', // … up to this late
136
+ });
137
+
138
+ const view = live.partitionBy('host').rolling('5m', { latencyMs: 'avg' });
139
+ const stop = view.on('event', (e) => render(e.get('host'), e.get('latencyMs')));
140
+
141
+ live.push([Date.now(), 'api-1', 42]); // validated against the schema
142
+ live.pushMany(batch);
143
+ const snapshot = live.toTimeSeries(); // immutable batch copy for analytics
144
+ ```
145
+
146
+ `live.aggregate(Sequence.every('1m'), …)` emits `'bucket'` (partial) and
147
+ `'close'` (final) events. Retention bounds memory; `sample({ stride })`
148
+ between `partitionBy` and a long `rolling` bounds it further at firehose
149
+ rates.
150
+
151
+ ### React and charts
152
+
153
+ ```tsx
154
+ import { useLiveSeries } from '@pond-ts/react';
155
+ import {
156
+ ChartContainer,
157
+ ChartRow,
158
+ Layers,
159
+ LineChart,
160
+ YAxis,
161
+ } from '@pond-ts/charts';
162
+
163
+ const [live, snap] = useLiveSeries({
164
+ name: 'latency',
165
+ schema,
166
+ retention: { maxAge: '10m' },
167
+ });
168
+
169
+ <ChartContainer width={800} cursor="crosshair" panZoom>
170
+ <ChartRow height={240}>
171
+ <YAxis id="ms" />
172
+ <Layers>
173
+ {snap && <LineChart series={snap} column="latencyMs" axis="ms" />}
174
+ </Layers>
175
+ </ChartRow>
176
+ </ChartContainer>;
177
+ ```
178
+
179
+ Charts read a pond series directly — do the maths in pond (`rolling`,
180
+ `aggregate`, `align`) and hand the result to a layer. `useLiveSeries`'s snapshot is `null` before the first
181
+ push, hence the guard. `width` is a pixel
182
+ number or `'auto'` (the parent then needs a definite width, or nothing draws).
183
+ Hooks: `useTimeSeries`, `useLiveSeries`, `useSnapshot`, `useLiveQuery`,
184
+ `useDerived`, `useWindow`, `useCurrent`, `useLatest`.
185
+
186
+ ### Financial
187
+
188
+ ```ts
189
+ import '@pond-ts/financial/fluent'; // once, anywhere: adds studies to TimeSeries
190
+ import { TradingCalendar } from '@pond-ts/financial';
191
+
192
+ const studied = bars
193
+ .sma({ period: 20 })
194
+ .rsi({ period: 14 })
195
+ .bollinger({ period: 20 });
196
+ // or, function form: sma(bars, { period: 20 })
197
+ const cal = TradingCalendar.fromRules(
198
+ { timeZone: 'America/New_York', open: '09:30', close: '16:00' },
199
+ { from: '2026-01-05', to: '2026-02-13' },
200
+ );
201
+ ```
202
+
203
+ Studies read `'close'` by default, take **bar-count** periods, append
204
+ columns, preserve row count (warm-up rows are `undefined`). Sixty-plus of
205
+ them; `import { STUDIES } from '@pond-ts/financial/catalog'` lists them at runtime. Session-aligned bars: `ticks.aggregate(cal.barSequence('5m'), {...})`.
206
+
207
+ ## Mistakes agents actually make
208
+
209
+ 1. **Dropping `as const` on the schema.** Everything compiles and every
210
+ column is `string`. If `.get('x')` is not `number | undefined`, this is
211
+ why.
212
+ 2. **`aggregate` when you meant `rolling`, or vice versa.** `aggregate`
213
+ changes the row count (one per bucket); `rolling` keeps it (one per
214
+ event); `align` puts rows on a grid without reducing.
215
+ 3. **`Sequence.every('1M')` for months.** Not fixed-length → use
216
+ `Sequence.calendar('month', { timeZone })`.
217
+ 4. **Wall-clock strings without a zone.** `'2025-01-01T09:00'` throws; add
218
+ `parse: { timeZone }` or use offset strings / ms numbers.
219
+ 5. **Unsorted rows.** The constructor throws and names the row; pass
220
+ `sort: true` rather than sorting by hand.
221
+ 6. **Mutating.** Nothing mutates. Capture the return value.
222
+ 7. **Iterating events in a hot loop for a chart.** Use `column(name)` /
223
+ `toFloat64Array()` or hand the series to `@pond-ts/charts` — do not
224
+ rebuild point arrays per frame.
225
+ 8. **Mismatched package versions.** All `pond-ts` / `@pond-ts/*` at the same
226
+ version, always.
227
+ 9. **Reaching for a chart-library adapter first.** If the project uses React,
228
+ `@pond-ts/charts` consumes the series with no adapter; `toPoints()` is the
229
+ bridge for other libraries.
230
+
231
+ ## Where to read next
232
+
233
+ - `API.md` (this folder) — find any export and its source file.
234
+ - <https://pond-ts.org/llms.txt> — every docs page with a one-line
235
+ description; `https://pond-ts.org/llms-<area>.txt` for a single-fetch dump
236
+ of one area (`pond-ts`, `charts`, `financial`, …).
237
+ - <https://pond-ts.org/docs/pond-ts/mental-model> — one picture, and the
238
+ pandas / pondjs translation tables.
239
+ - <https://pond-ts.org/docs/how-to-guides> — end-to-end builds with the
240
+ friction already ironed out (dashboard, messy CSV ingest, histograms,
241
+ large series).
242
+ - Claude Code users: `/plugin marketplace add pond-ts/pond` then
243
+ `/plugin install pond-ts@pond-ts` installs skills for core, charts and
244
+ financial.
package/API.md CHANGED
@@ -40,13 +40,13 @@ next door is the point.
40
40
 
41
41
  ### Series classes & construction
42
42
 
43
- | Export | Purpose | Source |
44
- | ----------------------- | ------------------------------------------------------ | ---------------------------------------------------- |
45
- | `TimeSeries` | Immutable time-indexed collection, columnar storage | `packages/core/src/batch/time-series.ts` |
46
- | `ValueSeries` | Series keyed by a monotonic non-time value axis | `packages/core/src/batch/value-series.ts` |
47
- | `PartitionedTimeSeries` | Scoped view for per-partition stateful transforms | `packages/core/src/batch/partitioned-time-series.ts` |
48
- | `Sequence` | Infinite grid of time buckets (daily, hourly, every N) | `packages/core/src/sequence/sequence.ts` |
49
- | `BoundedSequence` | Finite ordered list of explicit interval buckets | `packages/core/src/sequence/bounded-sequence.ts` |
43
+ | Export | Purpose | Source |
44
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
45
+ | `TimeSeries` | Immutable time-indexed collection, columnar storage | `packages/core/src/batch/time-series.ts` |
46
+ | `ValueSeries` | Series keyed by a monotonic non-time value axis | `packages/core/src/batch/value-series.ts` |
47
+ | `PartitionedTimeSeries` | Scoped view for per-partition stateful transforms; `<S, K, By>` — `By` is the partition column names, carried into `aggregate` / `rolling` result types | `packages/core/src/batch/partitioned-time-series.ts` |
48
+ | `Sequence` | Infinite grid of time buckets (daily, hourly, every N) | `packages/core/src/sequence/sequence.ts` |
49
+ | `BoundedSequence` | Finite ordered list of explicit interval buckets | `packages/core/src/sequence/bounded-sequence.ts` |
50
50
 
51
51
  Static constructors on `TimeSeries`: `fromJSON()` (row tuples/objects),
52
52
  `fromColumns()` (struct-of-arrays; `number` + `string` value columns),
@@ -125,10 +125,11 @@ Value-axis wire types
125
125
  `arrayContainsAny()`, `arrayAggregate()`, `arrayExplode()`
126
126
  - **Gap fill / dedupe**: `fill()`, `materialize()`, `dedupe()`
127
127
  - **Aggregate/group**: `aggregate(sequence, spec)`, `reduce()`, `groupBy()`,
128
- `partitionBy()`, `byColumn()` (order-free, by column value),
128
+ `partitionBy()`, `byColumn(col, bins, mapping)` (numeric binning of a column into
129
+ fixed-`width` or explicit-`edges` bins, then reduce per bin — histograms),
129
130
  `rollingByColumn()`, `byValue(axis)` (project onto a `ValueSeries`)
130
131
  - **Windowing/smoothing**: `rolling(window, spec, opts)`, `smooth(column,
131
- method)` (EMA / Butterworth / Savitzky-Golay), `align(method, opts)`
132
+ method, opts)` (`'ema'` / `'movingAverage'` / `'loess'`), `align(method, opts)`
132
133
  - **Differential/statistical**: `diff()`, `rate()`, `pctChange()`,
133
134
  `cumulative()`, `scan()` (custom stateful reducer), `shift()`, `baseline()`
134
135
  (rolling avg/sd/bands), `outliers()` (deviation from baseline)
package/CHANGELOG.md CHANGED
@@ -8,7 +8,8 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
8
8
  under a single `v*` tag, so this file covers them all. Pre-1.0: minor bumps may
9
9
  include new features and type-level changes; patch bumps are strictly additive.
10
10
 
11
- [Unreleased]: https://github.com/pond-ts/pond/compare/v0.67.0...HEAD
11
+ [Unreleased]: https://github.com/pond-ts/pond/compare/v0.68.0...HEAD
12
+ [0.68.0]: https://github.com/pond-ts/pond/compare/v0.67.0...v0.68.0
12
13
  [0.67.0]: https://github.com/pond-ts/pond/compare/v0.66.0...v0.67.0
13
14
  [0.66.0]: https://github.com/pond-ts/pond/compare/v0.65.0...v0.66.0
14
15
  [0.65.0]: https://github.com/pond-ts/pond/compare/v0.64.0...v0.65.0
@@ -70,6 +71,33 @@ include new features and type-level changes; patch bumps are strictly additive.
70
71
 
71
72
  ## [Unreleased]
72
73
 
74
+ ## [0.68.0] — 2026-09-13
75
+
76
+ ### Added
77
+
78
+ - **Agent adoption tranche ([PND-ADOPTMETA] / [PND-ADOPTLINKS] /
79
+ [PND-LLMSTXT] / [PND-AGENTGUIDE] / [PND-SKILL] / [PND-CONTEXT7]).** Every
80
+ package now declares `keywords`, `homepage` and `bugs` (there were none —
81
+ `pond-ts` ranked last in `npm search "time series"`). Every tarball ships an
82
+ `AGENTS.md` (source `docs/agents/USING_POND.md`): which package for which
83
+ task, the core idioms, the mistakes agents make. `pond-ts.org/llms.txt` is
84
+ now llmstxt.org-shaped (titles + descriptions per page, one section per
85
+ docs area, `Optional` links to `API.md` / the agent guide) with per-area
86
+ `llms-<area>.txt` dumps so a single fetch stays small. A Claude Code plugin
87
+ marketplace lives in the repo (`/plugin marketplace add pond-ts/pond`) with
88
+ `pond-ts`, `pond-charts` and `pond-financial` skills. `context7.json`
89
+ configures docs-MCP indexing. Plan and baseline:
90
+ `docs/plans/PND_ADOPTION_PLAN.md`.
91
+
92
+ - **Agent guide + skill hardened by the first cold-start run** (`docs/agents/USING_POND.md`, shipped as `AGENTS.md`; `plugins/pond-ts/skills/pond-ts`): install with `@latest` and the `.d.ts` paths that carry signatures. Cold-start harness committed at `docs/adoption/cold-start/`.
93
+
94
+ ### Fixed
95
+
96
+ - **`pond-ts`: the partition column is now in the static type after a partitioned `aggregate` / `rolling` ([PND-PARTCOL]).** `series.partitionBy('host').aggregate(seq, { p95: { from: 'ms', using: 'p95' } }).collect()` always carried `host` at runtime (auto-injected as `'first'`) but the result type omitted it, so `e.get('host')` failed to compile — every fresh agent in the cold-start experiment hit or pre-empted it. `PartitionedTimeSeries` gains a third type parameter `By` (the partition column names, captured by `partitionBy`, default `never`), and the two schema-replacing operators are typed over `WithPartitionColumns<Mapping, By>` — the user's keys win, kind and all; missing partition columns are added as `'first'`. Composite partitions and typed `groups` carry through; `smooth` / `baseline` under `partitionBy` now also keep `K`. Additive: untyped views are unchanged.
97
+ - `@pond-ts/charts` and `@pond-ts/fit` READMEs (rendered on npm) and eight
98
+ docs pages pointed at the retired `pjm17971.github.io/pond-ts` site /
99
+ `pjm17971/pond-ts` repo; now `pond-ts.org` / `pond-ts/pond`.
100
+
73
101
  ## [0.67.0] — 2026-09-11
74
102
 
75
103
  ### Added
package/README.md CHANGED
@@ -202,6 +202,26 @@ The full guide is at **<https://pond-ts.org/>**.
202
202
  — TypeDoc output, every public class and method.
203
203
  - **[CHANGELOG](./CHANGELOG.md)** — what shipped in each release.
204
204
 
205
+ ## For coding agents
206
+
207
+ pond is built by agents and expects to be used by them. Three things exist so
208
+ an agent can go from "never heard of pond" to working code without a human in
209
+ the loop:
210
+
211
+ - **`AGENTS.md` + `API.md` ship inside every npm tarball** —
212
+ `node_modules/pond-ts/AGENTS.md` is a one-read guide (which package for
213
+ which task, the idioms, the mistakes agents make); `API.md` maps every
214
+ public export to its source file. Source:
215
+ [docs/agents/USING_POND.md](docs/agents/USING_POND.md), [API.md](API.md).
216
+ - **<https://pond-ts.org/llms.txt>** — every docs page with a one-line
217
+ description, plus `llms-<area>.txt` single-fetch dumps per package.
218
+ - **Claude Code plugin** — skills for core, charts and financial, versioned
219
+ with the library:
220
+ ```
221
+ /plugin marketplace add pond-ts/pond
222
+ /plugin install pond-ts@pond-ts
223
+ ```
224
+
205
225
  ## Examples
206
226
 
207
227
  - **[pond-ts-dashboard](https://github.com/pjm17971/pond-ts-dashboard)**
package/package.json CHANGED
@@ -1,7 +1,24 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.67.0",
4
- "description": "React hooks for pond-ts live time series",
3
+ "version": "0.68.0",
4
+ "description": "React hooks for pond-ts: subscribe to LiveSeries and derived views with throttled snapshots",
5
+ "keywords": [
6
+ "time-series",
7
+ "timeseries",
8
+ "typescript",
9
+ "streaming",
10
+ "analytics",
11
+ "react",
12
+ "hooks",
13
+ "live",
14
+ "realtime",
15
+ "dashboard",
16
+ "pond-ts"
17
+ ],
18
+ "homepage": "https://pond-ts.org/docs/react/",
19
+ "bugs": {
20
+ "url": "https://github.com/pond-ts/pond/issues"
21
+ },
5
22
  "license": "MIT",
6
23
  "repository": {
7
24
  "type": "git",
@@ -24,17 +41,18 @@
24
41
  "files": [
25
42
  "dist",
26
43
  "CHANGELOG.md",
27
- "API.md"
44
+ "API.md",
45
+ "AGENTS.md"
28
46
  ],
29
47
  "scripts": {
30
48
  "build": "tsc -p tsconfig.json",
31
- "prepack": "cp ../../README.md ./README.md && cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md && cp ../../API.md ./API.md && npm run build && cp cjs-fallback.cjs dist/cjs-fallback.cjs && find dist -name '*.map' -delete",
49
+ "prepack": "cp ../../README.md ./README.md && cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md && cp ../../API.md ./API.md && cp ../../docs/agents/USING_POND.md ./AGENTS.md && npm run build && cp cjs-fallback.cjs dist/cjs-fallback.cjs && find dist -name '*.map' -delete",
32
50
  "test": "npm run test:type && npm run test:runtime",
33
51
  "test:type": "tsc -p tsconfig.types.json",
34
52
  "test:runtime": "vitest run"
35
53
  },
36
54
  "peerDependencies": {
37
- "pond-ts": "^0.67.0",
55
+ "pond-ts": "^0.68.0",
38
56
  "react": "^18.0.0 || ^19.0.0"
39
57
  },
40
58
  "devDependencies": {