An OPS example, end to end
One small change, followed from the request to the evidence. Everything on this
page is read from examples/project/ when the site is
built, and that example is executed by npm run example: the prompt and the
worklog entries are validated and the prompt's checks are run again.
This is an illustrative example. It is not one of the measured study cases; those are on the results page.
1. The request
What a person wrote, in plain language:
Request
Slugs coming out of packages/slug look wrong in the article URLs. A title like
a -- b turns into a------b, and -Hello! turns into -hello-.
Please make slugify produce clean slugs: one hyphen between words, and no
hyphen at the start or the end. Two tests in packages/slug/test/slug.test.mjs
already describe what I expect and currently fail.
Keep it small: do not add dependencies, do not change the function's name or signature, and do not touch the tests. Other packages in this repository are out of scope.
2. The OPS prompt
The same request as a task contract. It names the workspace, states an objective that can be checked, carries the constraints, orders the work, and lists the checks that decide completion. Nothing has been changed yet at this point; the person reads this and corrects it before any code is touched.
apiVersion: guided-engineering/v1
id: slug.clean-separators
version: 1
title: Make slugify collapse repeated separators and trim hyphens at the edges
agent: guided-engineer
workspace: ./packages/slug
objective: |
`slugify` returns clean slugs: exactly one hyphen between words and no hyphen
at the start or the end. `slugify('a -- b')` returns `a-b` and
`slugify(' -Hello! ')` returns `hello`.
context: |
`packages/slug` is a dependency-free ES module package tested with the Node.js
built-in test runner. `src/slug.mjs` replaces every non-alphanumeric character
with its own hyphen, so runs of separators survive as runs of hyphens and
leading or trailing separators stay in the result. Two tests in
`test/slug.test.mjs` describe the expected behavior and currently fail.
The request comes from `request.md` at the repository root.
inputs:
- src/slug.mjs
- test/slug.test.mjs
dependencies:
- Node.js 20 or newer is available as `node`
constraints:
- Change only `src/slug.mjs`.
- Do not edit, skip, or delete any test.
- Do not add dependencies.
- Keep the exported name `slugify` and its single-argument signature.
- Leave every other package in the repository untouched.
requirements:
- id: R1
text: Runs of separator characters collapse into a single hyphen.
- id: R2
text: The result never starts or ends with a hyphen.
- id: R3
text: Existing behavior (lowercasing, diacritic stripping) is preserved.
steps:
- id: reproduce
title: Reproduce the failure
requirements: [R1, R2]
actions:
- Run `node --test` in the workspace and record which tests fail and with which actual values.
- Confirm the two failing tests are the separator-collapsing and edge-trimming tests; stop if anything else fails.
- id: fix
title: Correct the separator handling
requirements: [R1, R2, R3]
actions:
- Read `src/slug.mjs` and identify the replacement that emits one hyphen per character.
- Change the implementation so a run of non-alphanumeric characters becomes one hyphen and hyphens at either edge are removed.
- Keep the normalization, diacritic stripping, and lowercasing steps as they are.
- id: verify
title: Verify the final bytes
requirements: [R1, R2, R3]
actions:
- Run `node --test` in the workspace after the last edit and record the exit code and the pass and fail counts.
- Confirm with `git status --short` that `src/slug.mjs` is the only modified file.
output:
- file: src/slug.mjs
rules:
- Exports `slugify(input)` with the same signature.
- Uses no dependencies.
verification:
- id: unit-tests
expect: All four tests in `test/slug.test.mjs` pass.
run: node --test
requirements: [R1, R2, R3]
- id: scope
expect: '`src/slug.mjs` is the only file changed inside or outside the workspace.'
requirements: [R3]
stopConditions:
- A test other than the two described ones fails before any change is made.
- The fix cannot be made without editing a test or adding a dependency.
limits:
repairAttempts: 2
timeBudgetMinutes: 15
tags:
- example
- bugfix
createdBy: guided-engineering
Validated with:
node dist/ops-validate.mjs --resolve examples/project/.guides/prompts/prompt.slug.clean-separators.yaml
3. The plan
Asked to plan, the agent validates the prompt, resolves where the work
happens, and writes a plan in which every task has a check. A plan is recorded
as a worklog entry with mode: plan, and it cannot claim that anything ran.
Plan: clean separators in slugify
The request was to plan the prompt slug.clean-separators. Nothing was
executed: no step ran, no test ran and no file other than this entry changed.
status: completed says only that the planning is finished.
What resolved
Validated with ops-validate --resolve, which accepted the prompt.
| Reference | Resolves to |
|---|---|
| Repository root | this example project |
| Workspace, the write boundary | packages/slug |
Agent guided-engineer | the current executor; the agent map binds no native profile |
| Inputs | packages/slug/src/slug.mjs and packages/slug/test/slug.test.mjs, both present |
| Output | packages/slug/src/slug.mjs |
Dependency: Node.js 20 or newer as node. The working tree of the example was
clean when the plan was written.
Tasks
| # | Step | Files | Change | Check for this task |
|---|---|---|---|---|
| 1 | reproduce | none | none | node --test in packages/slug fails with exactly two failing tests: the one that collapses repeated separators and the one about hyphens at the edges. The other two pass. |
| 2 | fix | src/slug.mjs | Replace each run of non-alphanumeric characters with one hyphen, then remove a hyphen at the start and at the end. Keep normalization, diacritic stripping and lowercasing as they are. | node --test exits 0. |
| 3 | verify | none | none | After the last edit: node --test exits 0 with four passing tests, and git status --short lists packages/slug/src/slug.mjs as the only changed product file. |
Checks that decide completion
unit-tests:node --test, run inpackages/slugafter the last edit. Exit code 0 passes. Covers R1, R2 and R3.scope: observed withgit status --shortfrom the repository root.src/slug.mjsis the only file changed, apart from the worklog entry of the run. Covers R3.
Out of scope
The tests, every other package, dependencies, and the name and signature of
slugify.
Stop conditions and limits
- Stop if a test other than the two described ones fails before any change.
- Stop if the fix would need an edited test or a new dependency.
- At most two repair attempts for a failing check, and 15 minutes for the run.
Who planned
The session that built this repository, acting as the current executor. It
followed the ops-execute procedure by reading it. The model is the one the
session reports; the host does not expose its version to the session.
Next unit
Execute the prompt, on request.
4. The evidence
Asked to execute, the agent reproduces the failure, makes the change, runs the checks again after the last edit, and records what it observed. The front matter of the entry is the checkpoint and the index of evidence:
apiVersion: guided-engineering/v1
entryId: 2026-11-13.slug-clean-separators
date: '2026-11-13T19:19:40Z'
prompt:
id: slug.clean-separators
version: 1
sha256: 09a3e858eeccfb4712e4a06e9cc19eb3e9b2b9cadbb481b8f76a3b4965b13cef
agent: guided-engineer
executor:
host: claude-code
hostVersion: UNKNOWN
model: claude-fable-5-2
mode: execute
status: completed
steps:
- id: reproduce
status: done
evidence:
- packages/slug/test/slug.test.mjs
- id: fix
status: done
evidence:
- packages/slug/src/slug.mjs
- id: verify
status: done
evidence:
- packages/slug/src/slug.mjs
checks:
- id: unit-tests
result: pass
command: node --test
exitCode: 0
at: '2026-11-13T19:19:11Z'
- id: scope
result: pass
command: git status --short
exitCode: 0
at: '2026-11-13T19:19:12Z'
evidence:
- packages/slug/src/slug.mjs
And the readable record:
Clean separators in slugify
The request was to execute the prompt slug.clean-separators, after the plan
in 2026-11-13.slug-clean-separators-plan.md.
What was done
- reproduce.
node --testinpackages/slug, before any edit, exited with code 1: two tests passed and two failed. The failing ones were the two the prompt describes. "collapses repeated separators into one hyphen" gota------bwherea-bwas expected, and "never starts or ends with a hyphen" got-hello-wherehellowas expected. Nothing else failed, so no stop condition applied. - fix.
src/slug.mjsreplaced every non-alphanumeric character with its own hyphen. The replacement now takes a whole run of such characters at once, and a second replacement removes a hyphen at the start and at the end. Two lines added, one removed. Normalization, diacritic stripping and lowercasing are untouched. - verify.
node --testwas run again after that edit, which was the last one.
Checks
| Check | Command or observation | Result | When |
|---|---|---|---|
unit-tests | node --test in packages/slug | exit code 0, four tests passed, none failed | after the last edit |
scope | git status --short from the repository root listed packages/slug/src/slug.mjs as the only modified file; the only other new files are this entry and the plan entry | as expected | after the last edit |
Failures and repairs
None. The failing run during reproduce was the expected starting state, not a
failed check. No repair attempt was used.
Decisions and open questions
- The existing
.trim()call was left in place. It is redundant after the change but harmless, and removing it was not asked for. - No open question.
Who executed
The session that built this repository, acting as the current executor. It
followed the ops-execute procedure by reading it. The model is the one the
session reports; the host does not expose its version to the session. No one
reviewed or approved this change, so the entry has no approvals.
Next unit
A person reads the diff of packages/slug/src/slug.mjs and decides whether to
keep it.
5. The decision
The entry has no approvals. The agent executed and reported; whether the
change is merged is a person's decision, and when it is made it is recorded as
that person's, with a reference to where it was given.