Release notes
Every published Sharpee release, newest first. A release is listed here once it is on npm — a version that was bumped and never published does not appear, because these notes describe what you can actually install.
Current: Sharpee 5.6.0 · Chord language 4.0.1 · Chord Writer 1.4.0. The three move independently (ADR-257): a platform patch does not touch the language, and the language version moves only when the author-visible surface changes.
5.6.0
— finished food leaves the world, and packages that export what they mean2026-11-06Chord 4.0.1One small language change and a round of cleanup underneath it. A thing that is fully eaten or drunk now leaves the world, and Chord gains servings <n> so a story can say a thing lasts more than one bite. Chord moves to 4.0.1. The rest is the platform getting smaller: three packages now export only what something uses, and state that had two writers has one.
- A fully eaten or drunk thing leaves the world. A vessel that holds liquid stays when it is emptied.
- servings <n> is a new line on an edible or drinkable thing: how many bites or sips it has before it is finished. A thing with no line has one serving, as before.
- The player is a role the session holds (ADR-390). WorldModel.playerCharacter replaces getPlayer() and playerId; setPlayer assigns the role at the start and changePlayer moves it during play.
- The Chord compiler and the loader refuse an invalid story by one rule (ADR-389), and a Chord entity's id in the world is the id the compiler gave it.
- @sharpee/core names its contract (ADR-391): the barrel lists each export by name, and the unused constants, extensions, debug and execution subsystems are deleted.
- @sharpee/event-processor writes no state for a standard action; the action's behavior is the one writer. Its barrel exports six names, and opening and closing each report one event.
- @sharpee/bootstrap takes the engine's Story type where it took any (#645).
- 5.5.1 was published on 2026-10-30 without a note of its own. It carried ADR-388: what a Chord save records is keyed by the names the author wrote, so a save still restores after the story is edited.
Traces to: ADR-388 · ADR-389 · ADR-390 · ADR-391 · #641 · #645 · #394
5.5.0
— Chord 4.0: the kind leads, vehicles, locks, and a parser that searches2026-10-27Chord 4.0.0Chord moves to 4.0.0, its first major since 3.0.0, and the platform under it to 5.5.0. The language change an author meets first is the one that made it a major: every create block names its kind, and the kind leads the block (a thing, a room, a container, openable); the three "hatch" forms that let a story reach into TypeScript are gone; a region declares its rooms instead of nesting them. On that footing the language gains a vehicle kind with six movement models, with sailing and open-field expanses as extensions on top of it; passages named by a command and exits that exist while a condition holds; backdrops, night vision and listeners; things that are attached, breakable or lit; two-noun and conversation-shaped clauses; and a dozen stock verbs that needed no object. State machines are core. A test tree can lock a reached state as a claim, and the lock proposes the necessary set from the line that reached it. Underneath, the English parser was reviewed end to end and rebuilt in seven steps: it searches slot extents and ranks readings by their nouns, every slot carries a declared seat, confidence is gone from ranking, one noun matcher answers every "which thing is this" question, and every English word the parser used to carry lives once, in the language package, with each parser instance owning its own state.
- Every create block names its kind, and the kind leads the block (ADR-359). thing is a kind; a block without one is analysis.missing-kind-noun; a kind behind a trait is analysis.kind-not-first. The inline form create the Potting Shed, a room is admitted.
- Hatches are removed (ADR-361): define text … from, define action … from and define chain … from are parse errors with fix-its; every Chord story is pure IR.
- A region declares its rooms (ADR-360): rooms groups and in membership replace containing and nesting; the heading loses its region part; a region exit table.
- Blocks fold for density (ADR-362): create <name>, <composition> and exits: / exits, one-way: lines.
- The vehicle is a kind with a movement model (ADR-366): line, streets, flight, compass, open and none; admits, to outside, boarding, the driving statements and predicates; UPPS's conveyances are vehicles. Sailing (ADR-375, use sailing: bearings in degrees, the naval commands, wind and sails) and expanses (ADR-376, use expanses: open movement on coordinates, landmarks, drift, edges, start <vehicle> heading <direction>) extend it.
- State machines are core (ADR-377): define machine needs no use line; writing use state-machines is a compile error that says so.
- Passages and hidden exits (ADR-378, ADR-380): a passage is a block with a grammar (passage to <room> … end passage, with while, blocked and deadly lines), an exit exists while a condition holds, admits on the way, a thing's own pushing block moves it between rooms; a flight's trip time is its pace:; [the] in a pattern.
- Systems are domain services (ADR-379): one question, one home, every mover — traversal and visibility answer the walking player, a vehicle, a pushed thing and an NPC alike.
- A clause head lists its gerunds (ADR-368): on the player taking, touching.
- Containers say what they show and hold (ADR-369): transparent; holds <n> is the one spelling of capacity; in and out are exit directions.
- Stock verbs without an object side (ADR-370): kissing, waving, jumping, saying yes / no / sorry, looking under, emptying.
- Object-side adjectives (ADR-371): lowering and raising take the clause body as their implementation; flammable [with the <tool>] gates burning; settable makes a thing's reversible states a dial and a setting head takes to <value>.
- Two-noun and conversation-shaped clauses (ADR-372): a head names its counterpart (on the player throwing at the sorting machine); ask <person> for <thing> is a request; a readable thing carries define topics and answers consult; costs <n> <currency> prices a thing and gates buying.
- Physical state the platform enforces (ADR-373): attached to / detachable; breakable, fragile, starts broken, broken as a state and after the player breaking; tying is a stock action.
- Scope and senses (ADR-374): a backdrop is one scenery thing in many rooms; night-vision, can see and can reach read the platform; listener, after hearing the <sound>, define sound without a file; lamps (light, put out, light-source with, starts lit, powered by); dark is reserved as a state name off rooms; play sound is never gated on the client.
- A reached state can be locked as a claim (ADR-367): sharpee claim <line> "<fact>" proposes the necessary set from the played line trimmed by the cone of influence, writes the claim and pins the card; a broken lock is a failed card named in the claim's words. Claims under a necessary set (ADR-365) prune the explorer to the winning path; a claim's needs is checked against the predicate's cone (analysis.claim-inert-needs).
- The test tree is segmented on disk (ADR-355): <story>.tests/ with a manifest, a canonical gate and stable card ids. Derived rule tests (ADR-356): arrange(), END STATE cards prove endings, sharpee test reports branches, endings and rooms, and the derived runner reaches every noun a command names (#549). The IDE's Testing tab keeps stale results instead of dropping them, names each failed card's cause, and walks failures one stop at a time (ADR-357).
- The parser review (ADR-382 to ADR-387), seven steps: a grammar rule crosses from Chord to the matcher as structured parts, never as text to re-split, and → cardinality is refused until it is real (382); every slot declares its seat, so hand the recipient the item and give the item to the recipient seat alike and a missing object is asked for by its seat (383); rules rank by literal specificity, tier and definition order, and confidence is gone (384); one noun matcher serves the parse-time gate, the validator and list expansion, articles and determiners are split once, a pronoun is a whole item, and a gate failure names the phrase and the reason (385); the parser searches slot extents and ranks readings by their nouns, so give the old man the sword, put jack in the box in chest and take salt and pepper shaker read right, and and a comma are list readings, and unlock door with asks for the key (386); one word table per language owns articles, determiners, self words, list separators, manner adverbs, directions and number words, the possessive is by person (your lantern is the player's own in the second-person voice), the parse-failure sentences are the language's, and a parser instance owns its vocabulary and pronoun context — two parsers in one process share nothing (387).
- Not in this release: ADR-381 (connectors replace attachment) is accepted but its cutover has not landed; attached to, detachable and the tying actions still ship as ADR-373 describes them above.
- Smaller platform fixes on main: the location heading rides one wire (ADR-349); a chapter's title announces before the room (ADR-330 D4); the repokit bundle resolves @sharpee/* through exports maps (#542); pin verdicts name entities by display name (#533); X.location = offstage holds for an entity in no place (#548); the Secret Letter port's platform fixes land (#543).
Traces to: ADR-355 · ADR-356 · ADR-357 · ADR-359 · ADR-360 · ADR-361 · ADR-362 · ADR-365 · ADR-366 · ADR-367 · ADR-368 · ADR-369 · ADR-370 · ADR-371 · ADR-372 · ADR-373 · ADR-374 · ADR-375 · ADR-376 · ADR-377 · ADR-378 · ADR-379 · ADR-380 · ADR-382 · ADR-383 · ADR-384 · ADR-385 · ADR-386 · ADR-387 · #633 · #549 · #507 · #560 · #570
5.4.1
— one source for the engine version, and installable packages again2026-09-11Chord 3.6.0Two fixes that both come down to a tool being wrong about something it did not own.
- The engine version has one source: the platform constant stamped at platform build time. The version and about actions, the info channel, and the opening banner all read it directly.
- A Chord story's banner now carries its engine line. start() read the version off StoryInfoTrait, which only a build pipeline writes, so a story loaded from IR emitted game.started with no version and the banner dropped the platform-version block silently.
- An author build no longer stamps a version range as a version. The author-side stampers computed the value from the ^<major>.0.0 dependency range with its caret stripped, which is how every 5.x author build came to report 5.0.0.
- engineVersion is removed from StoryInfoTrait, from the story-info projection, from BrowserBuildEnv, from the browser client's StoryInfo config, and from every generated story version.ts. STORY_VERSION and BUILD_DATE still stamp — those are per-build facts a story owns.
- The info channel still carries engineVersion for clients that show it, now always present and sourced from the constant rather than from whatever the story happened to be stamped with.
- Published packages carry their subpath exports again (tsf 1.0.4). @sharpee/platform-browser ships ./channels, ./channels/prose, ./channels/status, ./channels/text-content and ./styles/*; @sharpee/transcript-tester ships ./assertion-core.
Traces to: ADR-334 · ChicagoDave/tsf#1 · #433
5.4.0
— the explicit ending release2026-09-11Chord 3.6.0The end of a story is now something the platform can say. It had four names and no owner — a world-state flag, the story.victory/story.defeat events, the engine's own game.won/game.lost pair, and a Story.isComplete() hook polled once a turn — so five different places re-derived the same fact and none of them held it. A player who reached an ending in the browser could not type restart, and reloading the page put them back in the same dead prompt. The ending is now a first-class member of the world, declared by one verb, and the three defects behind that report close with it.
- The ending is a record on the world (ADR-347): IStoryEnding carries the kind, the turn, the ending phrase's message id and a cause, and it is absent while play continues. A story that has not ended has no Ending, which is a different statement from one that says nothing.
- One verb declares it. endStory(world, kind, opts) sets the Ending and returns the blessed ending event, and Chord's win/lose lowers onto it rather than carrying its own implementation — the same shape kill has always had with killPlayer. The first ending wins: a second call on an ended world writes nothing and emits nothing.
- Story.isComplete() is gone. An ending is declared at the moment it becomes true, never polled for once a turn. Nothing in the tree actually polled for completion, and an optional hook that could report complete while the world carried no Ending was the split state the change exists to prevent.
- The engine reads the Ending instead of recomputing it. The turn's ending stage used to reconstruct the answer from three unrelated sources every turn; it now asks the world one question.
- A Chord lose ends the story as a defeat. It previously set the world flag, which the completion poll read, which stopped the engine as a *victory* — the engine only ever watched for story.victory.
- Every ending reports itself. A death is declared by the engine rather than by the story, and it now emits story.defeat onto the turn's event stream like any other ending, where before it recorded the Ending silently.
- The engine's phase is derived from the Ending when a save is restored: a save carrying an Ending restores stopped, one without it restores to play. That retires the reconciling patch 5.3.2 needed, and it is why RESTORE and UNDO now work at an end-game prompt.
- Clients are told in state, not in prose. A new story-ending channel carries the record, alongside the existing endgame notification it deliberately does not replace, and the browser drives its input box from it — disabled when the story ends, live again the moment a restore or undo returns the player to a turn they can type into.
- The end-game prompt comes from the language layer, derived from the same Ending, so every host gets it rather than each client inventing one.
- Reloading an ended game no longer strands the player. The ended world is still saved, faithfully; what changed is that the reload lands at an end-game prompt that works, instead of the save being suppressed to dodge a state the platform could not represent.
Traces to: ADR-347 · ADR-345 · #414 · #415 · #416
5.3.2
— the Chord playable release2026-09-11Chord 3.6.0The Chord playable keyword finally reaches the runtime. It had been in the language since 2026-08-26 and the analyzer had enforced it from that day, but the loader step that writes the flag onto the actor was never built and the trait defaulted to *true* — so every actor in every story read as playable, and the guard that checks it could never fire. Connecting it opened three more seams, and all four are in this release.
- The player role holder is validated where the story is installed (ADR-344): it must exist, be placed, carry an actor trait, and be playable. The loader's old fallback of dropping an unplaced protagonist into the first declared room is gone — every story places its own.
- The engine is never handed a player. GameEngine no longer takes one at construction; it comes from the story source, for Chord and TypeScript stories alike.
- ActorTrait.isPlayable now defaults to false, matching what Chord means by the word's absence. A protagonist built through the author-facing builder says so with .playable().
- The engine's lifecycle is an explicit phase — empty → ready → playing ⇄ stopped (ADR-345) — rather than something each method re-derived from whichever field was nearest. resume() emits game.resumed, which it previously did silently.
- Traits no longer police completeness (ADR-346): a door may be one-sided and an exit half-built while a story is still composing the passage. Detection belongs where the world is checked as a whole.
- Gate work rode along: pnpm typecheck became a real gate (it had been compiling zero files), test files entered it, seven packages' suites entered the test:ci sweep, and engine tests stopped running on the wall clock.
Traces to: ADR-343 · ADR-344 · ADR-345 · ADR-346 · #400 · #401 · #402 · #404 · #410
5.3.1
— the refactoring survey2026-09-10Chord 3.6.0A patch release carrying a structural survey of the platform: seven ADRs, each naming one package's shape and fixing it. No author-visible syntax moved, which is why Chord stayed at 3.6.0 and this went out as a patch rather than a minor.
- ADR-334: the turn is a stage list. game-engine.ts gave up its turn helpers, one platform dispatcher and one enrichment funnel replaced duplicated pairs, and the package reorganized into command/, install/, session/, ports/ and introspection/.
- ADR-342: the engine's root barrel narrows to a contract — 31 named exports, no export *. A type reachable only through a kept export's signature stays internal.
- ADR-337: the interceptor lifecycle has exactly one call site, the executor's phase runner, and one validation pipeline replaced two.
- ADR-338: AuthorModel became a proxy view of the live world rather than a parallel one.
- ADR-339: the character tick's seven sub-steps live beside the subsystems they belong to, as a list with per-step requirements, pinned by a test.
- ADR-340: transcript-tester and branch-tester share one assertion core instead of 1,129 identical forked lines.
- Chord Writer 1.4.0 ships alongside.
Traces to: ADR-334 · ADR-335 · ADR-336 · ADR-337 · ADR-338 · ADR-339 · ADR-340 · ADR-342 · #376
5.3.0
— publish-readiness, and the acting statement2026-09-04Chord 3.6.0The largest release of the 5.x line, and the first that was measured against a specific question: what does an outside author writing a modest Chord story hit in their first hours? Forty defects were triaged into a plan and worked through in sixteen phases. Underneath it, ADR-327 made clause heads name who acts, ADR-328 threaded an actor through the whole standard-action library, and ADR-329 gave Chord the acting statement — one character performing one real action, validated and interceptable, through the same execution entry a player's command takes.
- 5.2.0 is not missing. It was bumped on 2026-08-29 and never published; everything in it ships here. That is why Chord went 3.3.0 → 3.6.0 in one step — 3.4.0 and 3.5.0 are landing history.
- ADR-327 is a Chord major folded into this release: on <gerund> it is gone, clause heads name the actor (on the player taking, after Jack entering), and syntactic it/its left statements and conditions outside a define trait body.
- The player became a role a named character holds: playable marks who is eligible, and change the player to <character> assigns it and can move it mid-play. create the player is gone.
- ADR-325 places and timers; ADR-326's move <entity> to a random adjacent room; ADR-330's chapters extension; , one-way exits; proper on any create block.
- The held command (a bare noun answering a disambiguation), possessive entity names in conditions, remove marking an entity *gone* rather than destroying it, and one-way exits are all publish-readiness fixes that an author meets early.
- @sharpee/world-index arrived (ADR-321): a story's map, reach and vocabulary gaps derived as JSON, surfaced in Chord Writer's World tab.
- Nested Chord imports (ADR-251 D5 amended), with Span.file so a diagnostic names the fragment it came from.
Traces to: ADR-325 · ADR-326 · ADR-327 · ADR-328 · ADR-329 · ADR-330 · ADR-332 · the publish-readiness proposal (40 items)
5.1.1
— the ESM build, repaired2026-08-19Chord 3.3.0A patch release almost entirely about the build. The ESM target was not being produced whole-tree, which broke vitest's ability to resolve dist-esm/ packages and, with it, the Chord Writer release pipeline. The fix makes the ESM build default-on and derives vitest's workspace aliases instead of requiring a prior dist-esm build.
- Chord Writer 1.3.1 ships alongside, with its release pipeline working again.
- #280: an opening card that could never be claimed.
- Full card sets and walkthroughs for the conversation stories, and The Ides of March moves.
- Author documentation for characters and conversation on sharpee.net, written against the syntax 5.1.0 had just shipped.
Traces to: #276 · #277 · #279 · #280
5.1.0
— conversation2026-08-18Chord 3.3.0The character model reached Chord. @sharpee/character had existed since April 2026 and passed its tests with zero consumers; ADR-310 and ADR-318 gave it a Chord surface, and ADR-320 built conversation on top across eleven phases. Authors can now write manner, greetings, exchanges, initiative and whole conversation threads in a .story file, and The Ides of March was written as the story that proves it.
- Chord 3.1.0, 3.2.0 and 3.3.0 all landed inside this release: the conversation grammar arrived in three slices, each with its vocabulary frozen by the owner the same day.
- NPC-to-NPC scenes, with earshot derived from spatial sound, player intrusion into a scene in progress, and mid-scene save/restore.
- Trait-level conversation memory: what a character has been told, and how recently, is world state that persists.
- Chord Writer gained an explain-NPC-turn panel — an author channel that reports why a character did what it did on a given turn.
- Goals, influence and information propagation are in scope rather than deferred, on the owner's ruling that they are the point of the character model.
Traces to: ADR-310 · ADR-318 · ADR-320 · ADR-141 through ADR-146 (prior art)
5.0.1
— Chord Writer ships its own toolchain2026-08-14Chord 3.0.0A patch release whose real content is on the desktop side: Chord Writer became installable without a Node toolchain. The DMG now carries a per-architecture vendor toolchain, so the download page could drop the npm install step an author previously had to perform before the app would do anything.
- Per-architecture build and packaging, with two download tiles on the site rather than one universal binary.
- The app runs on any Apple silicon Mac, not only the machine it was built on.
- Self-hosted analytics on sharpee.net, provisioned by the deploy with a salt that persists itself rather than rotating on every deploy.
- The app icon arrived: parchment at large sizes, a single note at small ones, masked into the macOS tile shape.
Traces to: ADR-279 · ADR-284
5.0.0
— the testing surface is the tree2026-08-11Chord 3.0.0A new model for testing a story. ADR-307 replaced the transcript-shaped testing UX with a tree document — one <story-id>.tests.json per story, where the tree *is* the model rather than a view over something else — and @sharpee/branch-tester is the greenfield walker that replays it against a real engine. Chord Writer's Testing tab became the play surface itself rather than a panel beside one.
- The tree document is a wire format with a schema, round-trip tests and discovery, shared by two consumers — the walker and the IDE — whose parity was signed off before the cutover.
- JSON is the source of truth for a story's tests; the old transcript-shaped IDE artifacts went away rather than being kept in parallel.
- ADR-309 made the IFID tool-owned: minted at story creation into <story-name>.config.json and rendered into the Chord header on save and build, so the compiler stopped asking authors for one.
- @sharpee/transcript-tester stays, and keeps owning the .transcript grammar for Sharpee's own hand-authored suites. The two runtimes are for different audiences.
Traces to: ADR-307 · ADR-309 · #248