From kuru
Use when decomposing a PRD into vertical slices sized for a single agent session. Covers the small-enough/complete-enough tension, vertical (not horizontal) slicing, frozen contracts, sequencing for a walking skeleton, and writing checkable acceptance criteria. This is the highest-leverage step in the harness.
How this skill is triggered — by the user, by Claude, or both
Slash command
/kuru:slicing-workThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A slice is the unit of work a builder agent picks up and finishes in **one
A slice is the unit of work a builder agent picks up and finishes in one session. Getting slice boundaries right is the highest-leverage decision in the whole harness: too big and the agent runs out of context and fakes done; too small or horizontal and it can't be independently verified. Every slice must satisfy two opposing constraints at once.
Before you cut a single slice, confirm the charter's and the PRD's Open
questions are resolved (answered inline, or explicitly DEFERRED (non-blocking)
with the user's agreement). If any blocking question remains, stop and resolve it
with the user first, then update the charter/PRD. Slicing freezes the PRD into
contracts; an unanswered question becomes a guess locked inside one. Resolving it
later means re-drafting slices — the drift this harness exists to prevent.
slice.md must give the builder the files to
touch, the existing pattern to follow, the data/API contract, and links to the
PRD section — so the builder never reverse-engineers intent. A slice that
assumes the builder "just knows" will drift.| Bad (unverifiable) | Good (checkable fact) |
|---|---|
| "Login works well" | "POST /login with valid creds returns 200 + a session cookie; with bad creds returns 401" |
| "The list is fast" | "GET /items?limit=50 returns in < 200ms p95 in the load test" |
| "Errors are handled" | "When the upstream returns 500, the UI shows the error state and logs an upstream_error event" |
If the charter's Required tooling / conventions names a skill, generator, or
reference setup a builder must use (e.g. "generate the Gradle build files with the
setup-gradle skill"), do not write the instruction "use skill X" as an
acceptance criterion. A builder can — and will — rationalize its way around an
unverifiable means ("it's just a template, I know the params"), because the harness
only enforces outcomes. Instead:
setup-gradle skill" but "gradle/libs.versions.toml pins versions via the
catalog; settings.gradle.kts repositories point at the internal mirror, not Maven
Central; ./gradlew --offline assemble exits 0." Now a hand-rolled wrong version
fails a gate and gets rejected, regardless of how it was built.setup-conformance gate in config.json
(a grep/test assertion), the setup slice's done-ness is enforced by the engine,
not agent judgment — the strongest form, and it keeps holding as a regression guard
on later slices. In that case the slice's AC can simply point at the gate
("setup-conformance and build are green"). Reserve hand-written ACs for the
judgmental facts a grep can't capture (e.g. "the module layout follows the
reference project"), which the verifier checks by inspection.setup-gradle
skill — it encodes the air-gap mirror, catalog, and plugin set; hand-written
versions fail the offline gate." This removes the "I know the params" escape hatch
without pretending the harness can force a skill invocation (it can't)."required": false in config.json
only as a temporary warn-only measure, and flip it back once the gate can run.slice.md. The builder of a later slice
should be able to assume earlier ones are done.When a slice is ready to build, set frozen: true in contract.yml and
kuru set-status <id> ready. From that moment the definition-of-done and
acceptance criteria are locked. If you discover the scope was wrong:
draft the slice and re-cut it,kuru set-status <id> dropped --note "<why>" — next and the loop
ignore dropped slices, and dropped -> draft resurrects one for a re-write
(same id, so other slices' dependencies on it stay valid).Never let a builder silently change the contract to match what it built — that's the exact drift this harness exists to prevent.
If config.json defines multiple gate targets — one per app/build flavor in the
repo (a gradle service, a pnpm web app) — each slice must say which one it builds,
because that decides which gates run and in which directory. You know this up
front: the charter defined the targets and the PRD says which app each piece of
work touches. Pass it at creation: kuru new-slice "<title>" --target web (or fix
later with kuru set-target <id> <name>). A slice that forgets its target is caught
by kuru doctor and can't be gated. Single-target repos ignore this entirely.
PRD: "Users can save and revisit search filters."
Cut into vertical, session-sized slices:
saved_filters +
POST /filters + a "Save" button that persists the current filter.
AC-1: POST returns 201 with the new id. AC-2: the row exists in the DB with the
owning user_id. AC-3: clicking Save on a filter then reloading shows it in the
list.GET /filters + a dropdown that, when a
saved filter is chosen, applies it to the current search.
AC-1: GET returns only the current user's filters. AC-2: selecting one updates
the results to match the saved query.DELETE /filters/:id + a delete control.
AC-1: DELETE removes only the owner's filter; another user's id returns 403.
AC-2: after delete it's gone from the list and the DB.audit_log row with actor, action, target.Each is vertical, fits a session, and has facts you can check. Create each with
kuru new-slice "<title>", fill slice.md + contract.yml, then mark ready.
npx claudepluginhub ultish/kurukuru --plugin kuruGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.