Commit graph

237 commits

Author SHA1 Message Date
Mario Zechner
be039fb316 feat(chord): Chord v1 and v2 on pi-schema, drop TypeBox
Schema helpers are a thin layer over pi-schema's builders with the same JSON,
so fingerprints and stored data are unchanged (proven by schema-switch tests and
a store written by the TypeBox code). Checks through pi-schema; error messages
are pi-schema's; format is an annotation. v1 contracts take any JSON Schema.
map(bytes()) works.
2026-11-01 10:15:02 +00:00
Mario Zechner
2c8d1feb14 docs(chord): the schema switch decisions 2026-11-01 00:36:33 +00:00
Mario Zechner
6d4b744363 docs(chord): the schema package is built 2026-10-31 21:47:22 +00:00
Mario Zechner
6af92c7950 docs(chord): the plugin model, a primer 2026-10-31 21:02:36 +00:00
Mario Zechner
20362c155e fix(chord): widen the origin-record heap bound for CI noise 2026-10-31 20:52:13 +00:00
Mario Zechner
cc08278a62 fix(chord): slice 10 http builds without DOM types 2026-10-31 20:46:26 +00:00
Mario Zechner
b22c5f6941 docs(chord): slice 10 as built (design 23, spec, explainer) 2026-10-31 20:43:29 +00:00
Mario Zechner
8959ad6e68 feat(chord): Chord v2 slice 10, HTTP and workers
chord/next/http: a Web fetch handler built from the registry Http (routes, wraps,
sockets, hosts, relays, CSP sources) and Authenticators, responses as descriptions,
a security baseline on by default, Chord's own Node listener as a host-lifetime
object, nodeRequest for apps mounting it, links and plugin sockets.
chord/next/workers: a forked worker per address, started on demand, stopped when
idle, never restarted by itself, plugins built by the server and shipped.
Plugins: kinds with platform and host packages, createPluginRuntime, scripts(kind),
rollout results per host, imports of other plugins by name. Kernel: RouteHandle
(retry, suspend), no route backoff, anonymous host.root, origins only from relays.
ws is an optional peer dependency.
2026-10-31 20:40:36 +00:00
Mario Zechner
81f3cd4127 docs(chord): a schema package beneath pi-ai and Chord 2026-10-31 20:06:14 +00:00
Mario Zechner
0baf611f04 docs(chord): API versions in import paths; the plugin model proposal 2026-10-31 19:07:10 +00:00
Mario Zechner
2b06c437ce docs(chord): settings are arguments, extensions are registries 2026-10-31 18:52:54 +00:00
Mario Zechner
83740ffa7a docs(chord): CSP nonce per response 2026-10-31 18:33:24 +00:00
Mario Zechner
d52e953fa8 docs(chord): slice 10 route overhead accepted 2026-10-31 17:47:31 +00:00
Armin Ronacher
b4c2e92acb fix: remove vulnerable dependency chains
Replace build-time shell utilities with Node filesystem operations and retire the native sandbox example in favor of existing isolation options. Upgrade glob matching and worker-test dependencies and refresh the lockfiles.
2026-10-31 17:54:29 +01:00
Mario Zechner
f0646a00fb docs(chord): slice 10 fix round small points 2026-10-31 15:57:13 +00:00
Mario Zechner
ed2bdde64b docs(chord): HTTP core as a fetch handler, Node listener as the easy path 2026-10-31 15:04:43 +00:00
Mario Zechner
56cae78234 docs(chord): plugins import each other by name 2026-10-31 14:46:28 +00:00
Mario Zechner
112a8b46f3 docs(chord): tutorial: base code vs plugins, shipped plugins, subpaths 2026-10-31 14:43:24 +00:00
Mario Zechner
bb36171aac docs(chord): tutorial: only the server builds 2026-10-31 14:28:28 +00:00
Mario Zechner
86338abbd8 docs(chord): tutorial: loading explained (build vs evaluate, host packages, why plugins.load) 2026-10-31 14:26:12 +00:00
Mario Zechner
fe6211607b docs(chord): tutorial: persisted documents and tables 2026-10-31 14:09:23 +00:00
Mario Zechner
dae7bd8fcb docs(chord): tutorial: an object's parts before they are used 2026-10-31 14:07:01 +00:00
Mario Zechner
436d99e04b docs(chord): tutorial: one schema for contract and document 2026-10-31 14:01:40 +00:00
Mario Zechner
a34444d6bd docs(chord): tutorial: overview figure, client hosts 2026-10-31 13:56:14 +00:00
Mario Zechner
081f28bad7 docs(chord): tutorial on hosts and plugins 2026-10-31 13:50:20 +00:00
Mario Zechner
e22468919b docs(chord): HTTP server as a native object; the opinionated app kit as the next design pass 2026-10-31 13:47:28 +00:00
Mario Zechner
b79f21095d docs(chord): slice 10 explainer (HTTP and workers) 2026-10-31 13:30:29 +00:00
Mario Zechner
07309b63eb docs(chord): slice 10 security decisions: origins only from relays, public worker errors, hosts by contribution, the HTTP baseline 2026-10-31 13:28:07 +00:00
Mario Zechner
44d9fb5f6e docs(chord): slice 10 spec wording from the build 2026-10-31 09:18:58 +00:00
Mario Zechner
9b7a44c48d docs(chord): slice 11 draft, P1-P2, one definition per facet kind 2026-10-31 08:22:49 +00:00
Mario Zechner
e4adba965e docs(chord): remove the stale v2 explainer (from before slice 1) 2026-10-31 08:02:27 +00:00
Mario Zechner
bc9a20f847 docs(chord): slice 10 approved 2026-10-31 07:56:35 +00:00
Mario Zechner
61f73f2a80 docs(chord): slice 10 spec review round 2 folded (Q1-Q6), ready to build 2026-10-31 07:56:28 +00:00
Mario Zechner
918c6ffc22 docs(chord): slice 10 spec review folded (R1-R6), no automatic worker restarts, app kit malleable by plugins 2026-10-30 22:57:59 +00:00
Mario Zechner
9e4868a605 docs(chord): slice 10 points D9-D12, RouteHandle.retry, design §23 folded 2026-10-30 21:12:13 +00:00
Mario Zechner
f8497996fe docs(chord): slice 10 spec draft, HTTP points D1-D8 2026-10-30 21:00:20 +00:00
Mario Zechner
a14cdf90f0 feat(chord): v2 slice 7c, plugins component and per-plugin load and reload
Plugin discovery, esbuild builds (optional peer dependency), vm evaluation with
pluginFile and mapStack, dependency installs, a watcher with dirty marks and
rollout across hosts; host.load and host.reload per plugin with the closure rule;
examples 35-39 as folders with real plugin directories.
2026-10-30 18:18:23 +00:00
Mario Zechner
b7e8249520 docs(chord): 7c build: abort after commit names what it applied, per-plugin wording, examples 2026-10-30 18:17:46 +00:00
Mario Zechner
3bbb06aad7 docs(chord): 7c closure rule kept as is; review wording 2026-10-30 16:27:15 +00:00
Mario Zechner
26e05e64f0 docs(chord): reload's failed option for plugins kept before staging 2026-10-30 15:42:41 +00:00
Mario Zechner
318d9add68 docs(chord): one failed list in load and reload reports 2026-10-30 15:01:20 +00:00
Mario Zechner
18a155e2f5 docs(chord): slice 7c spec (plugins), per plugin at startup and reload 2026-10-30 14:56:23 +00:00
Mario Zechner
50af8c1601 refactor(chord): simplification audit of slices 6a-7b
The owner's audit decisions (decisions.md, "Simplification audit"): cut the reload-only
installing state (staging is synchronous) and the static registry cycle edges (the
runtime guard stays); retry propagation by a visited set and a hop budget (retry.hops)
instead of operation ids and through lists; a pure swap sends holds a fresh bound; one
rule after a live failure (every member followed until the admitted commits published);
parked_long for any long park, naming the first blocker in declaration order with its
state; one seal token per attempt. Keys follow the old instance during a restart's drain
like members. src/next: about 255 code lines fewer.
2026-10-30 13:30:54 +00:00
robopipi[bot]
50d9f823e4
fix(chord): remove whole ANSI escape sequences from tool output (#11607)
`sanitizeOutput()` in `@earendil-works/chord/output` deleted the ESC
byte (0x1b) along with the other control characters, but it left the
rest of each escape sequence in place. Colored tool output such as
`\x1b[31mERROR\x1b[0m` came back from `OutputBuffer.snapshot()` as
`[31mERROR[0m`. Because the ESC byte was already gone, later ANSI
stripping could no longer recognize the leftover fragments.

`sanitizeOutput()` now removes whole 7-bit escape sequences before it
removes single control characters. It handles:
- CSI sequences (colors, cursor and erase commands)
- string sequences (OSC, DCS, APC, PM, SOS) terminated by BEL or `ESC \`
- short `ESC x` forms such as `ESC ( B` or `ESC 7`

`snapshot()` sanitizes the concatenated retained text, so a sequence
split across pushed chunks is also removed.

**Testing**
- Added a regression test in `packages/chord/test/output.test.ts`. It
covers SGR colors, cursor and erase CSI, charset and short escapes, OSC
8 hyperlinks and an OSC title, plus an `OutputBuffer` fed a color
sequence split across three chunks. The test fails without the change
and passes with it.
- `test/output.test.ts` and `test/output-skip.test.ts` pass.
- Biome is clean. The only `tsc` errors in `npm run check` are in
`packages/ai` tests and are unrelated to this change.
- The durable package test results are the same with and without the
change: 71 test files fail on both, and every individual test that runs
passes.
- Reproduction from the issue: before the change both lines printed
`"[31mERROR[0m\n"`; after it, both print `"ERROR\n"`.

Fixes #11604

Requested by @badlogic

Co-authored-by: triagent <triagent@localhost>
2026-10-30 12:17:49 +01:00
Mario Zechner
e5c6182bab feat(durable): group commit and batch Storage.commit
A Session no longer holds its line while a commit is stored. Commits that
arrive while one storage call is in flight go out together in the next call,
each with its own seq and outcome; a job runs until it touches a key an
unpublished commit wrote, then waits for that commit's publication. Outcomes
are delivered in line order; publication is in line order, one commit per
macrotask. The scheduler's decisions run as regions that record the keys they
read and rerun after a wait, with side effects only after a clean check.

Storage.commit(batches, receive, context) replaces commit(writes, adopt,
context): prefix semantics (Durable's own checks refuse a batch and keep the
ones before it; any other failure rejects the call), receipts per stored
batch, optional publishing() scope. Memory, SQLite, JSONL, IndexedDB and
StoreStorage implement it natively; StoreStorage through the new
ChordStore.commitSeries (one store transaction per call), replacing
commitInBatch.

A normal run makes no storage reads: bounded record cache, conversation
tails, task-document index, kept context ranges. A tool slot's running status
and a generation's attempt are stored with the next commit (12 instead of 14
commits per run).

One Harness with 128 conversations over storage with a 4 ms round trip: about
5 -> 440 agent runs per second. Design: packages/durable/docs/group-commit.md.
2026-10-30 10:41:11 +00:00
Mario Zechner
4b535d57ea feat(chord): slice 7b, reload in the kernel
host.reload(facets, ctx): staging into a staged table with a recording self (all or
nothing), one commit (types, registries, contributions; per-name wakes; installing
holds), and each object's fate: pure swap in place, native restart after its drain,
retry on the new code, or its end by its type's removal, with a report. Old calls
finish on old handles (R15 for documents and tables), routines hand over per object,
jobs keep their versions (accepts, blocked { version }, persisted runs per R3),
registries swap providers and contributions in one batch, holds are kept,
re-subscribed or unbound with failed { waiting } (model §5), accepts maps older
consumers' state, arguments, results and keyed members.

References are the only indirection (owner, 2026-10-29): a consumer's watches and
derives attach through the reference, which passes them straight to the object
instance's own document or derive, moves them to a new instance (one frame) and keeps
its last values while unbound; MemberSource, keyed-members and the per-version
hand-over are removed. Older consumers read through the instance's shared mapping
per version. Examples 33-34, reload benchmark.
2026-10-30 08:09:06 +00:00
Mario Zechner
0c3675e647 docs(chord): slice 7b spec: reload in the kernel 2026-10-29 13:05:53 +00:00
Mario Zechner
ec7852988e docs(chord): slice 7b decisions as recommended 2026-10-29 13:02:46 +00:00
Mario Zechner
ba7bdb9afc docs(chord): slice order: 7b, 7c, 10, 11, telemetry last 2026-10-29 12:44:38 +00:00
Mario Zechner
b857fbd8a9 docs(chord): slice 7b brief: plugin dependencies 2026-10-29 12:32:09 +00:00