trellis
Version:
Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications
354 lines (306 loc) • 19.3 kB
Markdown
# Changelog
Notable changes by release date and version. See
[trellis.computer/changelog](https://trellis.computer/changelog) for the public
site copy.
## trellis [4.0.0] — 2026-08-04
**Git is now the sole authority over file bytes. The op-log can no longer write
file state. (ADR 0038)**
The structural bug that caused the `9801056`-class silent revert — `git sync`
materializing stale op-log bytes over newer disk content — is fixed by removing
the second authority entirely, not by adding another guard. Two systems
claiming authority over the same bytes is unsound; someone always forgets to
guard one of the paths. ADR 0038 makes git the only writer of bytes and the
op-log a pure provenance layer that is *incapable* of clobbering disk.
- **`syncIntegrationToGit` commits the working tree as-is** (ADR 0038). No more
`buildFileStateAtOp` / `materializeToDisk` reconstruction from op-log blobs —
it checks out `-B`, `add -A`, and commits the actual bytes on disk. `git sync`
can never overwrite a newer file with stale op-log state.
- **Non-materializing `vcs:gitSync` annotations.** Each sync records
`vcs:gitSync { gitCommitHash, gitBranch }` on the causal stream. The op-log
holds provenance (who/what/why, milestones, decisions, lane lifecycle) — never
byte state. `journalWorkingTreeToOps` is diagnostic-only; sync no longer calls
it.
- **Promote delivers bytes via git, not replay.** `promoteLane` now runs a git
branch merge (lane branch → integration) as the byte delivery, then rechains
annotation ops onto integration. `mergeLaneWorktree` returns
`merged | up-to-date | failed`; a real conflict aborts before replay.
- **Lane worktrees are git checkouts, not op-log materials.** Entering a lane
auto-commits the agent's working bytes (`commitWorktree`) onto the lane
branch; re-entry sees the lane's files from git. `lanes.worktreeBind` gives
true per-agent isolation — one agent's `revert`/`reset` physically cannot
touch another's files.
### Breaking changes
- `GitSyncResult.refused` and `reason` are removed — sync never refuses and
there is no journal catch-up to race. The CLI "refused" branches in `git sync`
and milestone auto-commit are gone.
- `syncIntegrationToGit` no longer takes `blobResolver`, `integrationOps`, or
`headOpHash`. `resolveIntegrationHead` was removed from the `git-sync` module.
- `trellis git sync` does **not** journal previously-unjournaled edits — disk
edits to tracked files now flow through git commits, not file-materializing
ops.
### Fixes
- **`trellis lane list -p <dir>` resolved from cwd instead of the target.** The
child `-p` default of `.` shadowed the parent command's `-p`, so `lane list`
walked up from the shell cwd and reported an empty/mismatched lane set. The
list action now resolves paths the same way as every other `lane` subcommand.
- workflow-pipeline-primitives test mock brought in line with the real
`EAVStore` API (`addFacts`/`getLinksByEntity`), and the mock pool emits
`task:completed` so DAG runs terminate.
## trellis [3.4.0] — 2026-07-24
**Lane ops were unverifiable; criterion removal (TRL-1, TRL-102).**
- **Every op minted inside a lane failed hash verification — fixed (TRL-102).**
`createVcsOp` hashes `{kind, timestamp, agentId, previousHash, vcs}`, and
`stampLaneId` then mutated `op.vcs` — *after* the hash was computed. Measured
on this repo: **1334 of 1334 ops across 27 lane journals failed
`verifyVcsOpHash`; 1334 of 1334 verified once `vcs.laneId` was removed.** Both
ingest paths reject on `hash-mismatch`, so lane ops could never have been
exchanged with a peer — this gated peer sync of agent lanes and any Iroh
transport work.
- **Lane is now envelope, not identity.** `VcsOp.laneId` is a top-level field,
outside the preimage by construction. The same semantic op in two lanes now
hashes identically — required for cross-peer dedup and for cherry-pick not to
rewrite op identity, both of which set-reconciliation depends on.
- **`vcs.laneId` is retained where it is *subject* data.** `vcs:laneCreate`,
`vcs:laneDrop` and `vcs:testRun` are *about* a lane, pass `laneId` at mint, and
keep it hashed — excluding it would collapse `laneCreate lane-A` and
`laneCreate lane-B` to one identity. Promote paths carry the source lane as
envelope provenance instead of baking it into a promoted op's hash.
- **Existing journals migrated in place, no hash rewritten.** The stored hashes
were already correct for lane-free payloads, so migration only relocated the
field: 0/1334 → **1334/1334 verifying**. Verify-guided — an op was rewritten
only if it failed verification *and* stripping `laneId` made it pass.
Integration's 47 subject-role ops were untouched.
- **`VcsOp` envelope vs payload is now explicit.** `vcs` is payload (hashed);
top-level fields are envelope (not hashed). `facts`/`links` were already used
this way — `RemoteManager` tags pulled ops with `{e:'op', a:'remote'}` so
`trellis log --remote` can filter them *without* invalidating the remote's
hash. Documented rather than discovered.
- **Criterion removal (TRL-1):** `trellis issue ac-rm <id> <index>` and
`vcs:criterionRemove`. Removal is a **tombstone, not an erasure** — ids are
minted as `ac-${count+1}`, so deleting the entity would let a later add mint
the id of a *surviving* criterion (remove ac-2 of 3, next add collides with
ac-3 and merges into it). Retracted criteria keep their id and are filtered
from projections.
- **Promote gate now typechecks.** `promote.require` was `["smoke"]` — a single
VCS test file that cannot see a type break. An agent widened an exported
interface and the gate waved it through. Added a `check` suite (`npm run
check`, ~3s); `promote.require` is now `["smoke", "check"]`.
- **`.gitignore`: `.trellis/tests.json` was never actually tracked.** Git cannot
re-include a file whose parent directory is excluded, so `.trellis/` +
`!.trellis/tests.json` silently ignored the manifest — the file defining the
promote gate was unversioned. Now `/.trellis/*` + negation, plus
`*/**/.trellis/` for stray repos created by running the CLI in a subdirectory
(which root-anchoring would otherwise have un-ignored).
**Breaking**
- `VcsOp.vcs.laneId` is no longer set on stamped ops; read `VcsOp.laneId`
instead. Subject ops (`laneCreate`/`laneDrop`/`testRun`) are unchanged.
- New op kind `vcs:criterionRemove`; older readers will not project it.
**Migration:** lane journals in existing repos still carry `vcs.laneId` and will
fail verification until relocated. No hashes change — the stored hash is already
the lane-free one.
**Also in 3.4.0 (kernel / VCS / TML)**
- **Lane promote reliability:** snapshot-head invariant fixes perpetual
"Integration head moved during promote" on issue-branch closes; coordination
hard-conflict skip v0.1 for sibling lanes (TRL-301–302, TRL-297–298).
- **Promote == milestone + git:** `trellis milestone --commit` auto-commits on
integration; promote boundary locked to issue close; cross-agent file ownership
and lane coherence signals (TRL-117).
- **`trellis lane split`:** open a domain lane without requiring an issue.
- **`trellis doctor`:** probes mutation safety before contested writes.
- **Op log safety:** append-only JSONL mirror; destructive guards; remote sprite
backup specs (ADR follow-through).
- **TML runtime:** attribute projection on `/tml-lanes`; PeerDriver materializes
ops and queries with real TQL; Phase 4 vantage shell resolution; slimmer live
bundles (decompose browser-safe ~5.7 KB).
- **Theme contract Phase C:** fractal vantage + shell morph; unified
`runtime-theme.css` scrubber hardening (TRL-167/281).
- **Promote gate:** whole-suite check includes query-stress harness; 12 formerly
skipped CLI tests un-gated and passing.
- **ADR 0022 / 0026:** grants as ops; defaultVisibility floor; issueType as
field not title prefix.
**In development (not in this release's npm story)**
- **`trellis admin` operator console** — substantial work on `main` (TML
projections, lane datatable, chrome polish). UI modules are **not yet
prebundled for global `npm install`**; use a repo checkout for admin. Not
headline in 3.4.0 — kernel/VCS/TML CLI improvements are the ship focus.
## trellis [3.3.0] — 2026-07-14
**Canonical op hashing + op provenance (ADR 0021).** Op hashes are now
verifiable content addresses, and every op records who asserted it.
- **Op hashes were not recomputable — fixed.** The kernel hashed the *caller's*
payload object while each backend independently reconstructed a
differently-shaped one to store (`links: []` injected, key order drifting). No
op in any existing log could be re-derived from storage. `hash` was a
unique-ish identifier, not a content address. Undetected because nothing ever
re-verified a kernel op.
- **One serializer:** `core/persist/canonical-op.ts`. Mint (`hashKernelOp`) and
persist (every backend's `append()`) now go through the same canonicalization;
the bytes in the `payload` column *are* the hashed bytes.
- **`verifyOpHash(op)`** — new, and did not exist before. Returns
`{ valid, legacy }`.
- **Preimage is JSON, not `|`-joined.** Closes an injection where
`agentId="a|b", previousHash="c"` and `agentId="a", previousHash="b|c"`
produced identical preimages.
- **Op provenance (`actorType` + `origin`, SemType-aligned)** on every op,
inside the hash — provenance that can be altered without invalidating the hash
is decoration, not provenance. Resolved per-call
(`payload ?? ctx ?? kernel default`), because one `TenantPool` kernel serves
both HTTP and MCP. Wired at every mint site: HTTP, MCP, cron, sync, import,
agent harness, and the agent plugins.
- **Value-level provenance:** `Fact.meta` (`confidence`, `dataTypeId`,
`sources`). Rides inside `facts[]`, so it is hash-covered for free.
- **CLI graph writes are `VcsOp`s, not `KernelOp`s** — so kernel provenance
never covered them. Provenance now rides `VcsPayload` instead, hash-covered
via `hashVcsOp` with **no preimage change and no migration**. Set per engine
construction (CLI/MCP/UI/sync/migration/SDK). Covers `vcs:store*` ops; branch,
file and milestone ops are not yet covered.
- **`VcsMiddleware` deleted.** Never constructed, and written against a contract
that never existed — `handleOp` is documented as *"can throw to block the
operation"*, an observe-or-throw chain, so its decomposed ops were silently
discarded. `engine.ts` already does the same decomposition inline, which is
the path that actually runs. `DESIGN.md`'s
`kernel.mutate → VcsMiddleware → decompose` sequence documented a flow that
was never built and has been corrected.
**Breaking**
- `kernel.mutate(kind, payload)`: `payload.meta` removed (no caller used it),
`payload.provenance` added.
- `VcsMiddleware` no longer exported from `trellis/vcs`.
- Newly minted kernel ops use preimage v2 and hash differently from v1. **v1 ops
are grandfathered** — reported `{ valid: true, legacy: true }`, never
reverified, because their preimages are unrecoverable by construction. Every
log keeps a permanent unverifiable v1 prefix; this is the bug, not the fix.
- `KernelOp` gains `v` and `provenance`; `Fact` gains optional `meta`.
**Migration:** none required. Existing kernel logs boot and replay unchanged;
existing `ops.json` journals verify unchanged.
## trellis [3.2.6] — 2026-07-11
- **QR pairing (ADR 0020 Phase 1 start):** `trellis pair start|join|approve`
renders a compact Unicode QR in the terminal (TTY default; `--no-qr` /
`--qr`). Same OOB payloads as Phase 0 — `renderPairingQr` / `encodePairingQr`
via `uqr`.
- **Sprite relay blobs (ADR 0016):** `startServer({ presenceRelay })` accepts
full `RealtimeRelayOptions` (including `blobStore`). Sprite deploy entrypoints
mount
`presenceRelay: { path: '/rt', blobStore: () => new BlobStore('/home/sprite/trellis-db') }`
so `/blob` is available on `*.sprites.app` alongside `/rt`.
- **`BlobStore` export:** re-exported from `trellis/server` for deploy
entrypoints and embedders.
- **Redeploy required:** existing sprites still running a pre-3.2.6 bundle only
have `/rt`. Re-run `trellis deploy --name <sprite>` (or the app's
`smoke:deploy`) after publishing this kernel, then point clients at
`VITE_RELAY_URL=wss://<sprite>.sprites.app/rt` (HTTP `/blob` shares that
origin).
## trellis [3.2.5] — 2026-07-11
- **Agent coordination (Phase 2):** session-scoped lanes via
`trellis lane ensure --session <id>`; issue claim lock (`vcs:issueClaim`);
repo-wide promote mutex (`.trellis/locks/promote.lock`);
`trellis lane lock-status`, `promote --force-lock`.
- **Git adapter:** `trellis git sync [--push]` mirrors integration → `main` with
op-log-derived commit messages; auto-sync on `lane promote` when
`git.syncOnPromote` (default on init).
- **Issue close:** auto-promotes unpromoted lane ops by default (`--no-promote`
to skip); optional `--push` after close.
- **Init defaults:** every `trellis init` writes `lanes.worktreeBind: true` and
`git.syncOnPromote: true` in `.trellis/config.json` (no longer gated on `.git`
existing).
- **Lane watch dashboard:** `trellis lane watch` — SSE live view at `:3939`
(lanes, claims, promote lock, in-progress issues).
- **Test manifest:** `.trellis/tests.json` seeded on init; `trellis test`,
`lane promote --require-test`, suite-aware `issue check`.
- **Coordination smoke:** `scripts/trellis-coordination-smoke.mjs` validates
global Cursor hooks + kernel defaults.
- **Touch manifest:** `docs/kernel-touch-manifest.json` +
`scripts/sync-downstream.mjs` for create-trellis / docs / turtlecode sync.
## trellis [3.2.4] — 2026-07-08
- Workspace-only coordination wedge (session lanes, git sync, claims) — ship as
**3.2.5** on npm if 3.2.4 was not published.
## trellis [3.2.3] — 2026-06-29
- **Agent handoff protocol (TRL-41 / ADR 0015):** `trellis protocol send`
records trellis-handoffs YAML envelopes as child issues (`label: message` |
`label: decision`); `trellis whereami` (+ `checkpoint`) for WAITING / ACTIVE /
MOVED re-entry.
- **`src/protocol/`:** envelope parse/validate, `isWaitingOnHuman`, lane-aware
active context.
- **Desk harness:** `templates/trellis-harness/trellis-cli.sh` —
`trellis_harness_lane_worktree` / `trellis_harness_edit_root` for session
hooks when `lanes.worktreeBind` is on.
- **Agent lane worktree bind (W5 / TRL-40):** optional `lanes.worktreeBind` in
`.trellis/config.json` provisions a per-lane git worktree at
`.trellis/worktrees/<shortId>/` on `lane create` / `issue start`.
- **`enterLane` materialize:** lane file blobs replay to the bound worktree;
file watcher rebinds to the worktree root.
- **`dropLane` cleanup:** removes the git worktree when `worktreePath` was
provisioned.
- **ADR 0014:** git materialization + lane worktrees spec
(`docs/adr/0014-git-materialization-and-lane-worktrees.md`).
## trellis [3.2.2] — 2026-06-10
- **`trellis db serve` on Node:** preloads the default tenant with sql.js /
better-sqlite3 before accepting traffic — fixes `create-trellis` scaffolds and
any `npx trellis db serve` flow that hit
`SqliteKernelBackend requires the Bun runtime`.
- **`TenantPool.get()` on Node:** fails fast with a preload hint instead of
attempting `bun:sqlite`.
- **`TRELLIS_BACKEND`:** `sqljs` or `better-sqlite` env override for `db serve`
and custom hosts (`resolvePoolBackendFromEnv`).
- **Gitignore:** `.trellis-db/`, `.trellis-db.json`, `.trellis-deploy/` at repo
root.
## trellis [3.2.0] — 2026-06-08
- **Typed realtime SDK:** `trellis/schema` — `defineType`, `entityQuery`,
`WhereFilter` operators, nested `InferResolvedType`, server
`hydrateAndResolve` on subscription push.
- **Live client:** `liveEntities` / `liveEntity` in `trellis/client` with
id-scoped subscriptions (`entityQuery`) instead of full-type scans.
- **Framework hooks:** `trellis/svelte/typed`, `trellis/vue/typed`,
`trellis/react/typed` — typed `useEntities` / `useEntity` adapters.
- **Studio plugin exports:** `trellis/plugins/plan-approval`,
`proactive-watcher`, `idea-garden`, `agent-memory` ship in `dist/` for npm
consumers (Trellis Studio / opencode).
- **Ontology:** idempotent `registerType` — duplicate schema registration
returns quietly (409 swallowed client-side).
- **Realtime:** explorer graph-nav + collections demos; collab presence session
lifecycle hardening.
## trellis [3.1.32] — 2026-05-29
- **Agent Lanes (W1–W4):** `trellis lane` — isolated per-agent op journals under
`.trellis/lanes/`, `create` / `enter` / `leave` / `status` / `diff` /
`promote` / `drop`.
- **`trellis lane promote`:** replay lane ops onto integration with `--dry-run`,
`--explain`, and hard/soft/file conflict detection.
- **`trellis issue start`:** auto-creates and enters a lane (opt out with
`--no-lane`).
- **`TRELLIS_LANE_ID`:** subprocess agents auto-enter the lane via
`syncEnvLaneFromEnv()`.
- **Lazy replay (W4):** integration materialization cache; `leaveLane` restores
integration view without full journal replay.
- **`getBranchHeadOpHash`:** latest `headOpHash` fact wins (fixes stale head
during promote).
- **Op log lock:** configurable timeout via `TRELLIS_OPLOG_LOCK_MS`.
## trellis [3.1.14] — 2026-05-22
- CLI `trellis --version` now reports the real package version from
`package.json` (was hardcoded `0.1.0`).
- CLI `-p` / cwd resolution walks up to the nearest `.trellis` repo root
(monorepo subfolders work without passing the root path).
- Clearer "not a repository" errors: show looked-from path, cwd, and `-p` hint.
- `issue create` accepts `--description` as an alias for `--desc`.
- `bin/trellis.mjs` launcher finds Homebrew Bun when Node's `PATH` is minimal
(`npx trellis` / agent shells).
## trellis [3.1.2] — 2026-05-12
- Fixed `trellis/cms` collection reads for inferred collections whose normalized
key differs from the stored entity type casing, such as `blogpost` reading
`BlogPost` entities.
- Added graph-link awareness to CMS entries so reference links such as
`post --author--> author` appear in `fields` and can be expanded.
- Added `status` fact fallback when `cms_status` is absent, preserving content
created by agents or lower-level store tools.
- Added shared polling for CMS subscriptions so duplicate subscribers to the
same collection or entry reuse one poll stream.
- Added `onError` and custom `equals` subscription options.
- Fixed CMS entity pagination to respect the opencode store route's 1000-entity
page limit.
- Added CMS client/scaffold tests and included them in the default test script.
- Added `directory` support to CMS consumer scaffolds for multi-instance
opencode routing.
## trellis [3.1.1] — 2026-05-12
- Published the first `trellis/cms` SDK package update after adding scaffold
helpers.
## trellis [3.1.0] — 2026-05-12
- Added the `trellis/cms` subpath with `createCmsClient`, collection reads,
entry reads, polling subscriptions, reference expansion, collection discovery,
and consumer scaffold helpers for vanilla, React, Solid, and Vue.