Skip to main content

ops-workspace

An isolated place to build and test one change — worktree, database, ports, dependencies — and the teardown that removes everything it created. Prepared and torn down by `ops-change`, never by a loop, so how isolation is provisioned stays a product fact. The framework default uses a plain git worktree; a repo needing a seeded database or a free port ships its own. Called by name with (action, context-json). NOT for direct use — never select it from a description match.

Source facts

Repository
umbraco/umbraco-ai-ops
Last source activity
September 23, 2026 at 12:46
Detected SKILL.md language
English
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
ops-workspace
description
An isolated place to build and test one change — worktree, database, ports, dependencies — and the teardown that removes everything it created. Prepared and torn down by `ops-change`, never by a loop, so how isolation is provisioned stays a product fact. The framework default uses a plain git worktree; a repo needing a seeded database or a free port ships its own. Called by name with (action, context-json). NOT for direct use — never select it from a description match.
# ops-workspace One change, one clean place to build it. **Visibility: supporting primitive.** Only **`ops-change`** calls it. A framework loop must not — the loop does not know whether this repo needs a worktree, a container, a seeded database, or nothing at all, and the moment a loop decides that, the engine has learned a product fact. ## Invocation ``` ops-workspace <action> '<context-json>' ``` | Action | Context | Returns | |---|---|---| | `prepare` | `{ branch }` | `{ ok, path, reused, fidelity, notes }` | | `teardown` | `{ path }` | `{ ok }` | An absent context is `{}`. **Reject any other action.** ## Action: `prepare` Create an isolated workspace for that branch and leave it **ready to build** — not merely checked out. Whatever this repo needs before its build command works (dependencies restored, a database seeded, a port claimed, credentials in place) happens here, because the alternative is `ops-change · implement` discovering it halfway through. **Idempotent.** An existing workspace for that branch **MUST** be reused and returned with `reused: true`, never duplicated. Two worktrees on one branch is a corruption, not a convenience, and a re-fired routine will ask twice. **Framework default:** a git worktree off the branch, and nothing else. That is enough for a repo whose build needs only a checkout, and honestly insufficient for one that needs a database — which is why those repos override. **In a cloud routine there is often nothing to do.** The session already has its own isolated checkout and no sibling work to collide with. Return that checkout's path with `reused: true` rather than nesting a worktree inside it. A workspace capability that insists on creating something is worse than one that recognises it already has what it needs. ### Find out what the environment already provides, before provisioning anything A cloud environment is **built once and reused**, and its build step may already have installed the SDK, cached a container image, or started a service. A `prepare` that probes blindly or reinstalls wastes minutes of every run and can end up with two versions of the same thing. So **read first, provision second**. In a cloud environment built by the engine's stub, that record is **`$HOME/env-manifest.md`**, written by `cloud-env-setup.sh` on every build: the .NET SDK it installed, whether the SQL Server image is cached, and where the session script lives. Read that and treat it as authoritative. If there is no manifest, say so and fall back to the repo's own documented setup rather than guessing. Report the difference in `notes`: what was already there, and what you had to create. **To bring Umbraco up**, a repo's `prepare` calls the script the manifest names: ``` bash $HOME/.umbraco-ops/run-umbraco.sh --provider <sqlite|sqlserver> --boot "<this repo's start command>" ``` `--boot` is the one thing only the repo knows — how its site starts — and it must honour `ASPNETCORE_URLS` (for `dotnet run`, pass `--no-launch-profile`). For `sqlserver` the script starts the container and hands the site `ConnectionStrings__umbracoDbDSN` through its environment; for `sqlite` the site keeps its own default. Choose the provider by `fidelity` below: `sqlserver` where the manifest says the image is cached, because that is what CI tests against; `sqlite` is `reduced`. "Available but not running" is not "unavailable". A cached container image with a stopped daemon means **startable** — start it. Reinstalling because a service was not already running is the most expensive way to get this wrong. ### Say how faithful the workspace is: `fidelity` Where a repo has more than one possible test target — the one CI uses, and a lighter, faster stand-in — `prepare` **MUST** say which one it produced: | `fidelity` | Means | |---|---| | `ci-parity` | this workspace tests against what CI tests against. A pass here predicts a pass there | | `reduced` | a faster stand-in: a different database engine, a stubbed dependency, a smaller fixture set | **Default to `ci-parity`.** A `reduced` target is a last resort — for a quick smoke of one focused change, or when the parity target genuinely is not available here — because a different engine produces both false failures *and* false passes. **A `reduced` pass is not evidence CI will pass**, and `ops-change · verify` must carry that through to whatever it reports. Silently downgrading the test target and reporting a clean pass is worse than not testing: it spends the loop's trust on a result that did not earn it. A repo with exactly one test target reports `ci-parity` and never thinks about this again. ## Action: `teardown` Remove the workspace **and everything `prepare` created** — the worktree, the database, the container, the claimed port. A teardown that leaves the database behind is why the tenth run fails on a name collision. **MUST succeed when there is nothing to remove.** Teardown is reached from failure paths, and a teardown that errors because the thing was already gone turns one failure into two. **Never remove anything you did not create.** Not the main checkout, not a branch that has not landed, not a sibling workspace. A `teardown` that guesses is a data-loss bug with a routine running it unattended. ## Rules - **Never called by a loop.** If a loop is preparing a workspace, `ops-change` has been bypassed. - **`prepare` leaves it buildable**, or reports why it could not. - **Both actions are idempotent**, and `teardown` is safe on an absent workspace. - **Teardown destroys only what prepare made.** - **One workspace per change.** Never two changes in one tree — the whole point is that a failing build belongs to exactly one change.
View on GitHub