Repository navigation
Releases: enes-alatas/spool
Releases · enes-alatas/spool
Release list
v0.5.1
What's Changed
- feat: the hub reads the Claude plan's usage from its loops' streams by @enes-alatas in #654
- feat(web): each Fleet row shows its share of today's fleet spend by @enes-alatas in #656
- fix(docker): every docker wake catches the proxy up with the fleet's hosts by @enes-alatas in #658
- feat(web): the Fleet page shows the plan's 5-hour and 7-day usage by @enes-alatas in #659
- test(itest): the live egress row counts only turns begun after each reach by @enes-alatas in #660
- feat(web): a first-run step the hub is working on lists its phases by @enes-alatas in #663
- fix: the toolchain moves to go1.26.9 for its standard-library fixes by @enes-alatas in #666
- chore(web): bump source-map-js to 1.2.2 past its advisory by @enes-alatas in #669
- ci: a feat PR that changes one half of the product names the other by @enes-alatas in #670
- feat(httpapi): the onboarding read says what each waiting pillar is doing by @enes-alatas in #664
- feat(loop): above the plan cap every loop sleeps until the window resets by @enes-alatas in #672
- feat(web): the room sets the plan cap and shows a capped fleet by @enes-alatas in #671
- fix(itest): the docker MCP-broker row skips on a host without docker by @enes-alatas in #673
Full Changelog: v0.5.0...v0.5.1
v0.5.0
What's Changed
- fix(loop): a rehomed loop is not_provisioned until its workstation is built by @enes-alatas in #641
- feat(store): secrets sealed at rest under a hub key by @enes-alatas in #642
- feat(loop): an env-var change reaches an awake loop from its next turn by @enes-alatas in #644
- feat(redact): the operator token and the hub key are redacted by @enes-alatas in #645
Full Changelog: v0.4.3...v0.5.0
v0.4.3
What's Changed
- refactor(egress): remove a loop's own egress entries by @enes-alatas in #633
- feat(loop): the loop view says when a rehome is pending by @enes-alatas in #635
- feat(web): a bare loop's Workstation panel moves it into a docker container by @enes-alatas in #637
- fix(itest): the empty-context check no longer races a new loop's first tick by @enes-alatas in #638
Full Changelog: v0.4.2...v0.4.3
v0.4.2
What's Changed
- feat: every change to a connection is on an append-only record by @enes-alatas in #608
- feat: rotating a connection's value retires the old one and ends the sessions that held it by @enes-alatas in #612
- feat: revoking a connection takes it from every loop, refuses it from then on, and keeps it redacted by @enes-alatas in #613
- fix(telegram): a loop's reaction to a teammate's message reaches a supergroup by @enes-alatas in #615
- feat(web): a connection's record, rotate and revoke in the control room by @enes-alatas in #616
- feat(web): a loop's Telegram notes say where a reaction to a teammate shows by @enes-alatas in #619
- chore: remove the per-loop secrets routes; private env-var connections replace them by @enes-alatas in #618
- feat: the fleet's extra egress hosts are stored and apply without a restart by @enes-alatas in #620
- feat(web): Settings has an Egress section, the fleet's allowlist by @enes-alatas in #621
- feat: secrets a loop holds don't reach teammates or hide in encodings; ADR-0045 states the posture by @enes-alatas in #625
- feat(httpapi): the hub brokers a loop's http MCP servers by @enes-alatas in #627
- feat: a bare loop can be rehomed into a docker workstation by @enes-alatas in #631
Full Changelog: v0.4.1...v0.4.2
v0.4.1
What's Changed
- fix(httpapi): a docker loop that cannot reach the loop listener is refused by @enes-alatas in #477
- docs(release): a release is titled with its tag alone by @enes-alatas in #486
- feat: channels exist in the hub, with the fleet channel named group by @enes-alatas in #488
- feat(web): a Channels page creates channels and chooses their loops by @enes-alatas in #490
- docs: a loop reaches only Spool's MCP server by @enes-alatas in #494
- fix(runtime): Spool builds on macOS, keeping Pdeathsig on Linux by @enes-alatas in #498
- fix(loop): a loop whose claude cannot reach the hub is down, and its work waits by @enes-alatas in #496
- fix(httpapi): a Docker Desktop workstation reaches the loop listener by @enes-alatas in #509
- feat(cmd): a docker hub puts its loop listener where workstations reach it by @enes-alatas in #511
- feat(web): name a claude that can't reach the hub, and offer no Power on for it by @enes-alatas in #510
- feat(loop): a loop posts to its channels by name by @enes-alatas in #512
- test(uifixture): the fixture seeds channels besides the fleet channel by @enes-alatas in #513
- feat(telegram): a group is bound to a channel per loop, and carries it both ways by @enes-alatas in #516
- docs: a Report a problem form, triage rule, and CONTRIBUTING for outside reports by @enes-alatas in #522
- feat(loop): the loop view says what the session reaches through MCP by @enes-alatas in #525
- chore(ci): an issue from outside the team is labelled and welcomed by @enes-alatas in #528
- feat(web): the loop page lists its rooms and binds one to a channel by @enes-alatas in #530
- feat: reactions exist in the hub — ADR-0040, store and bus kind by @enes-alatas in #536
- feat(web): the loop page shows what the session reaches through MCP by @enes-alatas in #537
- feat(telegram): reactions travel both ways between a loop's bot and the hub by @enes-alatas in #538
- fix(web): no next wake is shown while a loop is in a turn by @enes-alatas in #539
- feat(loop): a loop reacts with send_message and hears of reactions on its next turn by @enes-alatas in #540
- feat(web): one slider sets a loop's min wake, tick and max wake by @enes-alatas in #545
- feat(slack): reactions travel both ways between a loop's app and the hub by @enes-alatas in #544
- feat(web): the control room shows a message's reactions by @enes-alatas in #547
- chore(egress): a workstation can pip install from PyPI by @enes-alatas in #546
- feat: polls exist in the hub — ADR-0041, store, bus kind and the close by @enes-alatas in #555
- feat(telegram): a loop's poll is a native Telegram poll, and its votes reach the hub by @enes-alatas in #557
- feat(web): a loop's channels are tabs of its page, and Activity filters by channel by @enes-alatas in #556
- feat(slack): a loop's poll is its app's post with buttons, and clicks are votes by @enes-alatas in #558
- feat: a loop polls, votes and closes with send_message, and votes ride with its next turn by @enes-alatas in #560
- fix(telegram): an unanswered send is retried on a fresh connection within seconds by @enes-alatas in #562
- feat: the control room renders polls with their tallies by @enes-alatas in #563
- feat: the hub pins a PreToolUse hook that refuses the host's shared-state commands by @enes-alatas in #565
- feat: a loop dismisses a lost send, and is reminded of it until it does by @enes-alatas in #566
- feat: connections can be created, listed, described and deleted, secret write-only by @enes-alatas in #568
- feat(web): show when a loop dismissed or left a lost send by @enes-alatas in #569
- fix(telegram): the HTTP/1 transport offers only http/1.1 in its TLS handshake by @enes-alatas in #571
- feat: a connection is attached to and detached from loops, and an attached one can't be deleted by @enes-alatas in #573
- feat: a connection's env-var kind replaces env-credential by @enes-alatas in #575
- feat(web): Connections page and loop-page connections panel by @enes-alatas in #577
- feat: per-loop secrets are env-var connections, and an attached env-var is in the wake env by @enes-alatas in #578
- fix(web): connections say env variables reach their loop, and long names fit the panel by @enes-alatas in #583
- feat: GET /api/onboarding reports readiness per pillar by @enes-alatas in #584
- feat(web): first-run page for the three onboarding pillars by @enes-alatas in #586
- feat: the harness pillar checks the Claude login with one haiku answer by @enes-alatas in #587
- feat(web): the first-run Harness card sets up and checks the login in place by @enes-alatas in #590
- feat(slack): a Slack channel is a room bound to a channel per loop by @enes-alatas in #591
- feat(web): the first-run Loops and Chat surface cards open their steps in place by @enes-alatas in #592
- test: two docker itests stop racing other hubs on the shared daemon by @enes-alatas in #594
- feat(loop): an attached mcp-server is a server in the loop's mcp-config by @enes-alatas in #598
- feat(web): a Slack loop's channels are rooms on its page by @enes-alatas in #596
- feat(docker): an attached MCP server opens its host to its loop alone by @enes-alatas in #602
- feat: a connection can be private to one loop, and is shared one way by @enes-alatas in #603
- feat(web): the loop page's secrets are its private connections by @enes-alatas in #605
Full Changelog: v0.4.0...v0.4.1
v0.4.0
What's Changed
- fix(web): the Undelivered pane restacks by its own width, not the viewport's by @enes-alatas in #417
- fix(loop): a refused Claude login is a named down reason, not silence by @enes-alatas in #416
- feat(surface): the owner hears once that a refused login stopped their loops by @enes-alatas in #421
- fix(web): a refused Claude login shows its cause and its fix by @enes-alatas in #422
- feat(surface/slack): each loop's Slack app holds a Socket Mode connection by @enes-alatas in #423
- fix(telegram): a native reply reaches its author whichever bot ingests it by @enes-alatas in #425
- fix(web): the New loop runtime select says why it is locked by @enes-alatas in #428
- feat(surface/slack): what a human says to a loop's app reaches the loop by @enes-alatas in #430
- fix(web): New loop locks the workspace field for a docker loop by @enes-alatas in #432
- fix(web): a Slack post in the fleet channel says it came via Slack by @enes-alatas in #433
- feat(surface/slack): a loop's words reach Slack: group mirrors, owner_dm, threads by @enes-alatas in #434
- feat(surface/slack): turned-away senders, the login notice and channel_name on Slack by @enes-alatas in #435
- fix(web): Slack attach and channel copy say what actually happened by @enes-alatas in #439
- fix(loop): a refused login keeps one tick, not a backlog of them by @enes-alatas in #436
- fix: a running hub settles every send it accepted by @enes-alatas in #440
- fix(cmd): a hub that stops serving exits 1 by @enes-alatas in #443
- fix(store): commits wait on the WAL, not on an fsync; a perf smoke asserts the envelope by @enes-alatas in #444
- docs(readme): Quick start is a numbered path that works end to end by @enes-alatas in #448
- feat(surface): a stopping hub fails its surfaces' held sends before the store closes by @enes-alatas in #449
- feat(attach): a photo or file sent to a loop reaches it as a path it can read by @enes-alatas in #454
- feat(attach): a loop sends a file with its message by @enes-alatas in #455
- fix(web): a context trend bar keeps its width at any turn count by @enes-alatas in #459
- feat(web): glyph and wordmark match the README banner by @enes-alatas in #461
- feat(slack): files cross Slack both ways by @enes-alatas in #458
- chore: the README opens with a demo video, rendered by make demo by @enes-alatas in #463
- feat(httpapi): the control room reads, serves and sends attachments by @enes-alatas in #467
- feat(web): messages carry files in the control room by @enes-alatas in #469
- docs(conventions): every slice of a multi-PR issue is its own sub-issue by @enes-alatas in #465
- docs(conventions): rare procedures move to skills by @enes-alatas in #473
- chore(deps-dev): Bump brace-expansion from 1.1.18 to 1.1.21 in /web in the npm_and_yarn group across 1 directory by @dependabot[bot] in #468
- docs(conventions): a bare #n may sit anywhere in a code comment by @enes-alatas in #478
- feat(web): allowing a pending sender takes the code they were sent by @enes-alatas in #482
New Contributors
- @dependabot[bot] made their first contribution in #468
Full Changelog: v0.3.0...v0.4.0
v0.3.0
What's Changed
- chore: make ui-shots takes the screenshot set from fixture data by @enes-alatas in #260
- chore(secret-guard): a handle and a chat id are quotes of the group by @enes-alatas in #259
- feat(web): the Fleet row says how many of a loop's messages never arrived by @enes-alatas in #262
- fix(itest): two suites, two egress walls by @enes-alatas in #265
- fix(httpapi): a saved mission takes the loop's next session, not its next hour by @enes-alatas in #271
- feat(web): a loop's mission can be edited from its page by @enes-alatas in #268
- feat(httpapi): the fleet's undelivered sends have somewhere to be read by @enes-alatas in #273
- feat(web): the sends that failed get a tab of their own by @enes-alatas in #274
- feat(httpapi): a failed send can be retried or dismissed, and stops counting by @enes-alatas in #276
- feat(route): a loop's resend closes the failure it replaces by @enes-alatas in #278
- feat(web): a failed send can be retried or set aside, and says which by @enes-alatas in #279
- feat(httpapi): one loop's undelivered sends can be asked for alone by @enes-alatas in #290
- docs(adr): the fleet channel is the hub's; surfaces are attached and mirror it by @enes-alatas in #291
- fix(web): an Undelivered row says where it went and why, together by @enes-alatas in #292
- feat(telegram): nothing the operator writes leaves the hub by @enes-alatas in #293
- feat(web): Undelivered is a pane of the loop page, not a destination by @enes-alatas in #294
- docs(conventions): Activity stays out of every shot, and says it is a decision by @enes-alatas in #296
- feat(route): a loop outside the fleet channel has no group by @enes-alatas in #295
- feat(httpapi): the fleet channel has endpoints of its own by @enes-alatas in #297
- chore: the model lists know Opus 5.5 and Fable 5.1 by @enes-alatas in #299
- feat(web): the fleet channel is a tab of the Fleet page by @enes-alatas in #300
- feat: a message says whether it is on the surface too by @enes-alatas in #301
- fix(web): the missing-Claude-token banner is about contained loops only by @enes-alatas in #307
- feat(httpapi): a new loop starts outside the fleet channel when it is alone by @enes-alatas in #306
- chore(claude): TestedVersion is 2.1.281, the CLI the fleet runs on by @enes-alatas in #309
- feat(web): loop surfaces — attach Telegram after creation, fleet-channel membership by @enes-alatas in #308
- docs: add theme-aware Spool banner and badges by @enes-alatas in #310
- docs: reduce README banner width by @enes-alatas in #313
- feat(httpapi): the operator can reply in the fleet channel by @enes-alatas in #311
- feat(web): the fleet channel says what stays on the hub and what failed to mirror by @enes-alatas in #312
- feat(web): reply to any message in the fleet channel by @enes-alatas in #317
- fix(workstation): a rebuild installs the newest Claude Code by @enes-alatas in #315
- feat(web): a favicon set and the spool glyph in the banner's proportion by @enes-alatas in #318
- feat(prompt): a loop is taught only the conversations it has by @enes-alatas in #321
- docs(conventions): an epic's children are attached as sub-issues by @enes-alatas in #324
- chore(web): upgrade vite, vitest and react-router past their advisories by @enes-alatas in #325
- docs(adr): ADR-0010 points to ADR-0018, which narrowed its Engine API clause by @enes-alatas in #327
- docs(conventions): a commit subject has one scope and no closing keyword by @enes-alatas in #328
- chore(ci): itest skips content it already passed on this PR by @enes-alatas in #326
- feat(web): the model list offers the four family aliases and no versions by @enes-alatas in #329
- feat(loop): a refused model holds the loop until the model is edited by @enes-alatas in #330
- feat(web): the control room's text uses no em dashes by @enes-alatas in #333
- feat(web): a refused model shows in the room, with what the CLI said by @enes-alatas in #335
- chore(web): move the control room to react-router 7 by @enes-alatas in #336
- docs: every new dependency is interviewed; binary ones also take an ADR by @enes-alatas in #337
- docs(adr): the hub resolves model aliases with a CLI run that can reach nothing by @enes-alatas in #338
- feat: the model list says what each name runs as on this hub by @enes-alatas in #340
- feat(web): model dropdowns show what each alias runs as by @enes-alatas in #339
- ci: the checks summary reports coverage of the PR's changed lines by @enes-alatas in #343
- feat(web): Surfaces offers Attach Slack, with the loop's app manifest by @enes-alatas in #346
- fix(itest): the hub's two listeners never draw the same port by @enes-alatas in #342
- fix(web): a disabled rule mutes its text, not its opacity by @enes-alatas in #355
- fix(web): a rule's buttons wrap under its title on a narrow screen by @enes-alatas in #358
- fix(httpapi): a loop's model cannot read as a CLI flag by @enes-alatas in #357
- fix(web): the loop page's model and pacing controls say what they set by @enes-alatas in #359
- fix(web): Access says when it is loading or could not load senders by @enes-alatas in #361
- fix(httpapi): a wrong method under /api/ is 405, not the control room by @enes-alatas in #362
- fix(web): Settings says it could not load, not that no token is set by @enes-alatas in #364
- fix(httpapi): a write whose subject vanished answers 404, not 500 by @enes-alatas in #365
- fix(web): the loop page says when its timeline could not load by @enes-alatas in #367
- fix(web): the loop page says when a loop is missing or failed to load by @enes-alatas in #369
- refactor(httpapi): names say what they hold by @enes-alatas in #370
- feat(web): the header's New loop is quiet white text, not a filled button by @enes-alatas in #371
- fix(sched): a tick due during a suspend fires once the machine resumes by @enes-alatas in #373
- fix(web): the room's errors are announced to a screen reader by @enes-alatas in #374
- feat(loop): a rotation tells the loop why it is happening by @enes-alatas in #376
- feat(ci): a browser smoke walks the control room on every web change by @enes-alatas in #375
- refactor(sqlite): names say what they hold by @enes-alatas in #377
- test(uifixture): the fixture hub signs in with a synthetic operator token by @enes-alatas in #379
- fix(web): the header switches to the narrow bar by text size, not width alone by @enes-alatas in #380
- refactor(loop): names say what they hold by @enes-alatas in #382
- fix(httpapi): health says the hub is up and nothing about the host by @enes-alatas in #385
- feat(web): Surfaces and Access gain the Slack surface's control-room half by @enes-alatas in #384
- docs(readme): Spool leads with what it makes easier by @enes-alatas in #387
- feat(store): a loop can hold a Slack identity and a Slack allowlist by @enes-alatas in #390
- docs(conventions): an issue's body is its spec of record by @enes-alatas in #3...
v0.2.0
What's Changed
- build(workstation): official spool-workstation image by @enes-alatas in #23
- docs(conventions): require self-contained comments by @enes-alatas in #25
- feat: Claude auth for workstations via setup-token by @enes-alatas in #26
- feat: per-loop secret env vars by @enes-alatas in #29
- docs(conventions): "fresh main" means fetched, not the local checkout by @enes-alatas in #28
- docs: GitHub is loop-native work, not a Spool surface by @enes-alatas in #32
- feat(web): workstation panel on loop detail by @enes-alatas in #35
- fix(runtime): drop bare.Start's kill-on-cancel watcher by @enes-alatas in #34
- chore(web): untrack tsconfig.tsbuildinfo by @enes-alatas in #40
- feat(web): context occupancy trend on loop detail by @enes-alatas in #49
- docs(conventions): delegated decisions are per-decision and quoted in the record by @enes-alatas in #41
- fix(telegram): dedup group and DM messages per bot, not per chat by @enes-alatas in #48
- feat(loop): operator power controls for a loop's workstation by @enes-alatas in #53
- feat(web): workstation power controls on loop detail by @enes-alatas in #50
- feat(httpapi): context usage on the loop view by @enes-alatas in #54
- feat(web): context fill against the model's window by @enes-alatas in #56
- feat(web): one fleet alert for a missing Claude token by @enes-alatas in #57
- fix(loop): rotate a session that can no longer be resumed by @enes-alatas in #59
- docs: record the proactive context rotation strategy (ADR-0022) by @enes-alatas in #62
- docs: separate coordination from human-facing traffic (ADR-0023) by @enes-alatas in #63
- feat(loop): proactive context rotation before the degradation zone by @enes-alatas in #64
- feat: fleet rules — storage, CRUD API, and prompt injection by @enes-alatas in #72
- feat(web): fleet rules panel by @enes-alatas in #58
- docs: define private DMs and explicit group delivery by @enes-alatas in #78
- docs: settle the loop sending contract (ADR-0026) by @enes-alatas in #81
- feat: conversation identity and per-loop MCP tokens by @enes-alatas in #82
- feat: hub MCP endpoint and the explicit send core by @enes-alatas in #83
- feat: fakeclaude scripted MCP sends by @enes-alatas in #84
- feat: runner wiring for explicit sends by @enes-alatas in #85
- feat(telegram): explicit delivery in, selective wake out by @enes-alatas in #86
- feat: web composer destination picker + read-only Activity by @enes-alatas in #87
- test: ADR-0025 scenario close-out and docs refresh by @enes-alatas in #88
- fix(loop): name an over-window payload for what it is by @enes-alatas in #90
- feat(web): semantic colour tokens for the control room by @enes-alatas in #92
- feat: operator control to rotate a session on demand by @enes-alatas in #93
- fix(loop): context is the last API call's occupancy, not the turn's summed usage by @enes-alatas in #95
- feat(web): responsive control-room navigation by @enes-alatas in #96
- feat: explicit message references and native group replies by @enes-alatas in #97
- fix(web): a fleet card's stats wrap instead of clipping by @enes-alatas in #99
- feat: a loop's owner is configured, and owner_dm reaches them by @enes-alatas in #102
- feat(web): choose a loop's owner and see whether it can DM them by @enes-alatas in #103
- feat: an identity catalog that says who a loop can address by @enes-alatas in #104
- fix: the retry ladder survives a failure-driven rotation by @enes-alatas in #109
- feat(web): Fleet is one list of loops, not a grid of cards by @enes-alatas in #105
- feat(web): the control room scales with the reader's text size by @enes-alatas in #111
- feat: @ALL addresses the group's eligible loops by @enes-alatas in #110
- fix(web): a state dot is an accent, not a second voice by @enes-alatas in #113
- refactor: one threshold rule, one threshold read, one fill signal by @enes-alatas in #114
- refactor(web): name the styles three pages were repeating inline by @enes-alatas in #115
- fix(loop): a rotation survives the orchestrator restarting by @enes-alatas in #116
- fix(web): centre the page column under its own header by @enes-alatas in #121
- fix(web): read an absent context fill as unreported, not as zero-length by @enes-alatas in #125
- feat(httpapi): read a loop's timeline from its newest end by @enes-alatas in #127
- feat(web): open the loop timeline on its newest window by @enes-alatas in #128
- test(itest): script a contained loop the way a bare one is scripted by @enes-alatas in #129
- fix(web): give a form page the column its content asks for by @enes-alatas in #133
- test(itest): port the m2 scenarios and the untested fakeclaude directives by @enes-alatas in #135
- fix(web): draw hairlines for the screen they land on by @enes-alatas in #137
- fix(web): let Fleet's STATE heading be a heading by @enes-alatas in #138
- feat(web): draw the scrollbars in the room's own vocabulary by @enes-alatas in #139
- refactor(telegram): the ingest-election margin becomes a value by @enes-alatas in #140
- feat(web): clamp a long mission, with the rest one click away by @enes-alatas in #142
- test(itest): port the m4 storm-guard and m6 worktree scenarios by @enes-alatas in #144
- feat(web): say what happened when a loop's session or machine changed by @enes-alatas in #145
- fix(telegram): keep the bot token out of transport errors by @enes-alatas in #155
- docs: secrets stay out of evidence, not just out of code by @enes-alatas in #156
- fix(telegram): a send that fails is retried, then recorded — never dropped by @enes-alatas in #148
- fix(datadir): spool's data is private to the account that runs it by @enes-alatas in #159
- feat(web): walk back through a loop's history, without losing the thread by @enes-alatas in #160
- fix(store): a single-field write stops reverting its neighbours by @enes-alatas in #163
- feat(web): rotate a loop's bot token from the loop page by @enes-alatas in #165
- fix(web): credential fields stop showing and stop offering themselves by @enes-alatas in #169
- fix(web): dress every control on the element, not on a wrapper by @enes-alatas in #170
- feat(loop): tell a running session when its standing instructions change by @enes-alatas in #174
- feat(web): the rotation thresholds are settings, so Settings edits them by @enes-alatas in #172
- chore(web): a unit test tier for the control room, on Vitest by @enes-alatas in #176
- feat(loop): a loop hears which of its own messages never arrived by @enes-alatas in #177
- fix(web): a disabled control mutes its text, and drops what well it has by @enes-alatas in #178
- fix(httpapi): saving a loop's settings stops reverting a concurrent bot write by @enes-alatas in #179
- chore(ci): spend Actions minutes on the jobs a change can break by @enes-alatas in https://github....