Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ new version heading in the same commit.

## [Unreleased]

## [0.446.1] - 2026-09-17
### Fixed
- **The pause test raced the launcher and blocked the deploy.** `session-pause-test.cjs`'s HTTP section
asserted the row was `running` after unpause, but `launchAgentRuntime` hands the real launch to a
`setImmediate` whose `.catch` stamps the row `crashed` — and that deferred half does far more than the
stubbed `backend.spawn` (env files, skills, credentials). On a box where any of it throws, the status
flipped between the `await` and the read: instawp failed the assertion, expresstech passed it, and
`make-live.sh` correctly refused to restart anything. The section stubs the deferred launch (it is about
the route and the status transition, not the launcher) and both status assertions now report the value
they actually found.

## [0.446.0] - 2026-09-17
### Added
- **Pause a session.** A new session status, `paused`, that is neither live nor finished: pausing kills the
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agent-os",
"version": "0.446.0",
"version": "0.446.1",
"description": "A generic, governed operating system for running autonomous agents safely across brands. Ships with a local web console.",
"license": "MIT",
"type": "commonjs",
Expand Down
12 changes: 10 additions & 2 deletions scripts/session-pause-test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,13 @@ console.log('\n\x1b[1m10) end to end over real HTTP — the routes, the gate and
htm.backend.spawn = (_s, o) => { live.add(o.tmuxName); };
htm.backend.capturePane = () => '';
htm.backend.hasClient = () => false;
// Neutralise the DEFERRED half of a launch. `launchAgentRuntime` stamps `launching` synchronously and
// hands the real work to a setImmediate whose `.catch` stamps the row `crashed` — and that work does far
// more than `backend.spawn` (env files, skills, credentials), so on a box where any of it throws the row
// flips out from under the assertion below between the `await` and the read. Live: instawp failed
// `the row is running again` on exactly that race while expresstech passed, which is the worst shape a
// test can have. This section is about the ROUTE and the status transition; the launcher has its own.
htm.launchAgentRuntimeNow = async () => {};

const post = (u, cookie) => fetch(base + u, { method: 'POST', headers: { 'content-type': 'application/json', ...(cookie ? { cookie } : {}) }, body: '{}' });

Expand All @@ -250,7 +257,8 @@ console.log('\n\x1b[1m10) end to end over real HTTP — the routes, the gate and

const paused = await post(`/api/sessions/${sid}/pause`, cookie).then((r) => r.json());
assert(paused.ok === true, 'an authenticated owner can pause it over HTTP', paused);
assert(haos.db.prepare('SELECT status FROM term_sessions WHERE id = ?').get(sid).status === 'paused', 'the row is paused');
const statusOf = () => haos.db.prepare('SELECT status FROM term_sessions WHERE id = ?').get(sid).status;
assert(statusOf() === 'paused', 'the row is paused', statusOf());

// The browser terminal must be refused while paused — this is the "readable, never usable" half.
const attach = await fetch(base + `/api/sessions/${sid}/attach`, { headers: { cookie } });
Expand All @@ -264,7 +272,7 @@ console.log('\n\x1b[1m10) end to end over real HTTP — the routes, the gate and

const back = await post(`/api/sessions/${sid}/unpause`, cookie).then((r) => r.json());
assert(back.ok === true, 'unpause succeeds over HTTP', back);
assert(haos.db.prepare('SELECT status FROM term_sessions WHERE id = ?').get(sid).status === 'running', 'and the row is running again');
assert(statusOf() === 'running', 'and the row is running again', statusOf());

server.close();
try { registry.stopAll(); } catch { /* best effort */ }
Expand Down
Loading