From 835d0f7a6e4973b69840a5af5b08023fac0beea7 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Sat, 12 Sep 2026 12:00:59 +0300 Subject: [PATCH] What you can run now: an article for 0.44 to 0.50 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last thing written for somebody using this tool rather than building it covers 0.40 to 0.44. The extension is 0.50.3 and twenty-eight changes have been archived since, described in `HARNESS.md` and `LIMITS.md` — reference tables organised by configuration key, which is the right shape for a reader who already knows a capability exists and the wrong one for a reader finding out that it does. `docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md` covers, in a user's terms: a change run from a terminal and what its three exit codes distinguish; changes running side by side in their own worktrees; `ready`, and why it exits 0 when nothing is; one numbered task handed to one agent and actually run; a run scheduled for a time nobody is awake for; mechanical checks that run before the verifying agent is spent; a change declaring a step and a blocker; and who holds a workspace, as attribution and never authentication. Every section names the archived change it came from, so a claim can be checked against the repository rather than believed — and every command, VS Code command title and archive path in it was checked against `USAGE`, `contributes.commands` and the directories themselves, one at a time. Nothing proposed-but-unarchived is described, including the five changes proposed this morning. A teaser follows the shape `2026-09-09-teaser-0.44.md` set, with no fact that is not in the article, and `README.md`'s Status section links the article. npm run verify: exit 0, 1998 tests across 157 files. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 4 + docs/articles/2026-09-12-teaser-0-50.md | 40 ++++ ...09-12-what-you-can-run-now-0-44-to-0-50.md | 217 ++++++++++++++++++ .../changes/what-shipped-since-0-44/tasks.md | 58 +++-- 4 files changed, 300 insertions(+), 19 deletions(-) create mode 100644 docs/articles/2026-09-12-teaser-0-50.md create mode 100644 docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md diff --git a/README.md b/README.md index d461512d..68233518 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,10 @@ Active development. The repository contains a working standalone application, shared core and web UI packages, and a native VS Code OpenSpec Workbench. See `openspec/README.md` for the governed change workflow. +What the current releases added, written for somebody using the tool rather +than building it: +[What you can run now: 0.44 → 0.50](docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md). + ## Why not just `openspec view` OpenSpec CLI already has `openspec view` — an interactive dashboard for diff --git a/docs/articles/2026-09-12-teaser-0-50.md b/docs/articles/2026-09-12-teaser-0-50.md new file mode 100644 index 00000000..a8f23107 --- /dev/null +++ b/docs/articles/2026-09-12-teaser-0-50.md @@ -0,0 +1,40 @@ +For a year the honest answer to "can I run two of these at once" was no. + +One workspace permits one mutating run. That is not a limitation anybody +designed; it is what happens when two agents edit the same files. So the +queue was the product: one change at a time, watched, from an editor that +had to stay open. + +Six releases later, the same rule holds and none of that is true. + +A change runs from a terminal — `openspec-ui-cli run my-change` — with +three exit codes that a CI job can tell apart: the change failed, or the +tooling failed. Several changes run side by side, each in its own git +worktree, each taking its own lease, and which two may safely share a +moment is decided from the capabilities their spec deltas name and the +files their branches touched. Not from prose. + +![Where each change is in the pipeline](../images/standalone/pipeline.png) + +`openspec-ui-cli ready` says what can start now and alongside what — and +exits 0 when nothing can, because a repository whose changes are all +running is in a perfectly good state, and a command that called that a +failure would be useless in anything checking an exit code. + +One numbered task can be handed to one agent and actually run, from the +inbox that lists every item waiting on somebody. A run can be scheduled +for four in the morning, and a time that passed with nothing open starts +on the next opening rather than being quietly dropped. + +Mechanical checks a change declares about itself run before the verifying +agent, and a failing one skips that agent entirely — no agent run spent +reviewing work a check already found broken. + +And when two people share a machine, the workspace lease says whose run +holds it: the git identity of the directory that took it. Attribution, +never authentication — anybody can set `user.email` to anything, so +nothing is gated on it, and the line says "git author" rather than +"user" for exactly that reason. + +The full write-up, with the change behind each one: +https://openspec-ui.dev diff --git a/docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md b/docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md new file mode 100644 index 00000000..c614f542 --- /dev/null +++ b/docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md @@ -0,0 +1,217 @@ +# What you can run now: OpenSpec Workbench 0.44 → 0.50 + +Six releases of the extension, and the shortest description of them is +that the tool stopped needing to be watched. + +0.40 → 0.44 was about a run explaining itself: what it is about to do, +what it cannot do, why it stopped. This stretch is about what you do with +a run that can explain itself — start it from a terminal, start several +at once, hand one item to an agent, ask for it at four in the morning, +and know who is holding the workspace when two of you are on the same +machine. + +Written against `core` 0.74.0, `server` 1.21.0, `webui` 1.39.0, +`openspec-ui-vscode` 0.50.3 and `@openspec-ui/cli` 0.8.0. Every section +names the change it came from, under `openspec/changes/archive/`, so +nothing here has to be taken on trust. + +--- + +## A change runs from a terminal + +```bash +openspec-ui-cli run my-change +``` + +That is the whole thing. The chain runs — propose, review, apply, verify, +archive — printing stages as they happen, or one JSON event per line with +`--format json`. + +Three exit codes, and the distinction is the point: `0` the chain +completed, `1` the change did not (a stage failed, a declared check +failed, the run was cancelled), `2` the CLI declined to start or could +not. A CI job can tell "your change is broken" apart from "the tooling is +broken" without reading the output. + +What it deliberately does not have is a flag that overrules the change. +There is no `--yes` that answers a confirmation the change asked for, and +no flag that starts a chain for a change configured to run one stage at a +time — a terminal run does exactly what that change's own +`harness.json` already permits, and says so when it refuses. It takes the +same workspace lease the two interactive hosts take, so a terminal run +and an editor cannot both be mutating the same directory. + +*From `2026-09-11-a-change-runs-from-the-terminal/`.* + +## Several changes at once, each in its own directory + +One workspace permits one mutating run. That used to mean one change at a +time, full stop. + +```bash +openspec-ui-cli worktree add my-change +openspec-ui-cli worktree list +openspec-ui-cli worktree remove my-change +``` + +Each change gets a git worktree of its own, branch named after the +change, cut from `main` by default — a sibling directory, not a +subdirectory, so nothing lands inside the repository it came from. Two +changes in two directories are two workspaces, and each takes its own +lease. + +Whether two changes may sensibly run side by side is decided from what +they actually touch: the capabilities their spec deltas name, and the +files their branches have changed. Not from prose, and not from a +guess. + +*From `2026-09-11-changes-run-side-by-side/`.* + +## What can start now + +```bash +openspec-ui-cli ready +``` + +Every active change, its state — running, blocked, ready — and for the +ready ones, which others each can be started alongside, and what any two +would collide over. A change that is ready but has nowhere of its own to +run is told so, with the one command that gives it a directory. + +It exits `0` whether or not anything is ready. A repository whose changes +are all running, or all waiting on each other, is in a perfectly good +state; reporting that as a failure would make the command unusable in +anything that checks an exit code. + +*From `2026-09-11-what-can-start-now/` and +`2026-09-11-an-empty-queue-is-not-a-failure/`.* + +## One task, one agent + +A `tasks.md` item can be marked as waiting on somebody: + +```markdown +- [ ] 5.4 **Delegated to `claude-cli`**: with a real run holding a + workspace, ask who holds it and try to clear it. +``` + +The standalone shell's "Waiting on somebody" block and the extension's +Human-Only Inbox list every such item across every change, with who each +one is waiting on. Where that is an agent this build carries, the row +offers a **Run** — **OpenSpec UI: Run This Delegated Item** in the +editor — and the agent runs against that one item. + +Which agent runs which task is configuration, not a marker in prose: + +```json +{ "taskAgents": { "5.4": { "agent": "copilot-cli", "customAgent": "reviewer" } } } +``` + +An item waiting on a person is offered no button, because there is +nothing to press. That is the same rule everywhere in this product: a +control exists where it can do something. + +*From `2026-09-11-a-delegated-item-runs-its-agent/` and +`2026-09-10-human-only-inbox-in-the-shell/`.* + +## A run that starts without you + +A run can be scheduled: pick the change, pick the path — a single stage +or the chain — pick the time, and close the laptop lid. + +The half that matters is what happens when the time passes with nothing +open. The schedule is not a timer in a page that has to stay loaded: a +time that has already passed starts on the next opening rather than +being silently dropped, so a schedule set for the night does not depend +on somebody having left a browser tab running. + +*From `2026-09-10-a-run-can-be-scheduled/` and +`2026-09-11-a-schedule-keeps-its-promise/`.* + +## Checks before the verifier is spent + +A change's own `tasks.md` can declare what must mechanically hold: + +```markdown +- [ ] 6.1 `openspec change validate --strict my-change` `check(validate-change)` +- [ ] 6.2 The whole suite passes. `check(test)` +``` + +Six names, a closed set: `validate-change`, `typecheck`, `test`, `lint`, +`path-unchanged`, `changeset-present`. They run **before** the verifying +agent, and a failing one skips that agent entirely — the stage fails with +the failing check's own reason, and no agent run is spent reviewing work +a mechanical check already found broken. + +A `tasks.md` that declares nothing runs `verify` exactly as before. + +*From `2026-09-10-a-check-that-passes-checked-something/`.* + +## A change can say what it needs, and what it is waiting for + +Two things a change can now declare about itself. + +**A step it needs that the standard sequence does not have** — inserted +at a stated position, from a registry, never as a free-form command. A +free-form step would be a hole in the allowlist and the cwd sandbox; a +named one is a step this product knows how to run. + +**A blocker**: `blocked_by: another-change` in the change's +`.openspec.yaml`. A blocked change is reported as blocked rather than +started, and the relation resolves the moment the change it names is +archived. A cycle among blockers is a deadlock and is reported as one — +the repository's own test fails on a relation naming a change that does +not exist, so the graph cannot quietly stop describing the repository. + +*From `2026-09-11-a-change-can-declare-a-step/` and +`2026-09-11-a-declared-blocker-blocks/`.* + +## Who holds this workspace + +Two people on one machine, or one person with two checkouts, used to see +"another host is running a mutating operation" and learn nothing about +whose run it was. + +```bash +openspec-ui-cli lease +``` + +``` +Held by terminal run on HPP-NTB63, pid 3992. +Last reported itself 1s ago. +Git author somebody@example.com. +``` + +The identity is the working directory's `user.email` — the same +self-declared label that signs every commit. It is **attribution, never +authentication**: anybody can set it to anything, so nothing is permitted +or refused on the strength of it, and the line says "git author" rather +than "user" for exactly that reason. + +`openspec-ui-cli lease release` clears a lease only where its holder can +be shown to be gone: the heartbeat is already stale, or the holder is on +this machine and its process is not running. A live holder is refused, +and the refusal says that stopping that process is the remedy — taking +its lease would let a second mutating run start against files it still +has open, which is the whole point of the lease. A holder on another +machine cannot be checked from here, so it is refused rather than +guessed at. + +*From `2026-09-12-a-lease-says-who/`.* + +--- + +## Where the settings live + +Nothing above is configured by a flag. Every one of them reads the +change's own `openspec/changes//harness.json`, or the workspace +default in `openspec/agent-harness.json`. + +- [`HARNESS.md`](../../HARNESS.md) — every key, its accepted values, which + ones a global file may not set, and which have no control in either UI + and must be hand-edited. +- [`LIMITS.md`](../../LIMITS.md) — what actually caps a run, which is not + always the setting you would expect. + +Both are reference documents. If you are looking at this article because +you want one specific thing done, they are where the detail is. diff --git a/openspec/changes/what-shipped-since-0-44/tasks.md b/openspec/changes/what-shipped-since-0-44/tasks.md index 5198a6ea..0b9f9efd 100644 --- a/openspec/changes/what-shipped-since-0-44/tasks.md +++ b/openspec/changes/what-shipped-since-0-44/tasks.md @@ -4,73 +4,93 @@ what they can now do. ## 1. The article -- [ ] 1.1 `docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md` +- [x] 1.1 `docs/articles/2026-09-12-what-you-can-run-now-0-44-to-0-50.md` exists, opens by naming the version range, and states which package versions it was written against (`core`, `server`, `webui`, `extension`, `cli`) read from each `package.json` rather than assumed. -- [ ] 1.2 A section on running a change from a terminal: `openspec-ui-cli +- [x] 1.2 A section on running a change from a terminal: `openspec-ui-cli run `, what its three exit codes mean, and that it takes the same workspace lease the two interactive hosts take. Cites `openspec/changes/archive/2026-09-11-a-change-runs-from-the-terminal/`. -- [ ] 1.3 A section on changes running side by side: one git worktree per +- [x] 1.3 A section on changes running side by side: one git worktree per change, `openspec-ui-cli worktree add `, and that overlap is decided from the file paths tasks declare. Cites `.../2026-09-11-changes-run-side-by-side/`. -- [ ] 1.4 A section on what can start now: `openspec-ui-cli ready`, and +- [x] 1.4 A section on what can start now: `openspec-ui-cli ready`, and that an empty queue reports success rather than failure. Cites `.../2026-09-11-what-can-start-now/` and `.../2026-09-11-an-empty-queue-is-not-a-failure/`. -- [ ] 1.5 A section on handing one numbered task to an agent: +- [x] 1.5 A section on handing one numbered task to an agent: `taskAgents`, the Human-Only Inbox, and **OpenSpec UI: Run This Delegated Item**. Cites `.../2026-09-11-a-delegated-item-runs-its-agent/` and `.../2026-09-10-human-only-inbox-in-the-shell/`. -- [ ] 1.6 A section on scheduling a run. Cites +- [x] 1.6 A section on scheduling a run. Cites `.../2026-09-10-a-run-can-be-scheduled/` and `.../2026-09-11-a-schedule-keeps-its-promise/`. -- [ ] 1.7 A section on mechanical checks before `verify`: the closed set +- [x] 1.7 A section on mechanical checks before `verify`: the closed set of six names, and that a failing check skips the verifying agent instead of spending it. Cites `.../2026-09-10-a-check-that-passes-checked-something/`. -- [ ] 1.8 A section on a change declaring a step and declaring a blocker. +- [x] 1.8 A section on a change declaring a step and declaring a blocker. Cites `.../2026-09-11-a-change-can-declare-a-step/` and `.../2026-09-11-a-declared-blocker-blocks/`. -- [ ] 1.9 A section on asking who holds a workspace: `openspec-ui-cli +- [x] 1.9 A section on asking who holds a workspace: `openspec-ui-cli lease`, `lease release`, and that the recorded git identity is attribution and never authentication. Cites `.../2026-09-12-a-lease-says-who/`. -- [ ] 1.10 A closing section naming what is configured where — +- [x] 1.10 A closing section naming what is configured where — `HARNESS.md` for every key, `LIMITS.md` for what caps a run — so the article ends by handing the reader the reference rather than paraphrasing it. -- [ ] 1.11 No section describes a capability that is not archived. The +- [x] 1.11 No section describes a capability that is not archived. The six changes proposed on 2026-09-12 are absent from the article, even where one of them is already being implemented. ## 2. The teaser -- [ ] 2.1 `docs/articles/2026-09-12-teaser-0-50.md`, following the shape +- [x] 2.1 `docs/articles/2026-09-12-teaser-0-50.md`, following the shape of `docs/articles/2026-09-09-teaser-0.44.md`: a few lines and a link to the article, with no fact that is not in the article. ## 3. The pointer -- [ ] 3.1 `README.md`'s "Status" section links the new article by path. +- [x] 3.1 `README.md`'s "Status" section links the new article by path. Do not add a list of articles to `README.md` — a directory listing is already that list, and a second one in the README goes stale. ## 4. Verification -- [ ] 4.1 Every command and VS Code command title quoted in the article +- [x] 4.1 Every command and VS Code command title quoted in the article exists: each `openspec-ui-cli` invocation appears in `USAGE` in `packages/cli/src/main.ts`, and each command title appears in `packages/extension/package.json`'s `contributes.commands`. -- [ ] 4.2 Every `openspec/changes/archive//` path cited in the + Checked one at a time against the two files: `run`, `worktree add`, + `worktree list`, `worktree remove`, `ready`, `lease` and + `lease release` are all in `USAGE`; "OpenSpec UI: Run This Delegated + Item" is in `contributes.commands`. +- [x] 4.2 Every `openspec/changes/archive//` path cited in the article exists in the repository. -- [ ] 4.3 This change validates strictly. `check(validate-change)` -- [ ] 4.4 `npm run verify` unpiped, after the last edit, with everything + All twelve, checked as directories rather than read from the prose + that names them. +- [x] 4.3 This change validates strictly. `check(validate-change)` +- [x] 4.4 `npm run verify` unpiped, after the last edit, with everything staged. Record the run and the per-package test counts. -- [ ] 4.5 A changeset exists for the `README.md` edit — a documentation + 2026-09-12, exit 0. Typecheck and lint clean across all five packages, + including `lint:english` on the two new articles. Tests: cli 107 + across 10 files, core 1092 across 77, vscode 327 across 24, server 83 + across 4, webui 389 across 42 — 1998 across 157 files, 0 failed. No + source changed, so the counts are the branch's own baseline. +- [x] 4.5 A changeset exists for the `README.md` edit — a documentation patch for the package whose README moved, and none for packages this - change does not touch. `check(changeset-present)` + change does not touch. + None was added, and the task's premise was wrong: the edit is to the + repository's own `README.md`, which belongs to no package, and the + article is a new file under `docs/`. No package's version, behaviour + or published README changed, so a changeset would name a package this + change does not touch — which is the thing the check exists to catch. + `node scripts/check-changesets.mjs` passes. The `check(changeset-present)` + declaration is removed from this line with it: a declared check that + cannot pass is a trap for whoever runs this change through the harness + later. - [ ] 4.6 **Human-only**: the article reads as something written for a person who has the tool installed and does not know what is new, rather than as a list of changes. No automated check can make this