AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Highly optimised, fully typed Timeseries library for TypeScript
Schema-driven events, composable batch transforms, push-based streaming
ingest, multi-entity partitioning — and, optionally, React hooks and
canvas charts that read the series directly. All strict TypeScript end to
end, all immutable.
pond-ts is the TypeScript-first successor to
pondjs, rewritten from scratch with a
focus on type safety, composability, and the live-streaming patterns
that pondjs never grew.
Three packages carry most projects. The core has no dependency on the other
two; add them only if you render.README 전문 보기 ↗Highly optimised, fully typed Timeseries library for TypeScript
Schema-driven events, composable batch transforms, push-based streaming ingest, multi-entity partitioning — and, optionally, React hooks and canvas charts that read the series directly. All strict TypeScript end to end, all immutable.
pond-ts is the TypeScript-first successor to pondjs, rewritten from scratch with a focus on type safety, composability, and the live-streaming patterns that pondjs never grew.
Three packages carry most projects. The core has no dependency on the other two; add them only if you render.
| Package | What it is | Needs |
|---|---|---|
pond-ts — core | TimeSeries (batch) and LiveSeries (streaming) with one operator vocabulary: aggregate, rolling, align, fill, partition, join, typed columns. Node or browser, no React. | nothing |
@pond-ts/charts — optional | Declarative React charts on a canvas data plane that consume a pond series with no adapter: line, area, band, bar, scatter, box, candlestick, heat map; cursors, selection, pan/zoom, annotations. | pond-ts, @pond-ts/react, React 18/19 |
@pond-ts/react — optional | Hooks to own a series in a component and read live views on a throttled snapshot cadence (useLiveSeries, useSnapshot, …). | pond-ts, React 18/19 |
npm install pond-ts # core — enough for Node pipelines and non-React apps
npm install @pond-ts/charts @pond-ts/react pond-ts # add the React chart stack
Two domain packages (@pond-ts/financial for markets,
@pond-ts/fit for activity data) and one experimental
runtime (@pond-ts/process) sit on top — see
Domain packages below. All six release together under
one version; keep them in step.
event.get('cpu') returns number | undefined straight from
the schema; no as casts.filter, map,
aggregate, rolling, diff, rate, fill, cumulative,
sample, reduce all exist on both TimeSeries and LiveSeries.partitionBy('host') routes per
entity; rolling / aggregate / fill / sample over a partitioned
view all become per-entity automatically.series.column('cpu') returns a
schema-narrowed typed column with single-pass reductions
(min/max/sum/mean/stdev/median/percentile/minMax),
index downsampling (bin), and a zero-copy toFloat64Array() for
canvas / WebGL draw loops — no per-event allocation on the hot path.import { Sequence, TimeSeries } from 'pond-ts';
const schema = [
{ name: 'time', kind: 'time' },
{ name: 'cpu', kind: 'number' },
{ name: 'requests', kind: 'number' },
{ name: 'host', kind: 'string' },
] as const;
const cpu = TimeSeries.fromJSON({
name: 'cpu',
schema,
rows: [
['2025-01-01T00:00:00Z', 0.31, 120, 'host1'],
['2025-01-01T00:01:00Z', 0.44, 135, 'host2'],
['2025-01-01T00:02:00Z', 0.52, 141, 'host1'],
['2025-01-01T00:03:00Z', 0.48, 128, 'host1'],
['2025-01-01T00:04:00Z', 0.63, 166, 'host3'],
],
});
const byMinute = cpu.aggregate(Sequence.every('1m'), {
cpu: 'avg',
requests: 'sum',
host: 'last',
});
const bands = cpu.baseline('cpu', { window: '2m', sigma: 2 });
// ^ appends rolling avg / sd / upper / lower in one pass.
const anomalies = cpu.outliers('cpu', { window: '2m', sigma: 2 });
// ^ schema-preserving filter — same columns, just the spikes.
The full batch surface (align, rolling, smooth, groupBy, join,
reduce, diff, rate, fill, dedupe, materialize, sample,
partitionBy, pivotByGroup, …) follows the same shape: TimeSeries
in, TimeSeries out, schema preserved.
import { LiveSeries, Sequence } from 'pond-ts';
// 1. Same schema; this is a live append buffer with retention.
const live = new LiveSeries({
name: 'cpu',
schema,
retention: { maxAge: '10m' }, // keep only the last 10 minutes
});
// 2. Push as events arrive. Each push is validated against the schema.
live.push([Date.now(), 0.45, 128, 'api-1']);
// 3. Compose live views — incremental, push-driven, eviction-aware.
const recentAvg = live.rolling('5m', { cpu: 'avg' });
recentAvg.on('event', (e) => render(e.get('cpu')));
// 4. Snapshot to a TimeSeries for batch analytics at any time.
const snap = live.toTimeSeries();
The full live surface (filter, map, select, window, aggregate,
rolling, reduce, diff, rate, pctChange, fill, cumulative,
sample) is incremental — events flow, views emit, retention bounds
memory.
@pond-ts/charts reads a TimeSeries or LiveSeries directly — do the maths
in pond, hand the result to a layer. Rows share one x scale, so they pan,
zoom and track the cursor together.
import {
BandChart,
ChartContainer,
ChartRow,
Layers,
LineChart,
YAxis,
CrosshairCursor,
} from '@pond-ts/charts';
// `bands` is the baseline() result from the batch quick start:
// cpu + avg / sd / upper / lower columns.
export function CpuChart({ width }: { width: number }) {
return (
<ChartContainer width={width} panZoom>
<CrosshairCursor />
<ChartRow height={240}>
<YAxis id="cpu" format=".0%" />
<Layers>
<BandChart series={bands} lower="lower" upper="upper" axis="cpu" />
<LineChart series={bands} column="cpu" axis="cpu" />
</Layers>
</ChartRow>
</ChartContainer>
);
}
Pass width="auto" to measure the parent instead. Live data renders through
the same layers: own the series with useLiveSeries from @pond-ts/react
and pass its snapshot as series.
partitionBy routes events into per-key buffers. Every stateful
operator downstream of partitionBy runs per-partition automatically:
const perHost = cpu
.partitionBy('host')
.rolling('5m', { cpu: 'avg', cpu_sd: 'stdev' });
// .collect() fans the per-partition outputs back into a flat TimeSeries
// with the partition key auto-injected as a column.
const flat = perHost.collect();
Same shape on the live side — live.partitionBy('host') returns a
LivePartitionedSeries whose rolling / fill / diff / sample
methods all maintain per-partition state.
At firehose rates, a long rolling baseline blows the heap. sample({ stride: N }) decouples baseline length from event rate; chain it
between partitionBy and rolling:
// Per-host 1-in-10 stride feeding a per-host 5m baseline.
live
.partitionBy('host')
.sample({ stride: 10 })
.rolling('5m', { cpu_avg: 'avg', cpu_sd: 'stdev' });
For visualization, the snapshot side ships reservoir sampling too — single-pass Algorithm R, sorted by key, fixed point count regardless of source size:
const points = series.sample({ reservoir: { size: 500 } }).toRows();
// 500 uncorrelated points drawn uniformly from the source.
Measured against three reference points (snapshot 2026-07-30; full tables, methodology, and every losing number in the benchmark reference):
aggregate up to 453×,
median 157×, and select / rename effectively instant (O(1)
column rebinds).ema,
mean, median / percentile; behind ~1.1–1.9× on the rolling
studies. A five-study strategy pass runs 1.28× slower than pandas'
Cython kernels.bollinger 0.53×, strategy stack 0.85×, ema 0.32× — lower is
pond-ts faster), behind 4–9× on whole-column reductions (the SIMD gap;
half-closed already by blocked summation) and on raw ingest, where
pond-ts front-loads validation the dataframe engines defer.[PND-PROCPAR]).The honest one-line version: the rewrite beat its predecessor by an order of magnitude, holds its own per-core against the native engines on the composite queries that dominate real workloads, and knows exactly where it is behind. Run locally:
npm run build && node packages/core/bench/vs-pondjs.cjs
Optional, domain-specific, all on plain pond series:
@pond-ts/financial
— sixty-plus oracle-verified technical studies (SMA, EMA, RSI, MACD,
Bollinger, ATR, VWAP, …) that append columns to a bar series, a fluent
bars.sma({ period: 20 }).rsi({ period: 14 }) form, and a
TradingCalendar so session-aligned bars, rolling windows and chart axes
stop at the close.@pond-ts/fit — fitness
and activity analytics: typed quantities with units, canonical activity
series, geo (distance, elevation, best efforts), power (NP / IF / TSS,
curves), heart-rate zones, splits.@pond-ts/process —
experimental. Computations as data: processing graphs authored fluently
or composed as JSON, resolved against a declared op vocabulary with
content-addressed caching, provenance and per-node timings. The API is
expected to move.The full guide is at https://pond-ts.org/.
LiveSeries, live transforms, triggering.All six packages release together under one version — keep them in step.
@pond-ts/process) or internal is excluded.Details: pond-ts.org/docs/reference/versioning.
pond is built by agents and expects to be used by them. Three things exist so an agent can go from "never heard of pond" to working code without a human in the loop:
AGENTS.md + API.md ship inside every npm tarball —
node_modules/pond-ts/AGENTS.md is a one-read guide (which package for
which task, the idioms, the mistakes agents make); API.md maps every
public export to its source file. Source:
docs/agents/USING_POND.md, API.md.llms-<area>.txt single-fetch dumps per package./plugin marketplace add pond-ts/pond
/plugin install pond-ts@pond-ts
The repo is an npm-workspaces monorepo with six published packages
(pond-ts, @pond-ts/react, @pond-ts/charts, @pond-ts/financial,
@pond-ts/fit, @pond-ts/process). Node 18+ for runtime; Node 20+ for the
docs site (Docusaurus).
npm install # one-time, hoists deps for all packages
npm run build # build both packages
npm test # runtime + type-level tests on both packages
npm run format # prettier write across the repo
npm run verify # format check + build + test (CI parity)
Each package lives under packages/<name>/ (core is pond-ts, the rest
match their scoped names). Docs live in website/ — its own npm root, not a
workspace.
MIT